summaryrefslogtreecommitdiff
path: root/bench
diff options
context:
space:
mode:
authorKornelius Kalnbach <murphy@rubychan.de>2011-09-09 02:05:44 +0200
committerKornelius Kalnbach <murphy@rubychan.de>2011-09-09 02:05:44 +0200
commit7567e6e2f18334d3f0b5b3c6c9659a018be00e9e (patch)
tree18104f93126d0fd3b162ffdc2cadd1da104945ff /bench
parent74b05c9f583669849fded8417a8f5003be3b3c6c (diff)
downloadcoderay-7567e6e2f18334d3f0b5b3c6c9659a018be00e9e.tar.gz
remove obsolete big C example code, to make this a Ruby project on GitHub
Diffstat (limited to 'bench')
-rw-r--r--bench/caching.rb39
-rw-r--r--bench/example.c92649
-rw-r--r--bench/example.cpp13544
-rw-r--r--bench/example.delphi2708
-rw-r--r--bench/example.html169
-rw-r--r--bench/example.json655
-rw-r--r--bench/example.plain201
-rw-r--r--bench/example.rb10070
-rw-r--r--bench/example.rhtml561
-rw-r--r--bench/example.rubyfast10428
-rw-r--r--bench/example.rubylexbin284360 -> 0 bytes
-rw-r--r--bench/example.scheme38
-rw-r--r--bench/example.xhtml376
-rw-r--r--bench/example.xml28137
-rw-r--r--bench/output18
-rw-r--r--bench/strange.c90
-rw-r--r--bench/strange.ruby328
17 files changed, 0 insertions, 160011 deletions
diff --git a/bench/caching.rb b/bench/caching.rb
deleted file mode 100644
index b6c8b66..0000000
--- a/bench/caching.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-require 'coderay'
-require 'benchmark'
-
-N = 1000
-$code = 'snoo Snoo ' * 10
-Benchmark.bm 15 do |bm|
- bm.report 'Loading parts' do
- CodeRay::Scanners.load :ruby
- CodeRay::Encoders.load :div
- end
- bm.report 'CodeRay.encode' do N.times do
- CodeRay.encode($code, :ruby, :div)
- end end
- bm.report 'Direct' do N.times do
- CodeRay::Encoders::Div.new.encode_tokens(
- CodeRay::Scanners::Ruby.new($code).tokenize
- )
- end end
- bm.report 'Encoder cached' do
- encoder = CodeRay::Encoders::Div.new
- N.times do
- encoder.encode $code, :ruby
- end
- end
- bm.report 'Fully cached' do
- scanner = CodeRay::Scanners::Ruby.new('')
- encoder = CodeRay::Encoders::Div.new
- N.times do
- scanner.string = $code
- encoder.encode_tokens scanner.tokens
- end
- end
- bm.report 'CodeRay::Duo' do
- duo = CodeRay::Duo[:ruby, :div]
- N.times do
- duo.encode $code
- end
- end
-end
diff --git a/bench/example.c b/bench/example.c
deleted file mode 100644
index 3a5b4b1..0000000
--- a/bench/example.c
+++ /dev/null
@@ -1,92649 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "codegen.h"
-#include "symboltable.h"
-#include "stringbuffer.h"
-
-extern void yyerror(char* msg);
-
-static stringBuffer* staticVariableBuffer;
-static stringBuffer* classInitBuffer;
-static stringBuffer* currentMethodBuffer;
-static stringBuffer* finishedMethodsBuffer;
-static stringBuffer* mainBuffer;
-
-static int currentMethodBufferIndex;
-static int currentMethodStackSize;
-static int currentMethodStackSizeMax;
-static int currentMethodNumberOfLocals;
-
-static int classInitBufferIndex;
-static int classInitStackSize;
-static int classInitStackSizeMax;
-
-static int labelCounter = 0;
-static int global = 1;
-
-char tempString[MAX_LENGTH_OF_COMMAND];
-
-extern char* className; /* from minako-syntax.y */
-
-/* forward declarations */
-static void increaseStackby(int stackdiff);
-char convertType(int type);
-
-void codegenInit() {
- staticVariableBuffer = newStringBuffer();
- classInitBuffer = newStringBuffer();
- currentMethodBuffer = 0;
- finishedMethodsBuffer = newStringBuffer();
- mainBuffer = newStringBuffer();
-
- stringBufferAppend(mainBuffer, "; ------- Header --------------------------------------------");
- sprintf(tempString, ".class public synchronized %s", className);
- stringBufferAppend(mainBuffer, tempString);
- stringBufferAppend(mainBuffer, ".super java/lang/Object");
- stringBufferAppend(mainBuffer, "; -----------------------------------------------------------");
- stringBufferAppend(mainBuffer, "");
-
- stringBufferAppend(finishedMethodsBuffer, "; ------- Constructor ---------------------------------------");
- stringBufferAppend(finishedMethodsBuffer, ".method public <init>()V");
- stringBufferAppend(finishedMethodsBuffer, "\t.limit stack 1");
- stringBufferAppend(finishedMethodsBuffer, "\t.limit locals 1");
- stringBufferAppend(finishedMethodsBuffer, "\taload_0");
- stringBufferAppend(finishedMethodsBuffer, "\tinvokenonvirtual java/lang/Object/<init>()V");
- stringBufferAppend(finishedMethodsBuffer, "\treturn");
- stringBufferAppend(finishedMethodsBuffer, ".end method");
- stringBufferAppend(finishedMethodsBuffer, "; -----------------------------------------------------------");
- stringBufferAppend(finishedMethodsBuffer, "");
-
- stringBufferAppend(staticVariableBuffer, "; ------- Class Variables -----------------------------------");
-
- stringBufferAppend(classInitBuffer, "; ------- Class Initializer ---------------------------------");
- stringBufferAppend(classInitBuffer, ".method static <clinit>()V");
- classInitBufferIndex = classInitBuffer->numberOfNextElement;
- stringBufferAppend(classInitBuffer, "\t.limit locals 0");
-
-}
-
-void codegenAppendCommand(char* cmd, int stackdiff) {
- char tempString[MAX_LENGTH_OF_COMMAND];
- sprintf(tempString, "\t%s", cmd);
- if (global) stringBufferAppend(classInitBuffer, tempString);
- else stringBufferAppend(currentMethodBuffer, tempString);
- increaseStackby(stackdiff);
-}
-
-void codegenInsertCommand(int address, char* cmd, int stackdiff) {
- char tempString[MAX_LENGTH_OF_COMMAND];
- sprintf(tempString, "\t%s", cmd);
- if (global) stringBufferInsert(classInitBuffer, address, tempString);
- else stringBufferInsert(currentMethodBuffer, address, tempString);
- increaseStackby(stackdiff);
-}
-
-void codegenAppendLabel(int label) {
- char tempString[MAX_LENGTH_OF_COMMAND];
- sprintf(tempString, "Label%d:", label);
- if (global) stringBufferAppend(classInitBuffer, tempString);
- else stringBufferAppend(currentMethodBuffer, tempString);
-}
-
-void codegenAddVariable(char* name, int type) {
- /*fprintf(stderr, "add variable %s(%d) global=%d ", name, convertType(type), global);*/
- if (global) {
- if (type == TYPE_INT) sprintf(tempString, ".field static %s %c", name, 'I');
- else if (type == TYPE_FLOAT) sprintf(tempString, ".field static %s %c", name, 'F');
- else if (type == TYPE_BOOLEAN) sprintf(tempString, ".field static %s %c", name, 'Z');
- else yyerror("compiler-intern error in codegenAddGlobalVariable().\n");
- stringBufferAppend(staticVariableBuffer, tempString);
- }
- else {
- currentMethodNumberOfLocals++;
- }
-}
-
-int codegenGetNextLabel() {
- return labelCounter++;
-}
-
-int codegenGetCurrentAddress() {
- if (global) return classInitBuffer->numberOfNextElement;
- else return currentMethodBuffer->numberOfNextElement;
-}
-
-void codegenEnterFunction(symtabEntry* entry) {
- currentMethodBuffer = newStringBuffer();
- currentMethodStackSize = 0;
- currentMethodStackSizeMax = 0;
- labelCounter = 1;
- global = 0;
-
- if (strcmp(entry->name, "main") == 0) {
- if (entry->idtype != TYPE_VOID) yyerror("main has to be void.\n");
- currentMethodNumberOfLocals = 1;
- symtabInsert(strdup("#main-param#"), TYPE_VOID, CLASS_FUNC);
- stringBufferAppend(currentMethodBuffer, "; ------- Methode ---- void main() --------------------------");
- stringBufferAppend(currentMethodBuffer, ".method public static main([Ljava/lang/String;)V");
- }
- else {
- int i;
- currentMethodNumberOfLocals = entry->paramIndex;
- stringBufferAppend(currentMethodBuffer, "; ------- Methode -------------------------------------------");
- sprintf(tempString, ".method public static %s(", entry->name);
- for (i=entry->paramIndex-1; i>=0; i--) {
- int type = entry->params[i]->idtype;
- tempString[strlen(tempString)+1] = 0;
- tempString[strlen(tempString)] = convertType(type);
- }
- tempString[strlen(tempString)+2] = 0;
- tempString[strlen(tempString)+1] = convertType(entry->idtype);
- tempString[strlen(tempString)] = ')';
- stringBufferAppend(currentMethodBuffer, tempString);
- }
- currentMethodBufferIndex = currentMethodBuffer->numberOfNextElement;
-}
-
-void codegenLeaveFunction() {
- global = 1;
- sprintf(tempString, "\t.limit locals %d", currentMethodNumberOfLocals);
- stringBufferInsert(currentMethodBuffer, currentMethodBufferIndex, tempString);
- sprintf(tempString, "\t.limit stack %d", currentMethodStackSizeMax);
- stringBufferInsert(currentMethodBuffer, currentMethodBufferIndex, tempString);
- stringBufferAppend(currentMethodBuffer, "\treturn");
- stringBufferAppend(currentMethodBuffer, ".end method");
- stringBufferAppend(currentMethodBuffer, "; -----------------------------------------------------------");
- stringBufferAppend(currentMethodBuffer, "");
-
- stringBufferConcatenate(finishedMethodsBuffer, currentMethodBuffer);
-}
-
-
-
-void codegenFinishCode() {
- stringBufferAppend(staticVariableBuffer, "; -----------------------------------------------------------");
- stringBufferAppend(staticVariableBuffer, "");
-
- sprintf(tempString, "\t.limit stack %d", classInitStackSizeMax);
- stringBufferInsert(classInitBuffer, classInitBufferIndex, tempString);
- stringBufferAppend(classInitBuffer, "\treturn");
- stringBufferAppend(classInitBuffer, ".end method");
- stringBufferAppend(classInitBuffer, "; -----------------------------------------------------------");
-
- stringBufferConcatenate(mainBuffer, staticVariableBuffer);
- stringBufferConcatenate(mainBuffer, finishedMethodsBuffer);
- stringBufferConcatenate(mainBuffer, classInitBuffer);
-
- stringBufferPrint(mainBuffer);
-}
-
-static void increaseStackby(int stackdiff) {
- if (global) {
- classInitStackSize += stackdiff;
- if (classInitStackSize > classInitStackSizeMax) classInitStackSizeMax = classInitStackSize;
- }
- else {
- currentMethodStackSize += stackdiff;
- if (currentMethodStackSize > currentMethodStackSizeMax) currentMethodStackSizeMax = currentMethodStackSize;
- }
-}
-
-char convertType(int type) {
- switch(type) {
- case TYPE_VOID: return 'V';
- case TYPE_INT: return 'I';
- case TYPE_FLOAT: return 'F';
- case TYPE_BOOLEAN: return 'Z';
- default: yyerror("compiler-intern error in convertType().\n");
- }
- return 0; /* to avoid compiler-warning */
-}
-
-
-//#include <stdlib.h>
-//#include <stdio.h>
-
-int main() {
- int a = 12, b = 44;
- while (a != b) {
- if (a > b)
- a -= b;
- else
- b -= a;
- }
- printf("%d\n%d", a, 0X0);\
-}
-
-
-/**********************************************************************
-
- array.c -
-
- $Author: matz $
- $Date: 2005/03/04 06:47:45 $
- created at: Fri Aug 6 09:46:12 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 "util.h"
-#include "st.h"
-#include "node.h"
-
-VALUE rb_cArray, rb_cValues;
-
-static ID id_cmp;
-
-#define ARY_DEFAULT_SIZE 16
-
-
-void
-rb_mem_clear(mem, size)
- register VALUE *mem;
- register long size;
-{
- while (size--) {
- *mem++ = Qnil;
- }
-}
-
-static inline void
-memfill(mem, size, val)
- register VALUE *mem;
- register long size;
- register VALUE val;
-{
- while (size--) {
- *mem++ = val;
- }
-}
-
-#define ARY_TMPLOCK FL_USER1
-
-static inline void
-rb_ary_modify_check(ary)
- VALUE ary;
-{
- if (OBJ_FROZEN(ary)) rb_error_frozen("array");
- if (FL_TEST(ary, ARY_TMPLOCK))
- rb_raise(rb_eRuntimeError, "can't modify array during iteration");
- if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't modify array");
-}
-
-static void
-rb_ary_modify(ary)
- VALUE ary;
-{
- VALUE *ptr;
-
- rb_ary_modify_check(ary);
- if (FL_TEST(ary, ELTS_SHARED)) {
- ptr = ALLOC_N(VALUE, RARRAY(ary)->len);
- FL_UNSET(ary, ELTS_SHARED);
- RARRAY(ary)->aux.capa = RARRAY(ary)->len;
- MEMCPY(ptr, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
- RARRAY(ary)->ptr = ptr;
- }
-}
-
-VALUE
-rb_ary_freeze(ary)
- VALUE ary;
-{
- return rb_obj_freeze(ary);
-}
-
-/*
- * call-seq:
- * array.frozen? -> true or false
- *
- * Return <code>true</code> if this array is frozen (or temporarily frozen
- * while being sorted).
- */
-
-static VALUE
-rb_ary_frozen_p(ary)
- VALUE ary;
-{
- if (OBJ_FROZEN(ary)) return Qtrue;
- if (FL_TEST(ary, ARY_TMPLOCK)) return Qtrue;
- return Qfalse;
-}
-
-static VALUE ary_alloc(VALUE);
-static VALUE
-ary_alloc(klass)
- VALUE klass;
-{
- NEWOBJ(ary, struct RArray);
- OBJSETUP(ary, klass, T_ARRAY);
-
- ary->len = 0;
- ary->ptr = 0;
- ary->aux.capa = 0;
-
- return (VALUE)ary;
-}
-
-static VALUE
-ary_new(klass, len)
- VALUE klass;
- long len;
-{
- VALUE ary;
-
- if (len < 0) {
- rb_raise(rb_eArgError, "negative array size (or size too big)");
- }
- if (len > 0 && len * sizeof(VALUE) <= len) {
- rb_raise(rb_eArgError, "array size too big");
- }
- if (len == 0) len++;
-
- ary = ary_alloc(klass);
- RARRAY(ary)->ptr = ALLOC_N(VALUE, len);
- RARRAY(ary)->aux.capa = len;
-
- return ary;
-}
-
-VALUE
-rb_ary_new2(len)
- long len;
-{
- return ary_new(rb_cArray, len);
-}
-
-
-VALUE
-rb_ary_new()
-{
- return rb_ary_new2(ARY_DEFAULT_SIZE);
-}
-
-#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
-
-VALUE
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_ary_new3(long n, ...)
-#else
-rb_ary_new3(n, va_alist)
- long n;
- va_dcl
-#endif
-{
- va_list ar;
- VALUE ary;
- long i;
-
- ary = rb_ary_new2(n);
-
- va_init_list(ar, n);
- for (i=0; i<n; i++) {
- RARRAY(ary)->ptr[i] = va_arg(ar, VALUE);
- }
- va_end(ar);
-
- RARRAY(ary)->len = n;
- return ary;
-}
-
-VALUE
-rb_ary_new4(n, elts)
- long n;
- const VALUE *elts;
-{
- VALUE ary;
-
- ary = rb_ary_new2(n);
- if (n > 0 && elts) {
- MEMCPY(RARRAY(ary)->ptr, elts, VALUE, n);
- }
- RARRAY(ary)->len = n;
-
- return ary;
-}
-
-VALUE
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_values_new(long n, ...)
-#else
-rb_values_new(n, va_alist)
- long n;
- va_dcl
-#endif
-{
- va_list ar;
- VALUE val;
- long i;
-
- val = ary_new(rb_cValues, n);
- va_init_list(ar, n);
- for (i=0; i<n; i++) {
- RARRAY(val)->ptr[i] = va_arg(ar, VALUE);
- }
- va_end(ar);
- RARRAY(val)->len = n;
-
- return val;
-}
-
-VALUE
-rb_values_new2(n, elts)
- long n;
- const VALUE *elts;
-{
- VALUE val;
-
- val = ary_new(rb_cValues, n);
- if (n > 0 && elts) {
- RARRAY(val)->len = n;
- MEMCPY(RARRAY(val)->ptr, elts, VALUE, n);
- }
-
- return val;
-}
-
-static VALUE
-ary_make_shared(ary)
- VALUE ary;
-{
- if (!FL_TEST(ary, ELTS_SHARED)) {
- NEWOBJ(shared, struct RArray);
- OBJSETUP(shared, rb_cArray, T_ARRAY);
-
- shared->len = RARRAY(ary)->len;
- shared->ptr = RARRAY(ary)->ptr;
- shared->aux.capa = RARRAY(ary)->aux.capa;
- RARRAY(ary)->aux.shared = (VALUE)shared;
- FL_SET(ary, ELTS_SHARED);
- OBJ_FREEZE(shared);
- return (VALUE)shared;
- }
- else {
- return RARRAY(ary)->aux.shared;
- }
-}
-
-static VALUE
-ary_shared_array(klass, ary)
- VALUE klass, ary;
-{
- VALUE val = ary_alloc(klass);
-
- ary_make_shared(ary);
- RARRAY(val)->ptr = RARRAY(ary)->ptr;
- RARRAY(val)->len = RARRAY(ary)->len;
- RARRAY(val)->aux.shared = RARRAY(ary)->aux.shared;
- FL_SET(val, ELTS_SHARED);
- return val;
-}
-
-VALUE
-rb_values_from_ary(ary)
- VALUE ary;
-{
- return ary_shared_array(rb_cValues, ary);
-}
-
-VALUE
-rb_ary_from_values(val)
- VALUE val;
-{
- return ary_shared_array(rb_cArray, val);
-}
-
-VALUE
-rb_assoc_new(car, cdr)
- VALUE car, cdr;
-{
- return rb_values_new(2, car, cdr);
-}
-
-static VALUE
-to_ary(ary)
- VALUE ary;
-{
- return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
-}
-
-static VALUE
-to_a(ary)
- VALUE ary;
-{
- return rb_convert_type(ary, T_ARRAY, "Array", "to_a");
-}
-
-VALUE
-rb_check_array_type(ary)
- VALUE ary;
-{
- return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary");
-}
-
-static VALUE rb_ary_replace _((VALUE, VALUE));
-
-/*
- * call-seq:
- * Array.new(size=0, obj=nil)
- * Array.new(array)
- * Array.new(size) {|index| block }
- *
- * Returns a new array. In the first form, the new array is
- * empty. In the second it is created with _size_ copies of _obj_
- * (that is, _size_ references to the same
- * _obj_). The third form creates a copy of the array
- * passed as a parameter (the array is generated by calling
- * to_ary on the parameter). In the last form, an array
- * of the given size is created. Each element in this array is
- * calculated by passing the element's index to the given block and
- * storing the return value.
- *
- * Array.new
- * Array.new(2)
- * Array.new(5, "A")
- *
- * # only one copy of the object is created
- * a = Array.new(2, Hash.new)
- * a[0]['cat'] = 'feline'
- * a
- * a[1]['cat'] = 'Felix'
- * a
- *
- * # here multiple copies are created
- * a = Array.new(2) { Hash.new }
- * a[0]['cat'] = 'feline'
- * a
- *
- * squares = Array.new(5) {|i| i*i}
- * squares
- *
- * copy = Array.new(squares)
- */
-
-static VALUE
-rb_ary_initialize(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- long len;
- VALUE size, val;
-
- if (rb_scan_args(argc, argv, "02", &size, &val) == 0) {
- RARRAY(ary)->len = 0;
- if (rb_block_given_p()) {
- rb_warning("given block not used");
- }
- return ary;
- }
-
- if (argc == 1 && !FIXNUM_P(size)) {
- val = rb_check_array_type(size);
- if (!NIL_P(val)) {
- rb_ary_replace(ary, val);
- return ary;
- }
- }
-
- len = NUM2LONG(size);
- if (len < 0) {
- rb_raise(rb_eArgError, "negative array size");
- }
- if (len > 0 && len * (long)sizeof(VALUE) <= len) {
- rb_raise(rb_eArgError, "array size too big");
- }
- rb_ary_modify(ary);
- if (len > RARRAY(ary)->aux.capa) {
- REALLOC_N(RARRAY(ary)->ptr, VALUE, len);
- RARRAY(ary)->aux.capa = len;
- }
- if (rb_block_given_p()) {
- long i;
-
- if (argc == 2) {
- rb_warn("block supersedes default value argument");
- }
- for (i=0; i<len; i++) {
- rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
- RARRAY(ary)->len = i + 1;
- }
- }
- else {
- memfill(RARRAY(ary)->ptr, len, val);
- RARRAY(ary)->len = len;
- }
-
- return ary;
-}
-
-
-/*
-* Returns a new array populated with the given objects.
-*
-* Array.[]( 1, 'a', /^A/ )
-* Array[ 1, 'a', /^A/ ]
-* [ 1, 'a', /^A/ ]
-*/
-
-static VALUE
-rb_ary_s_create(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE ary = ary_alloc(klass);
-
- if (argc > 0) {
- RARRAY(ary)->ptr = ALLOC_N(VALUE, argc);
- MEMCPY(RARRAY(ary)->ptr, argv, VALUE, argc);
- }
- RARRAY(ary)->len = RARRAY(ary)->aux.capa = argc;
-
- return ary;
-}
-
-void
-rb_ary_store(ary, idx, val)
- VALUE ary;
- long idx;
- VALUE val;
-{
- if (idx < 0) {
- idx += RARRAY(ary)->len;
- if (idx < 0) {
- rb_raise(rb_eIndexError, "index %ld out of array",
- idx - RARRAY(ary)->len);
- }
- }
-
- rb_ary_modify(ary);
- if (idx >= RARRAY(ary)->aux.capa) {
- long new_capa = RARRAY(ary)->aux.capa / 2;
-
- if (new_capa < ARY_DEFAULT_SIZE) {
- new_capa = ARY_DEFAULT_SIZE;
- }
- new_capa += idx;
- if (new_capa * (long)sizeof(VALUE) <= new_capa) {
- rb_raise(rb_eArgError, "index too big");
- }
- REALLOC_N(RARRAY(ary)->ptr, VALUE, new_capa);
- RARRAY(ary)->aux.capa = new_capa;
- }
- if (idx > RARRAY(ary)->len) {
- rb_mem_clear(RARRAY(ary)->ptr + RARRAY(ary)->len,
- idx-RARRAY(ary)->len + 1);
- }
-
- if (idx >= RARRAY(ary)->len) {
- RARRAY(ary)->len = idx + 1;
- }
- RARRAY(ary)->ptr[idx] = val;
-}
-
-static VALUE
-ary_shared_first(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- VALUE nv, result;
- long n;
-
- rb_scan_args(argc, argv, "1", &nv);
- n = NUM2LONG(nv);
- if (n > RARRAY(ary)->len) {
- n = RARRAY(ary)->len;
- }
- else if (n < 0) {
- rb_raise(rb_eArgError, "negative array size");
- }
- result = ary_shared_array(rb_cArray, ary);
- RARRAY(result)->len = n;
- return result;
-}
-
-static VALUE
-ary_shared_last(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- VALUE result = ary_shared_first(argc, argv, ary);
-
- RARRAY(result)->ptr += RARRAY(ary)->len - RARRAY(result)->len;
- return result;
-}
-
-/*
- * call-seq:
- * array << obj -> array
- *
- * Append---Pushes the given object on to the end of this array. This
- * expression returns the array itself, so several appends
- * may be chained together.
- *
- * [ 1, 2 ] << "c" << "d" << [ 3, 4 ]
- * #=> [ 1, 2, "c", "d", [ 3, 4 ] ]
- *
- */
-
-VALUE
-rb_ary_push(ary, item)
- VALUE ary;
- VALUE item;
-{
- rb_ary_store(ary, RARRAY(ary)->len, item);
- return ary;
-}
-
-/*
- * call-seq:
- * array.push(obj, ... ) -> array
- *
- * Append---Pushes the given object(s) on to the end of this array. This
- * expression returns the array itself, so several appends
- * may be chained together.
- *
- * a = [ "a", "b", "c" ]
- * a.push("d", "e", "f")
- * #=> ["a", "b", "c", "d", "e", "f"]
- */
-
-static VALUE
-rb_ary_push_m(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- while (argc--) {
- rb_ary_push(ary, *argv++);
- }
- return ary;
-}
-
-VALUE
-rb_ary_pop(ary)
- VALUE ary;
-{
- rb_ary_modify_check(ary);
- if (RARRAY(ary)->len == 0) return Qnil;
- if (!FL_TEST(ary, ELTS_SHARED) &&
- RARRAY(ary)->len * 2 < RARRAY(ary)->aux.capa &&
- RARRAY(ary)->aux.capa > ARY_DEFAULT_SIZE) {
- RARRAY(ary)->aux.capa = RARRAY(ary)->len * 2;
- REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
- }
- return RARRAY(ary)->ptr[--RARRAY(ary)->len];
-}
-
-/*
- * call-seq:
- * array.pop -> obj or nil
- *
- * Removes the last element from <i>self</i> and returns it, or
- * <code>nil</code> if the array is empty.
- *
- * a = [ "a", "b", "c", "d" ]
- * a.pop #=> "d"
- * a.pop(2) #=> ["b", "c"]
- * a #=> ["a"]
- */
-
-static VALUE
-rb_ary_pop_m(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- VALUE result;
-
- if (argc == 0) {
- return rb_ary_pop(ary);
- }
-
- rb_ary_modify_check(ary);
-
- result = ary_shared_last(argc, argv, ary);
- RARRAY(ary)->len -= RARRAY(result)->len;
- return result;
-}
-
-VALUE
-rb_ary_shift(ary)
- VALUE ary;
-{
- VALUE top;
-
- rb_ary_modify_check(ary);
- if (RARRAY(ary)->len == 0) return Qnil;
- top = RARRAY(ary)->ptr[0];
- ary_make_shared(ary);
- RARRAY(ary)->ptr++; /* shift ptr */
- RARRAY(ary)->len--;
-
- return top;
-}
-
-/*
- * call-seq:
- * array.shift -> obj or nil
- *
- * Returns the first element of <i>self</i> and removes it (shifting all
- * other elements down by one). Returns <code>nil</code> if the array
- * is empty.
- *
- * args = [ "-m", "-q", "filename" ]
- * args.shift #=> "-m"
- * args #=> ["-q", "filename"]
- *
- * args = [ "-m", "-q", "filename" ]
- * args.shift(2) #=> ["-m", "-q"]
- * args #=> ["filename"]
- */
-
-static VALUE
-rb_ary_shift_m(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- VALUE result;
- long n;
-
- if (argc == 0) {
- return rb_ary_shift(ary);
- }
-
- rb_ary_modify_check(ary);
-
- result = ary_shared_first(argc, argv, ary);
- n = RARRAY(result)->len;
- RARRAY(ary)->ptr += n;
- RARRAY(ary)->len -= n;
-
- return result;
-}
-
-VALUE
-rb_ary_unshift(ary, item)
- VALUE ary, item;
-{
- rb_ary_modify(ary);
- if (RARRAY(ary)->len == RARRAY(ary)->aux.capa) {
- long capa_inc = RARRAY(ary)->aux.capa / 2;
- if (capa_inc < ARY_DEFAULT_SIZE) {
- capa_inc = ARY_DEFAULT_SIZE;
- }
- RARRAY(ary)->aux.capa += capa_inc;
- REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
- }
-
- /* sliding items */
- MEMMOVE(RARRAY(ary)->ptr + 1, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
-
- RARRAY(ary)->len++;
- RARRAY(ary)->ptr[0] = item;
-
- return ary;
-}
-
-/*
- * call-seq:
- * array.unshift(obj, ...) -> array
- *
- * Prepends objects to the front of <i>array</i>.
- * other elements up one.
- *
- * a = [ "b", "c", "d" ]
- * a.unshift("a") #=> ["a", "b", "c", "d"]
- * a.unshift(1, 2) #=> [ 1, 2, "a", "b", "c", "d"]
- */
-
-static VALUE
-rb_ary_unshift_m(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- long len = RARRAY(ary)->len;
-
- if (argc == 0) return ary;
-
- /* make rooms by setting the last item */
- rb_ary_store(ary, len + argc - 1, Qnil);
-
- /* sliding items */
- MEMMOVE(RARRAY(ary)->ptr + argc, RARRAY(ary)->ptr, VALUE, len);
- MEMCPY(RARRAY(ary)->ptr, argv, VALUE, argc);
-
- return ary;
-}
-
-/* faster version - use this if you don't need to treat negative offset */
-static inline VALUE
-rb_ary_elt(ary, offset)
- VALUE ary;
- long offset;
-{
- if (RARRAY(ary)->len == 0) return Qnil;
- if (offset < 0 || RARRAY(ary)->len <= offset) {
- return Qnil;
- }
- return RARRAY(ary)->ptr[offset];
-}
-
-VALUE
-rb_ary_entry(ary, offset)
- VALUE ary;
- long offset;
-{
- if (offset < 0) {
- offset += RARRAY(ary)->len;
- }
- return rb_ary_elt(ary, offset);
-}
-
-static VALUE
-rb_ary_subseq(ary, beg, len)
- VALUE ary;
- long beg, len;
-{
- VALUE klass, ary2, shared;
- VALUE *ptr;
-
- if (beg > RARRAY(ary)->len) return Qnil;
- if (beg < 0 || len < 0) return Qnil;
-
- if (beg + len > RARRAY(ary)->len) {
- len = RARRAY(ary)->len - beg;
- if (len < 0)
- len = 0;
- }
- klass = rb_obj_class(ary);
- if (len == 0) return ary_new(klass, 0);
-
- shared = ary_make_shared(ary);
- ptr = RARRAY(ary)->ptr;
- ary2 = ary_alloc(klass);
- RARRAY(ary2)->ptr = ptr + beg;
- RARRAY(ary2)->len = len;
- RARRAY(ary2)->aux.shared = shared;
- FL_SET(ary2, ELTS_SHARED);
-
- return ary2;
-}
-
-/*
- * call-seq:
- * array[index] -> obj or nil
- * array[start, length] -> an_array or nil
- * array[range] -> an_array or nil
- * array.slice(index) -> obj or nil
- * array.slice(start, length) -> an_array or nil
- * array.slice(range) -> an_array or nil
- *
- * Element Reference---Returns the element at _index_,
- * or returns a subarray starting at _start_ and
- * continuing for _length_ elements, or returns a subarray
- * specified by _range_.
- * Negative indices count backward from the end of the
- * array (-1 is the last element). Returns nil if the index
- * (or starting index) are out of range.
- *
- * a = [ "a", "b", "c", "d", "e" ]
- * a[2] + a[0] + a[1] #=> "cab"
- * a[6] #=> nil
- * a[1, 2] #=> [ "b", "c" ]
- * a[1..3] #=> [ "b", "c", "d" ]
- * a[4..7] #=> [ "e" ]
- * a[6..10] #=> nil
- * a[-3, 3] #=> [ "c", "d", "e" ]
- * # special cases
- * a[5] #=> nil
- * a[5, 1] #=> []
- * a[5..10] #=> []
- *
- */
-
-VALUE
-rb_ary_aref(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- VALUE arg;
- long beg, len;
-
- if (argc == 2) {
- beg = NUM2LONG(argv[0]);
- len = NUM2LONG(argv[1]);
- if (beg < 0) {
- beg += RARRAY(ary)->len;
- }
- return rb_ary_subseq(ary, beg, len);
- }
- if (argc != 1) {
- rb_scan_args(argc, argv, "11", 0, 0);
- }
- arg = argv[0];
- /* special case - speeding up */
- if (FIXNUM_P(arg)) {
- return rb_ary_entry(ary, FIX2LONG(arg));
- }
- /* check if idx is Range */
- switch (rb_range_beg_len(arg, &beg, &len, RARRAY(ary)->len, 0)) {
- case Qfalse:
- break;
- case Qnil:
- return Qnil;
- default:
- return rb_ary_subseq(ary, beg, len);
- }
- return rb_ary_entry(ary, NUM2LONG(arg));
-}
-
-/*
- * call-seq:
- * array.at(index) -> obj or nil
- *
- * Returns the element at _index_. A
- * negative index counts from the end of _self_. Returns +nil+
- * if the index is out of range. See also <code>Array#[]</code>.
- * (<code>Array#at</code> is slightly faster than <code>Array#[]</code>,
- * as it does not accept ranges and so on.)
- *
- * a = [ "a", "b", "c", "d", "e" ]
- * a.at(0) #=> "a"
- * a.at(-1) #=> "e"
- */
-
-static VALUE
-rb_ary_at(ary, pos)
- VALUE ary, pos;
-{
- return rb_ary_entry(ary, NUM2LONG(pos));
-}
-
-/*
- * call-seq:
- * array.first -> obj or nil
- * array.first(n) -> an_array
- *
- * Returns the first element of the array. If the array is empty,
- * returns <code>nil</code>.
- *
- * a = [ "q", "r", "s", "t" ]
- * a.first #=> "q"
- * a.first(2) #=> ["q", "r"]
- */
-
-static VALUE
-rb_ary_first(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- if (argc == 0) {
- if (RARRAY(ary)->len == 0) return Qnil;
- return RARRAY(ary)->ptr[0];
- }
- else {
- return ary_shared_first(argc, argv, ary);
- }
-}
-
-/*
- * call-seq:
- * array.last -> obj or nil
- * array.last(n) -> an_array
- *
- * Returns the last element(s) of <i>self</i>. If the array is empty,
- * the first form returns <code>nil</code>.
- *
- * a = [ "w", "x", "y", "z" ]
- * a.last #=> "z"
- * a.last(2) #=> ["y", "z"]
- */
-
-static VALUE
-rb_ary_last(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- if (argc == 0) {
- if (RARRAY(ary)->len == 0) return Qnil;
- return RARRAY(ary)->ptr[RARRAY(ary)->len-1];
- }
- else {
- return ary_shared_last(argc, argv, ary);
- }
-}
-
-/*
- * call-seq:
- * array.fetch(index) -> obj
- * array.fetch(index, default ) -> obj
- * array.fetch(index) {|index| block } -> obj
- *
- * Tries to return the element at position <i>index</i>. If the index
- * lies outside the array, the first form throws an
- * <code>IndexError</code> exception, the second form returns
- * <i>default</i>, and the third form returns the value of invoking
- * the block, passing in the index. Negative values of <i>index</i>
- * count from the end of the array.
- *
- * a = [ 11, 22, 33, 44 ]
- * a.fetch(1) #=> 22
- * a.fetch(-1) #=> 44
- * a.fetch(4, 'cat') #=> "cat"
- * a.fetch(4) { |i| i*i } #=> 16
- */
-
-static VALUE
-rb_ary_fetch(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- VALUE pos, ifnone;
- long block_given;
- long idx;
-
- rb_scan_args(argc, argv, "11", &pos, &ifnone);
- block_given = rb_block_given_p();
- if (block_given && argc == 2) {
- rb_warn("block supersedes default value argument");
- }
- idx = NUM2LONG(pos);
-
- if (idx < 0) {
- idx += RARRAY(ary)->len;
- }
- if (idx < 0 || RARRAY(ary)->len <= idx) {
- if (block_given) return rb_yield(pos);
- if (argc == 1) {
- rb_raise(rb_eIndexError, "index %ld out of array", idx);
- }
- return ifnone;
- }
- return RARRAY(ary)->ptr[idx];
-}
-
-/*
- * call-seq:
- * array.index(obj) -> int or nil
- * array.index {|item| block} -> int or nil
- *
- * Returns the index of the first object in <i>self</i> such that is
- * <code>==</code> to <i>obj</i>. If a block is given instead of an
- * argument, returns first object for which <em>block</em> is true.
- * Returns <code>nil</code> if no match is found.
- *
- * a = [ "a", "b", "c" ]
- * a.index("b") #=> 1
- * a.index("z") #=> nil
- * a.index{|x|x=="b"} #=> 1
- */
-
-static VALUE
-rb_ary_index(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- VALUE val;
- long i;
-
- if (rb_scan_args(argc, argv, "01", &val) == 0) {
- for (i=0; i<RARRAY(ary)->len; i++) {
- if (RTEST(rb_yield(RARRAY(ary)->ptr[i]))) {
- return LONG2NUM(i);
- }
- }
- }
- else {
- for (i=0; i<RARRAY(ary)->len; i++) {
- if (rb_equal(RARRAY(ary)->ptr[i], val))
- return LONG2NUM(i);
- }
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * array.rindex(obj) -> int or nil
- *
- * Returns the index of the last object in <i>array</i>
- * <code>==</code> to <i>obj</i>. If a block is given instead of an
- * argument, returns first object for which <em>block</em> is
- * true. Returns <code>nil</code> if no match is found.
- *
- * a = [ "a", "b", "b", "b", "c" ]
- * a.rindex("b") #=> 3
- * a.rindex("z") #=> nil
- * a.rindex{|x|x=="b"} #=> 3
- */
-
-static VALUE
-rb_ary_rindex(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- VALUE val;
- long i = RARRAY(ary)->len;
-
- if (rb_scan_args(argc, argv, "01", &val) == 0) {
- while (i--) {
- if (RTEST(rb_yield(RARRAY(ary)->ptr[i])))
- return LONG2NUM(i);
- if (i > RARRAY(ary)->len) {
- i = RARRAY(ary)->len;
- }
- }
- }
- else {
- while (i--) {
- if (rb_equal(RARRAY(ary)->ptr[i], val))
- return LONG2NUM(i);
- if (i > RARRAY(ary)->len) {
- i = RARRAY(ary)->len;
- }
- }
- }
- return Qnil;
-}
-
-VALUE
-rb_ary_to_ary(obj)
- VALUE obj;
-{
- if (TYPE(obj) == T_ARRAY) {
- return obj;
- }
- if (rb_respond_to(obj, rb_intern("to_ary"))) {
- return to_ary(obj);
- }
- return rb_ary_new3(1, obj);
-}
-
-static void
-rb_ary_splice(ary, beg, len, rpl)
- VALUE ary;
- long beg, len;
- VALUE rpl;
-{
- long rlen;
-
- if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
- if (beg < 0) {
- beg += RARRAY(ary)->len;
- if (beg < 0) {
- beg -= RARRAY(ary)->len;
- rb_raise(rb_eIndexError, "index %ld out of array", beg);
- }
- }
- if (beg + len > RARRAY(ary)->len) {
- len = RARRAY(ary)->len - beg;
- }
-
- if (rpl == Qundef) {
- rlen = 0;
- }
- else {
- rpl = rb_ary_to_ary(rpl);
- rlen = RARRAY(rpl)->len;
- }
- rb_ary_modify(ary);
-
- if (beg >= RARRAY(ary)->len) {
- len = beg + rlen;
- if (len >= RARRAY(ary)->aux.capa) {
- REALLOC_N(RARRAY(ary)->ptr, VALUE, len);
- RARRAY(ary)->aux.capa = len;
- }
- rb_mem_clear(RARRAY(ary)->ptr + RARRAY(ary)->len, beg - RARRAY(ary)->len);
- if (rlen > 0) {
- MEMCPY(RARRAY(ary)->ptr + beg, RARRAY(rpl)->ptr, VALUE, rlen);
- }
- RARRAY(ary)->len = len;
- }
- else {
- long alen;
-
- if (beg + len > RARRAY(ary)->len) {
- len = RARRAY(ary)->len - beg;
- }
-
- alen = RARRAY(ary)->len + rlen - len;
- if (alen >= RARRAY(ary)->aux.capa) {
- REALLOC_N(RARRAY(ary)->ptr, VALUE, alen);
- RARRAY(ary)->aux.capa = alen;
- }
-
- if (len != rlen) {
- MEMMOVE(RARRAY(ary)->ptr + beg + rlen, RARRAY(ary)->ptr + beg + len,
- VALUE, RARRAY(ary)->len - (beg + len));
- RARRAY(ary)->len = alen;
- }
- if (rlen > 0) {
- MEMMOVE(RARRAY(ary)->ptr + beg, RARRAY(rpl)->ptr, VALUE, rlen);
- }
- }
-}
-
-/*
- * call-seq:
- * array[index] = obj -> obj
- * array[start, length] = obj or an_array or nil -> obj or an_array or nil
- * array[range] = obj or an_array or nil -> obj or an_array or nil
- *
- * Element Assignment---Sets the element at _index_,
- * or replaces a subarray starting at _start_ and
- * continuing for _length_ elements, or replaces a subarray
- * specified by _range_. If indices are greater than
- * the current capacity of the array, the array grows
- * automatically. A negative indices will count backward
- * from the end of the array. Inserts elements if _length_ is
- * zero. An +IndexError+ is raised if a negative index points
- * past the beginning of the array. See also
- * <code>Array#push</code>, and <code>Array#unshift</code>.
- *
- * a = Array.new
- * a[4] = "4"; #=> [nil, nil, nil, nil, "4"]
- * a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
- * a[1..2] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"]
- * a[0, 2] = "?" #=> ["?", 2, nil, "4"]
- * a[0..2] = "A" #=> ["A", "4"]
- * a[-1] = "Z" #=> ["A", "Z"]
- * a[1..-1] = nil #=> ["A", nil]
- * a[1..-1] = [] #=> ["A"]
- */
-
-static VALUE
-rb_ary_aset(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- long offset, beg, len;
-
- if (argc == 3) {
- rb_ary_splice(ary, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
- return argv[2];
- }
- if (argc != 2) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
- }
- if (FIXNUM_P(argv[0])) {
- offset = FIX2LONG(argv[0]);
- goto fixnum;
- }
- if (rb_range_beg_len(argv[0], &beg, &len, RARRAY(ary)->len, 1)) {
- /* check if idx is Range */
- rb_ary_splice(ary, beg, len, argv[1]);
- return argv[1];
- }
-
- offset = NUM2LONG(argv[0]);
-fixnum:
- rb_ary_store(ary, offset, argv[1]);
- return argv[1];
-}
-
-/*
- * call-seq:
- * array.insert(index, obj...) -> array
- *
- * Inserts the given values before the element with the given index
- * (which may be negative).
- *
- * a = %w{ a b c d }
- * a.insert(2, 99) #=> ["a", "b", 99, "c", "d"]
- * a.insert(-2, 1, 2, 3) #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
- */
-
-static VALUE
-rb_ary_insert(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- long pos;
-
- if (argc < 1) {
- rb_raise(rb_eArgError, "wrong number of arguments (at least 1)");
- }
- pos = NUM2LONG(argv[0]);
- if (pos == -1) {
- pos = RARRAY(ary)->len;
- }
- else if (pos < 0) {
- pos++;
- }
-
- if (argc == 1) return ary;
- rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
- return ary;
-}
-
-/*
- * call-seq:
- * array.each {|item| block } -> array
- *
- * Calls <i>block</i> once for each element in <i>self</i>, passing that
- * element as a parameter.
- *
- * a = [ "a", "b", "c" ]
- * a.each {|x| print x, " -- " }
- *
- * produces:
- *
- * a -- b -- c --
- */
-
-VALUE
-rb_ary_each(ary)
- VALUE ary;
-{
- long i;
-
- for (i=0; i<RARRAY(ary)->len; i++) {
- rb_yield(RARRAY(ary)->ptr[i]);
- }
- return ary;
-}
-
-/*
- * call-seq:
- * array.each_index {|index| block } -> array
- *
- * Same as <code>Array#each</code>, but passes the index of the element
- * instead of the element itself.
- *
- * a = [ "a", "b", "c" ]
- * a.each_index {|x| print x, " -- " }
- *
- * produces:
- *
- * 0 -- 1 -- 2 --
- */
-
-static VALUE
-rb_ary_each_index(ary)
- VALUE ary;
-{
- long i;
-
- for (i=0; i<RARRAY(ary)->len; i++) {
- rb_yield(LONG2NUM(i));
- }
- return ary;
-}
-
-/*
- * call-seq:
- * array.reverse_each {|item| block }
- *
- * Same as <code>Array#each</code>, but traverses <i>self</i> in reverse
- * order.
- *
- * a = [ "a", "b", "c" ]
- * a.reverse_each {|x| print x, " " }
- *
- * produces:
- *
- * c b a
- */
-
-static VALUE
-rb_ary_reverse_each(ary)
- VALUE ary;
-{
- long len = RARRAY(ary)->len;
-
- while (len--) {
- rb_yield(RARRAY(ary)->ptr[len]);
- if (RARRAY(ary)->len < len) {
- len = RARRAY(ary)->len;
- }
- }
- return ary;
-}
-
-/*
- * call-seq:
- * array.length -> int
- *
- * Returns the number of elements in <i>self</i>. May be zero.
- *
- * [ 1, 2, 3, 4, 5 ].length #=> 5
- */
-
-static VALUE
-rb_ary_length(ary)
- VALUE ary;
-{
- return LONG2NUM(RARRAY(ary)->len);
-}
-
-/*
- * call-seq:
- * array.empty? -> true or false
- *
- * Returns <code>true</code> if <i>self</i> array contains no elements.
- *
- * [].empty? #=> true
- */
-
-static VALUE
-rb_ary_empty_p(ary)
- VALUE ary;
-{
- if (RARRAY(ary)->len == 0)
- return Qtrue;
- return Qfalse;
-}
-
-VALUE
-rb_ary_dup(ary)
- VALUE ary;
-{
- VALUE dup = rb_ary_new2(RARRAY(ary)->len);
-
- DUPSETUP(dup, ary);
- MEMCPY(RARRAY(dup)->ptr, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
- RARRAY(dup)->len = RARRAY(ary)->len;
- return dup;
-}
-
-extern VALUE rb_output_fs;
-
-static VALUE
-recursive_join(ary, arg, recur)
- VALUE ary;
- VALUE *arg;
- int recur;
-{
- if (recur) {
- return rb_str_new2("[...]");
- }
- return rb_ary_join(arg[0], arg[1]);
-}
-
-VALUE
-rb_ary_join(ary, sep)
- VALUE ary, sep;
-{
- long len = 1, i;
- int taint = Qfalse;
- VALUE result, tmp;
-
- if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
- if (OBJ_TAINTED(ary) || OBJ_TAINTED(sep)) taint = Qtrue;
-
- for (i=0; i<RARRAY(ary)->len; i++) {
- tmp = rb_check_string_type(RARRAY(ary)->ptr[i]);
- len += NIL_P(tmp) ? 10 : RSTRING(tmp)->len;
- }
- if (!NIL_P(sep)) {
- StringValue(sep);
- 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(recursive_join, ary, (VALUE)args);
- }
- break;
- default:
- tmp = rb_obj_as_string(tmp);
- }
- if (i > 0 && !NIL_P(sep))
- rb_str_buf_append(result, sep);
- rb_str_buf_append(result, tmp);
- if (OBJ_TAINTED(tmp)) taint = Qtrue;
- }
-
- if (taint) OBJ_TAINT(result);
- return result;
-}
-
-/*
- * call-seq:
- * array.join(sep=$,) -> str
- *
- * Returns a string created by converting each element of the array to
- * a string, separated by <i>sep</i>.
- *
- * [ "a", "b", "c" ].join #=> "abc"
- * [ "a", "b", "c" ].join("-") #=> "a-b-c"
- */
-
-static VALUE
-rb_ary_join_m(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- VALUE sep;
-
- rb_scan_args(argc, argv, "01", &sep);
- if (NIL_P(sep)) sep = rb_output_fs;
-
- return rb_ary_join(ary, sep);
-}
-
-/*
- * call-seq:
- * array.to_s -> string
- *
- * Returns _self_<code>.join</code>.
- *
- * [ "a", "e", "i", "o" ].to_s #=> "aeio"
- *
- */
-
-VALUE
-rb_ary_to_s(ary)
- VALUE ary;
-{
- if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
-
- return rb_ary_join(ary, rb_output_fs);
-}
-
-static VALUE
-inspect_ary(ary, dummy, recur)
- VALUE ary;
- VALUE dummy;
- int recur;
-{
- int tainted = OBJ_TAINTED(ary);
- long i;
- VALUE s, str;
-
- if (recur) return rb_tainted_str_new2("[...]");
- str = rb_str_buf_new2("[");
- for (i=0; i<RARRAY(ary)->len; i++) {
- s = rb_inspect(RARRAY(ary)->ptr[i]);
- if (OBJ_TAINTED(s)) tainted = Qtrue;
- if (i > 0) rb_str_buf_cat2(str, ", ");
- rb_str_buf_append(str, s);
- }
- rb_str_buf_cat2(str, "]");
- if (tainted) OBJ_TAINT(str);
- return str;
-}
-
-/*
- * call-seq:
- * array.inspect -> string
- *
- * Create a printable version of <i>array</i>.
- */
-
-static VALUE
-rb_ary_inspect(ary)
- VALUE ary;
-{
- if (RARRAY(ary)->len == 0) return rb_str_new2("[]");
- return rb_exec_recursive(inspect_ary, ary, 0);
-}
-
-/*
- * call-seq:
- * array.to_a -> array
- *
- * Returns _self_. If called on a subclass of Array, converts
- * the receiver to an Array object.
- */
-
-static VALUE
-rb_ary_to_a(ary)
- VALUE ary;
-{
- if (rb_obj_class(ary) != rb_cArray) {
- VALUE dup = rb_ary_new2(RARRAY(ary)->len);
- rb_ary_replace(dup, ary);
- return dup;
- }
- return ary;
-}
-
-/*
- * call-seq:
- * array.to_ary -> array
- *
- * Returns _self_.
- */
-
-static VALUE
-rb_ary_to_ary_m(ary)
- VALUE ary;
-{
- return ary;
-}
-
-VALUE
-rb_ary_reverse(ary)
- VALUE ary;
-{
- VALUE *p1, *p2;
- VALUE tmp;
-
- rb_ary_modify(ary);
- if (RARRAY(ary)->len > 1) {
- p1 = RARRAY(ary)->ptr;
- p2 = p1 + RARRAY(ary)->len - 1; /* points last item */
-
- while (p1 < p2) {
- tmp = *p1;
- *p1++ = *p2;
- *p2-- = tmp;
- }
- }
- return ary;
-}
-
-/*
- * call-seq:
- * array.reverse! -> array
- *
- * Reverses _self_ in place.
- *
- * a = [ "a", "b", "c" ]
- * a.reverse! #=> ["c", "b", "a"]
- * a #=> ["c", "b", "a"]
- */
-
-static VALUE
-rb_ary_reverse_bang(ary)
- VALUE ary;
-{
- return rb_ary_reverse(ary);
-}
-
-/*
- * call-seq:
- * array.reverse -> an_array
- *
- * Returns a new array containing <i>self</i>'s elements in reverse order.
- *
- * [ "a", "b", "c" ].reverse #=> ["c", "b", "a"]
- * [ 1 ].reverse #=> [1]
- */
-
-static VALUE
-rb_ary_reverse_m(ary)
- VALUE ary;
-{
- return rb_ary_reverse(rb_ary_dup(ary));
-}
-
-struct ary_sort_data {
- VALUE ary;
- VALUE *ptr;
- long len;
-};
-
-static void
-ary_sort_check(data)
- struct ary_sort_data *data;
-{
- if (RARRAY(data->ary)->ptr != data->ptr || RARRAY(data->ary)->len != data->len) {
- rb_raise(rb_eRuntimeError, "array modified during sort");
- }
-}
-
-static int
-sort_1(a, b, data)
- VALUE *a, *b;
- struct ary_sort_data *data;
-{
- VALUE retval = rb_yield_values(2, *a, *b);
- int n;
-
- n = rb_cmpint(retval, *a, *b);
- ary_sort_check(data);
- return n;
-}
-
-static int
-sort_2(ap, bp, data)
- VALUE *ap, *bp;
- struct ary_sort_data *data;
-{
- VALUE retval;
- VALUE a = *ap, b = *bp;
- int n;
-
- if (FIXNUM_P(a) && FIXNUM_P(b)) {
- if ((long)a > (long)b) return 1;
- if ((long)a < (long)b) return -1;
- return 0;
- }
- if (TYPE(a) == T_STRING && TYPE(b) == T_STRING) {
- return rb_str_cmp(a, b);
- }
-
- retval = rb_funcall(a, id_cmp, 1, b);
- n = rb_cmpint(retval, a, b);
- ary_sort_check(data);
-
- return n;
-}
-
-static VALUE
-sort_internal(ary)
- VALUE ary;
-{
- struct ary_sort_data data;
-
- data.ary = ary;
- data.ptr = RARRAY(ary)->ptr; data.len = RARRAY(ary)->len;
- qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),
- rb_block_given_p()?sort_1:sort_2, &data);
- return ary;
-}
-
-static VALUE
-sort_unlock(ary)
- VALUE ary;
-{
- FL_UNSET(ary, ARY_TMPLOCK);
- return ary;
-}
-
-/*
- * call-seq:
- * array.sort! -> array
- * array.sort! {| a,b | block } -> array
- *
- * Sorts _self_. Comparisons for
- * the sort will be done using the <code><=></code> operator or using
- * an optional code block. The block implements a comparison between
- * <i>a</i> and <i>b</i>, returning -1, 0, or +1. See also
- * <code>Enumerable#sort_by</code>.
- *
- * a = [ "d", "a", "e", "c", "b" ]
- * a.sort #=> ["a", "b", "c", "d", "e"]
- * a.sort {|x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
- */
-
-VALUE
-rb_ary_sort_bang(ary)
- VALUE ary;
-{
- rb_ary_modify(ary);
- if (RARRAY(ary)->len > 1) {
- FL_SET(ary, ARY_TMPLOCK); /* prohibit modification during sort */
- rb_ensure(sort_internal, ary, sort_unlock, ary);
- }
- return ary;
-}
-
-/*
- * call-seq:
- * array.sort -> an_array
- * array.sort {| a,b | block } -> an_array
- *
- * Returns a new array created by sorting <i>self</i>. Comparisons for
- * the sort will be done using the <code><=></code> operator or using
- * an optional code block. The block implements a comparison between
- * <i>a</i> and <i>b</i>, returning -1, 0, or +1. See also
- * <code>Enumerable#sort_by</code>.
- *
- * a = [ "d", "a", "e", "c", "b" ]
- * a.sort #=> ["a", "b", "c", "d", "e"]
- * a.sort {|x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
- */
-
-VALUE
-rb_ary_sort(ary)
- VALUE ary;
-{
- ary = rb_ary_dup(ary);
- rb_ary_sort_bang(ary);
- return ary;
-}
-
-/*
- * call-seq:
- * array.collect {|item| block } -> an_array
- * array.map {|item| block } -> an_array
- *
- * Invokes <i>block</i> once for each element of <i>self</i>. Creates a
- * new array containing the values returned by the block.
- * See also <code>Enumerable#collect</code>.
- *
- * a = [ "a", "b", "c", "d" ]
- * a.collect {|x| x + "!" } #=> ["a!", "b!", "c!", "d!"]
- * a #=> ["a", "b", "c", "d"]
- */
-
-static VALUE
-rb_ary_collect(ary)
- VALUE ary;
-{
- long i;
- VALUE collect;
-
- if (!rb_block_given_p()) {
- return rb_ary_new4(RARRAY(ary)->len, RARRAY(ary)->ptr);
- }
-
- collect = rb_ary_new2(RARRAY(ary)->len);
- for (i = 0; i < RARRAY(ary)->len; i++) {
- rb_ary_push(collect, rb_yield(RARRAY(ary)->ptr[i]));
- }
- return collect;
-}
-
-/*
- * call-seq:
- * array.collect! {|item| block } -> array
- * array.map! {|item| block } -> array
- *
- * Invokes the block once for each element of _self_, replacing the
- * element with the value returned by _block_.
- * See also <code>Enumerable#collect</code>.
- *
- * a = [ "a", "b", "c", "d" ]
- * a.collect! {|x| x + "!" }
- * a #=> [ "a!", "b!", "c!", "d!" ]
- */
-
-static VALUE
-rb_ary_collect_bang(ary)
- VALUE ary;
-{
- long i;
-
- rb_ary_modify(ary);
- for (i = 0; i < RARRAY(ary)->len; i++) {
- rb_ary_store(ary, i, rb_yield(RARRAY(ary)->ptr[i]));
- }
- return ary;
-}
-
-VALUE
-rb_get_values_at(obj, olen, argc, argv, func)
- VALUE obj;
- long olen;
- int argc;
- VALUE *argv;
- VALUE (*func) _((VALUE,long));
-{
- VALUE result = rb_ary_new2(argc);
- long beg, len, i, j;
-
- for (i=0; i<argc; i++) {
- if (FIXNUM_P(argv[i])) {
- rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
- continue;
- }
- /* check if idx is Range */
- switch (rb_range_beg_len(argv[i], &beg, &len, olen, 0)) {
- case Qfalse:
- break;
- case Qnil:
- continue;
- default:
- for (j=0; j<len; j++) {
- rb_ary_push(result, (*func)(obj, j+beg));
- }
- continue;
- }
- rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
- }
- return result;
-}
-
-/*
- * call-seq:
- * array.values_at(selector,... ) -> an_array
- *
- * Returns an array containing the elements in
- * _self_ corresponding to the given selector(s). The selectors
- * may be either integer indices or ranges.
- * See also <code>Array#select</code>.
- *
- * a = %w{ a b c d e f }
- * a.values_at(1, 3, 5)
- * a.values_at(1, 3, 5, 7)
- * a.values_at(-1, -3, -5, -7)
- * a.values_at(1..3, 2...5)
- */
-
-static VALUE
-rb_ary_values_at(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- return rb_get_values_at(ary, RARRAY(ary)->len, argc, argv, rb_ary_entry);
-}
-
-/*
- * call-seq:
- * array.select {|item| block } -> an_array
- *
- * Invokes the block passing in successive elements from <i>array</i>,
- * returning an array containing those elements for which the block
- * returns a true value (equivalent to <code>Enumerable#select</code>).
- *
- * a = %w{ a b c d e f }
- * a.select {|v| v =~ /[aeiou]/} #=> ["a", "e"]
- */
-
-static VALUE
-rb_ary_select(ary)
- VALUE ary;
-{
- VALUE result;
- long i;
-
- result = rb_ary_new2(RARRAY(ary)->len);
- for (i = 0; i < RARRAY(ary)->len; i++) {
- if (RTEST(rb_yield(RARRAY(ary)->ptr[i]))) {
- rb_ary_push(result, rb_ary_elt(ary, i));
- }
- }
- return result;
-}
-
-/*
- * call-seq:
- * array.delete(obj) -> obj or nil
- * array.delete(obj) { block } -> obj or nil
- *
- * Deletes items from <i>self</i> that are equal to <i>obj</i>. If
- * the item is not found, returns <code>nil</code>. If the optional
- * code block is given, returns the result of <i>block</i> if the item
- * is not found.
- *
- * a = [ "a", "b", "b", "b", "c" ]
- * a.delete("b") #=> "b"
- * a #=> ["a", "c"]
- * a.delete("z") #=> nil
- * a.delete("z") { "not found" } #=> "not found"
- */
-
-VALUE
-rb_ary_delete(ary, item)
- VALUE ary;
- VALUE item;
-{
- long i1, i2;
-
- for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
- VALUE e = RARRAY(ary)->ptr[i1];
-
- if (rb_equal(e, item)) continue;
- if (i1 != i2) {
- rb_ary_store(ary, i2, e);
- }
- i2++;
- }
- if (RARRAY(ary)->len == i2) {
- if (rb_block_given_p()) {
- return rb_yield(item);
- }
- return Qnil;
- }
-
- rb_ary_modify(ary);
- if (RARRAY(ary)->len > i2) {
- RARRAY(ary)->len = i2;
- if (i2 * 2 < RARRAY(ary)->aux.capa &&
- RARRAY(ary)->aux.capa > ARY_DEFAULT_SIZE) {
- REALLOC_N(RARRAY(ary)->ptr, VALUE, i2 * 2);
- RARRAY(ary)->aux.capa = i2 * 2;
- }
- }
-
- return item;
-}
-
-VALUE
-rb_ary_delete_at(ary, pos)
- VALUE ary;
- long pos;
-{
- long i, len = RARRAY(ary)->len;
- VALUE del;
-
- if (pos >= len) return Qnil;
- if (pos < 0) {
- pos += len;
- if (pos < 0) return Qnil;
- }
-
- rb_ary_modify(ary);
- del = RARRAY(ary)->ptr[pos];
- for (i = pos + 1; i < len; i++, pos++) {
- RARRAY(ary)->ptr[pos] = RARRAY(ary)->ptr[i];
- }
- RARRAY(ary)->len = pos;
-
- return del;
-}
-
-/*
- * call-seq:
- * array.delete_at(index) -> obj or nil
- *
- * Deletes the element at the specified index, returning that element,
- * or <code>nil</code> if the index is out of range. See also
- * <code>Array#slice!</code>.
- *
- * a = %w( ant bat cat dog )
- * a.delete_at(2) #=> "cat"
- * a #=> ["ant", "bat", "dog"]
- * a.delete_at(99) #=> nil
- */
-
-static VALUE
-rb_ary_delete_at_m(ary, pos)
- VALUE ary, pos;
-{
- return rb_ary_delete_at(ary, NUM2LONG(pos));
-}
-
-/*
- * call-seq:
- * array.slice!(index) -> obj or nil
- * array.slice!(start, length) -> sub_array or nil
- * array.slice!(range) -> sub_array or nil
- *
- * Deletes the element(s) given by an index (optionally with a length)
- * or by a range. Returns the deleted object, subarray, or
- * <code>nil</code> if the index is out of range. Equivalent to:
- *
- * def slice!(*args)
- * result = self[*args]
- * self[*args] = nil
- * result
- * end
- *
- * a = [ "a", "b", "c" ]
- * a.slice!(1) #=> "b"
- * a #=> ["a", "c"]
- * a.slice!(-1) #=> "c"
- * a #=> ["a"]
- * a.slice!(100) #=> nil
- * a #=> ["a"]
- */
-
-static VALUE
-rb_ary_slice_bang(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- VALUE arg1, arg2;
- long pos, len;
-
- if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
- pos = NUM2LONG(arg1);
- len = NUM2LONG(arg2);
- delete_pos_len:
- if (pos < 0) {
- pos = RARRAY(ary)->len + pos;
- }
- arg2 = rb_ary_subseq(ary, pos, len);
- rb_ary_splice(ary, pos, len, Qundef); /* Qnil/rb_ary_new2(0) */
- return arg2;
- }
-
- if (!FIXNUM_P(arg1) && rb_range_beg_len(arg1, &pos, &len, RARRAY(ary)->len, 1)) {
- goto delete_pos_len;
- }
-
- return rb_ary_delete_at(ary, NUM2LONG(arg1));
-}
-
-/*
- * call-seq:
- * array.reject! {|item| block } -> array or nil
- *
- * Equivalent to <code>Array#delete_if</code>, deleting elements from
- * _self_ for which the block evaluates to true, but returns
- * <code>nil</code> if no changes were made. Also see
- * <code>Enumerable#reject</code>.
- */
-
-static VALUE
-rb_ary_reject_bang(ary)
- VALUE ary;
-{
- long i1, i2;
-
- rb_ary_modify(ary);
- for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
- VALUE v = RARRAY(ary)->ptr[i1];
- if (RTEST(rb_yield(v))) continue;
- if (i1 != i2) {
- rb_ary_store(ary, i2, v);
- }
- i2++;
- }
- if (RARRAY(ary)->len == i2) return Qnil;
- if (i2 < RARRAY(ary)->len)
- RARRAY(ary)->len = i2;
-
- return ary;
-}
-
-/*
- * call-seq:
- * array.reject {|item| block } -> an_array
- *
- * Returns a new array containing the items in _self_
- * for which the block is not true.
- */
-
-static VALUE
-rb_ary_reject(ary)
- VALUE ary;
-{
- ary = rb_ary_dup(ary);
- rb_ary_reject_bang(ary);
- return ary;
-}
-
-/*
- * call-seq:
- * array.delete_if {|item| block } -> array
- *
- * Deletes every element of <i>self</i> for which <i>block</i> evaluates
- * to <code>true</code>.
- *
- * a = [ "a", "b", "c" ]
- * a.delete_if {|x| x >= "b" } #=> ["a"]
- */
-
-static VALUE
-rb_ary_delete_if(ary)
- VALUE ary;
-{
- rb_ary_reject_bang(ary);
- return ary;
-}
-
-/*
- * call-seq:
- * array.zip(arg, ...) -> an_array
- * array.zip(arg, ...) {| arr | block } -> nil
- *
- * Converts any arguments to arrays, then merges elements of
- * <i>self</i> with corresponding elements from each argument. This
- * generates a sequence of <code>self.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>enumObj.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,2,3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
- * [1,2].zip(a,b) #=> [[1, 4, 7], [2, 5, 8]]
- * a.zip([1,2],[8]) #=> [[4,1,8], [5,2,nil], [6,nil,nil]]
- */
-
-static VALUE
-rb_ary_zip(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- int i, j;
- long len;
- VALUE result;
-
- for (i=0; i<argc; i++) {
- argv[i] = to_a(argv[i]);
- }
- if (rb_block_given_p()) {
- for (i=0; i<RARRAY(ary)->len; i++) {
- VALUE tmp = rb_ary_new2(argc+1);
-
- rb_ary_push(tmp, rb_ary_elt(ary, i));
- for (j=0; j<argc; j++) {
- rb_ary_push(tmp, rb_ary_elt(argv[j], i));
- }
- rb_yield(tmp);
- }
- return Qnil;
- }
- len = RARRAY(ary)->len;
- result = rb_ary_new2(len);
- for (i=0; i<len; i++) {
- VALUE tmp = rb_ary_new2(argc+1);
-
- rb_ary_push(tmp, rb_ary_elt(ary, i));
- for (j=0; j<argc; j++) {
- rb_ary_push(tmp, rb_ary_elt(argv[j], i));
- }
- rb_ary_push(result, tmp);
- }
- return result;
-}
-
-/*
- * call-seq:
- * array.transpose -> an_array
- *
- * Assumes that <i>self</i> is an array of arrays and transposes the
- * rows and columns.
- *
- * a = [[1,2], [3,4], [5,6]]
- * a.transpose #=> [[1, 3, 5], [2, 4, 6]]
- */
-
-static VALUE
-rb_ary_transpose(ary)
- VALUE ary;
-{
- long elen = -1, alen, i, j;
- VALUE tmp, result = 0;
-
- alen = RARRAY(ary)->len;
- if (alen == 0) return rb_ary_dup(ary);
- for (i=0; i<alen; i++) {
- tmp = to_ary(rb_ary_elt(ary, i));
- if (elen < 0) { /* first element */
- elen = RARRAY(tmp)->len;
- result = rb_ary_new2(elen);
- for (j=0; j<elen; j++) {
- rb_ary_store(result, j, rb_ary_new2(alen));
- }
- }
- else if (elen != RARRAY(tmp)->len) {
- rb_raise(rb_eIndexError, "element size differs (%d should be %d)",
- RARRAY(tmp)->len, elen);
- }
- for (j=0; j<elen; j++) {
- rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
- }
- }
- return result;
-}
-
-/*
- * call-seq:
- * array.replace(other_array) -> array
- *
- * Replaces the contents of <i>self</i> with the contents of
- * <i>other_array</i>, truncating or expanding if necessary.
- *
- * a = [ "a", "b", "c", "d", "e" ]
- * a.replace([ "x", "y", "z" ]) #=> ["x", "y", "z"]
- * a #=> ["x", "y", "z"]
- */
-
-static VALUE
-rb_ary_replace(copy, orig)
- VALUE copy, orig;
-{
- VALUE shared;
-
- rb_ary_modify(copy);
- orig = to_ary(orig);
- if (copy == orig) return copy;
- shared = ary_make_shared(orig);
- if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED))
- free(RARRAY(copy)->ptr);
- RARRAY(copy)->ptr = RARRAY(orig)->ptr;
- RARRAY(copy)->len = RARRAY(orig)->len;
- RARRAY(copy)->aux.shared = shared;
- FL_SET(copy, ELTS_SHARED);
-
- return copy;
-}
-
-/*
- * call-seq:
- * array.clear -> array
- *
- * Removes all elements from _self_.
- *
- * a = [ "a", "b", "c", "d", "e" ]
- * a.clear #=> [ ]
- */
-
-VALUE
-rb_ary_clear(ary)
- VALUE ary;
-{
- rb_ary_modify(ary);
- RARRAY(ary)->len = 0;
- if (ARY_DEFAULT_SIZE * 2 < RARRAY(ary)->aux.capa) {
- REALLOC_N(RARRAY(ary)->ptr, VALUE, ARY_DEFAULT_SIZE * 2);
- RARRAY(ary)->aux.capa = ARY_DEFAULT_SIZE * 2;
- }
- return ary;
-}
-
-/*
- * call-seq:
- * array.fill(obj) -> array
- * array.fill(obj, start [, length]) -> array
- * array.fill(obj, range ) -> array
- * array.fill {|index| block } -> array
- * array.fill(start [, length] ) {|index| block } -> array
- * array.fill(range) {|index| block } -> array
- *
- * The first three forms set the selected elements of <i>self</i> (which
- * may be the entire array) to <i>obj</i>. A <i>start</i> of
- * <code>nil</code> is equivalent to zero. A <i>length</i> of
- * <code>nil</code> is equivalent to <i>self.length</i>. The last three
- * forms fill the array with the value of the block. The block is
- * passed the absolute index of each element to be filled.
- *
- * a = [ "a", "b", "c", "d" ]
- * a.fill("x") #=> ["x", "x", "x", "x"]
- * a.fill("z", 2, 2) #=> ["x", "x", "z", "z"]
- * a.fill("y", 0..1) #=> ["y", "y", "z", "z"]
- * a.fill {|i| i*i} #=> [0, 1, 4, 9]
- * a.fill(-2) {|i| i*i*i} #=> [0, 1, 8, 27]
- */
-
-static VALUE
-rb_ary_fill(argc, argv, ary)
- int argc;
- VALUE *argv;
- VALUE ary;
-{
- VALUE item, arg1, arg2;
- long beg, end, len;
- VALUE *p, *pend;
- int block_p = Qfalse;
-
- if (rb_block_given_p()) {
- block_p = Qtrue;
- rb_scan_args(argc, argv, "02", &arg1, &arg2);
- argc += 1; /* hackish */
- }
- else {
- rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
- }
- switch (argc) {
- case 1:
- beg = 0;
- len = RARRAY(ary)->len;
- break;
- case 2:
- if (rb_range_beg_len(arg1, &beg, &len, RARRAY(ary)->len, 1)) {
- break;
- }
- /* fall through */
- case 3:
- beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
- if (beg < 0) {
- beg = RARRAY(ary)->len + beg;
- if (beg < 0) beg = 0;
- }
- len = NIL_P(arg2) ? RARRAY(ary)->len - beg : NUM2LONG(arg2);
- break;
- }
- rb_ary_modify(ary);
- end = beg + len;
- if (end > RARRAY(ary)->len) {
- if (end >= RARRAY(ary)->aux.capa) {
- REALLOC_N(RARRAY(ary)->ptr, VALUE, end);
- RARRAY(ary)->aux.capa = end;
- }
- if (beg > RARRAY(ary)->len) {
- rb_mem_clear(RARRAY(ary)->ptr + RARRAY(ary)->len, end - RARRAY(ary)->len);
- }
- RARRAY(ary)->len = end;
- }
-
- if (block_p) {
- VALUE v;
- long i;
-
- for (i=beg; i<end; i++) {
- v = rb_yield(LONG2NUM(i));
- if (i>=RARRAY(ary)->len) break;
- RARRAY(ary)->ptr[i] = v;
- }
- }
- else {
- p = RARRAY(ary)->ptr + beg;
- pend = p + len;
- while (p < pend) {
- *p++ = item;
- }
- }
- return ary;
-}
-
-/*
- * call-seq:
- * array + other_array -> an_array
- *
- * Concatenation---Returns a new array built by concatenating the
- * two arrays together to produce a third array.
- *
- * [ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ]
- */
-
-VALUE
-rb_ary_plus(x, y)
- VALUE x, y;
-{
- VALUE z;
- long len;
-
- y = to_ary(y);
- len = RARRAY(x)->len + RARRAY(y)->len;
- z = rb_ary_new2(len);
- MEMCPY(RARRAY(z)->ptr, RARRAY(x)->ptr, VALUE, RARRAY(x)->len);
- MEMCPY(RARRAY(z)->ptr + RARRAY(x)->len, RARRAY(y)->ptr, VALUE, RARRAY(y)->len);
- RARRAY(z)->len = len;
- return z;
-}
-
-/*
- * call-seq:
- * array.concat(other_array) -> array
- *
- * Appends the elements in other_array to _self_.
- *
- * [ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
- */
-
-
-VALUE
-rb_ary_concat(x, y)
- VALUE x, y;
-{
- y = to_ary(y);
- if (RARRAY(y)->len > 0) {
- rb_ary_splice(x, RARRAY(x)->len, 0, y);
- }
- return x;
-}
-
-
-/*
- * call-seq:
- * array * int -> an_array
- * array * str -> a_string
- *
- * Repetition---With a String argument, equivalent to
- * self.join(str). Otherwise, returns a new array
- * built by concatenating the _int_ copies of _self_.
- *
- *
- * [ 1, 2, 3 ] * 3 #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
- * [ 1, 2, 3 ] * "," #=> "1,2,3"
- *
- */
-
-static VALUE
-rb_ary_times(ary, times)
- VALUE ary, times;
-{
- VALUE ary2, tmp;
- long i, len;
-
- tmp = rb_check_string_type(times);
- if (!NIL_P(tmp)) {
- return rb_ary_join(ary, tmp);
- }
-
- len = NUM2LONG(times);
- if (len == 0) return ary_new(rb_obj_class(ary), 0);
- if (len < 0) {
- rb_raise(rb_eArgError, "negative argument");
- }
- if (LONG_MAX/len < RARRAY(ary)->len) {
- rb_raise(rb_eArgError, "argument too big");
- }
- len *= RARRAY(ary)->len;
-
- ary2 = ary_new(rb_obj_class(ary), len);
- RARRAY(ary2)->len = len;
-
- for (i=0; i<len; i+=RARRAY(ary)->len) {
- MEMCPY(RARRAY(ary2)->ptr+i, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
- }
- OBJ_INFECT(ary2, ary);
-
- return ary2;
-}
-
-/*
- * call-seq:
- * array.assoc(obj) -> an_array or nil
- *
- * Searches through an array whose elements are also arrays
- * comparing _obj_ with the first element of each contained array
- * using obj.==.
- * Returns the first contained array that matches (that
- * is, the first associated array),
- * or +nil+ if no match is found.
- * See also <code>Array#rassoc</code>.
- *
- * s1 = [ "colors", "red", "blue", "green" ]
- * s2 = [ "letters", "a", "b", "c" ]
- * s3 = "foo"
- * a = [ s1, s2, s3 ]
- * a.assoc("letters") #=> [ "letters", "a", "b", "c" ]
- * a.assoc("foo") #=> nil
- */
-
-VALUE
-rb_ary_assoc(ary, key)
- VALUE ary, key;
-{
- long i;
- VALUE v;
-
- for (i = 0; i < RARRAY(ary)->len; ++i) {
- v = RARRAY(ary)->ptr[i];
- if (TYPE(v) == T_ARRAY &&
- RARRAY(v)->len > 0 &&
- rb_equal(RARRAY(v)->ptr[0], key))
- return v;
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * array.rassoc(key) -> an_array or nil
- *
- * Searches through the array whose elements are also arrays. Compares
- * <em>key</em> with the second element of each contained array using
- * <code>==</code>. Returns the first contained array that matches. See
- * also <code>Array#assoc</code>.
- *
- * a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
- * a.rassoc("two") #=> [2, "two"]
- * a.rassoc("four") #=> nil
- */
-
-VALUE
-rb_ary_rassoc(ary, value)
- VALUE ary, value;
-{
- long i;
- VALUE v;
-
- for (i = 0; i < RARRAY(ary)->len; ++i) {
- v = RARRAY(ary)->ptr[i];
- if (TYPE(v) == T_ARRAY &&
- RARRAY(v)->len > 1 &&
- rb_equal(RARRAY(v)->ptr[1], value))
- return v;
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * array == other_array -> bool
- *
- * Equality---Two arrays are equal if they contain the same number
- * of elements and if each element is equal to (according to
- * Object.==) the corresponding element in the other array.
- *
- * [ "a", "c" ] == [ "a", "c", 7 ] #=> false
- * [ "a", "c", 7 ] == [ "a", "c", 7 ] #=> true
- * [ "a", "c", 7 ] == [ "a", "d", "f" ] #=> false
- *
- */
-
-static VALUE
-rb_ary_equal(ary1, ary2)
- VALUE ary1, ary2;
-{
- long i;
-
- if (ary1 == ary2) return Qtrue;
- if (TYPE(ary2) != T_ARRAY) {
- if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
- return Qfalse;
- }
- return rb_equal(ary2, ary1);
- }
- if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
- for (i=0; i<RARRAY(ary1)->len; i++) {
- if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
- return Qfalse;
- }
- return Qtrue;
-}
-
-/*
- * call-seq:
- * array.eql?(other) -> true or false
- *
- * Returns <code>true</code> if _array_ and _other_ are the same object,
- * or are both arrays with the same content.
- */
-
-static VALUE
-rb_ary_eql(ary1, ary2)
- VALUE ary1, ary2;
-{
- long i;
-
- if (ary1 == ary2) return Qtrue;
- if (TYPE(ary2) != T_ARRAY) return Qfalse;
- if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
- for (i=0; i<RARRAY(ary1)->len; i++) {
- if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
- return Qfalse;
- }
- return Qtrue;
-}
-
-static VALUE
-recursive_hash(ary, dummy, recur)
- VALUE ary, dummy;
- int recur;
-{
- long i, h;
- VALUE n;
-
- if (recur) {
- return LONG2FIX(0);
- }
- h = RARRAY(ary)->len;
- for (i=0; i<RARRAY(ary)->len; i++) {
- h = (h << 1) | (h<0 ? 1 : 0);
- n = rb_hash(RARRAY(ary)->ptr[i]);
- h ^= NUM2LONG(n);
- }
- return LONG2FIX(h);
-}
-
-/*
- * call-seq:
- * array.hash -> fixnum
- *
- * Compute a hash-code for this array. Two arrays with the same content
- * will have the same hash code (and will compare using <code>eql?</code>).
- */
-
-static VALUE
-rb_ary_hash(ary)
- VALUE ary;
-{
- return rb_exec_recursive(recursive_hash, ary, 0);
-}
-
-/*
- * call-seq:
- * array.include?(obj) -> true or false
- *
- * Returns <code>true</code> if the given object is present in
- * <i>self</i> (that is, if any object <code>==</code> <i>anObject</i>),
- * <code>false</code> otherwise.
- *
- * a = [ "a", "b", "c" ]
- * a.include?("b") #=> true
- * a.include?("z") #=> false
- */
-
-VALUE
-rb_ary_includes(ary, item)
- VALUE ary;
- VALUE item;
-{
- long i;
-
- for (i=0; i<RARRAY(ary)->len; i++) {
- if (rb_equal(RARRAY(ary)->ptr[i], item)) {
- return Qtrue;
- }
- }
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * array <=> other_array -> -1, 0, +1
- *
- * Comparison---Returns an integer (-1, 0,
- * or +1) if this array is less than, equal to, or greater than
- * other_array. Each object in each array is compared
- * (using <=>). If any value isn't
- * equal, then that inequality is the return value. If all the
- * values found are equal, then the return is based on a
- * comparison of the array lengths. Thus, two arrays are
- * ``equal'' according to <code>Array#<=></code> if and only if they have
- * the same length and the value of each element is equal to the
- * value of the corresponding element in the other array.
- *
- * [ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1
- * [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1
- *
- */
-
-VALUE
-rb_ary_cmp(ary1, ary2)
- VALUE ary1, ary2;
-{
- long i, len;
-
- ary2 = to_ary(ary2);
- len = RARRAY(ary1)->len;
- if (len > RARRAY(ary2)->len) {
- len = RARRAY(ary2)->len;
- }
- for (i=0; i<len; i++) {
- VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
- if (v != INT2FIX(0)) {
- return v;
- }
- }
- len = RARRAY(ary1)->len - RARRAY(ary2)->len;
- if (len == 0) return INT2FIX(0);
- if (len > 0) return INT2FIX(1);
- return INT2FIX(-1);
-}
-
-static VALUE
-ary_make_hash(ary1, ary2)
- VALUE ary1, ary2;
-{
- VALUE hash = rb_hash_new();
- long i;
-
- for (i=0; i<RARRAY(ary1)->len; i++) {
- rb_hash_aset(hash, RARRAY(ary1)->ptr[i], Qtrue);
- }
- if (ary2) {
- for (i=0; i<RARRAY(ary2)->len; i++) {
- rb_hash_aset(hash, RARRAY(ary2)->ptr[i], Qtrue);
- }
- }
- return hash;
-}
-
-/*
- * call-seq:
- * array - other_array -> an_array
- *
- * Array Difference---Returns a new array that is a copy of
- * the original array, removing any items that also appear in
- * other_array. (If you need set-like behavior, see the
- * library class Set.)
- *
- * [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
- */
-
-static VALUE
-rb_ary_diff(ary1, ary2)
- VALUE ary1, ary2;
-{
- VALUE ary3, hash;
- long i;
-
- hash = ary_make_hash(to_ary(ary2), 0);
- ary3 = rb_ary_new();
-
- for (i=0; i<RARRAY(ary1)->len; i++) {
- if (st_lookup(RHASH(hash)->tbl, RARRAY(ary1)->ptr[i], 0)) continue;
- rb_ary_push(ary3, rb_ary_elt(ary1, i));
- }
- return ary3;
-}
-
-/*
- * call-seq:
- * array & other_array
- *
- * Set Intersection---Returns a new array
- * containing elements common to the two arrays, with no duplicates.
- *
- * [ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ]
- */
-
-
-static VALUE
-rb_ary_and(ary1, ary2)
- VALUE ary1, ary2;
-{
- VALUE hash, ary3, v, vv;
- long i;
-
- ary2 = to_ary(ary2);
- ary3 = rb_ary_new2(RARRAY(ary1)->len < RARRAY(ary2)->len ?
- RARRAY(ary1)->len : RARRAY(ary2)->len);
- hash = ary_make_hash(ary2, 0);
-
- for (i=0; i<RARRAY(ary1)->len; i++) {
- v = vv = rb_ary_elt(ary1, i);
- if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) {
- rb_ary_push(ary3, v);
- }
- }
-
- return ary3;
-}
-
-/*
- * call-seq:
- * array | other_array -> an_array
- *
- * Set Union---Returns a new array by joining this array with
- * other_array, removing duplicates.
- *
- * [ "a", "b", "c" ] | [ "c", "d", "a" ]
- * #=> [ "a", "b", "c", "d" ]
- */
-
-static VALUE
-rb_ary_or(ary1, ary2)
- VALUE ary1, ary2;
-{
- VALUE hash, ary3;
- VALUE v, vv;
- long i;
-
- ary2 = to_ary(ary2);
- ary3 = rb_ary_new2(RARRAY(ary1)->len+RARRAY(ary2)->len);
- hash = ary_make_hash(ary1, ary2);
-
- for (i=0; i<RARRAY(ary1)->len; i++) {
- v = vv = rb_ary_elt(ary1, i);
- if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) {
- rb_ary_push(ary3, v);
- }
- }
- for (i=0; i<RARRAY(ary2)->len; i++) {
- v = vv = rb_ary_elt(ary2, i);
- if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) {
- rb_ary_push(ary3, v);
- }
- }
- return ary3;
-}
-
-/*
- * call-seq:
- * array.uniq! -> array or nil
- *
- * Removes duplicate elements from _self_.
- * Returns <code>nil</code> if no changes are made (that is, no
- * duplicates are found).
- *
- * a = [ "a", "a", "b", "b", "c" ]
- * a.uniq! #=> ["a", "b", "c"]
- * b = [ "a", "b", "c" ]
- * b.uniq! #=> nil
- */
-
-static VALUE
-rb_ary_uniq_bang(ary)
- VALUE ary;
-{
- VALUE hash, v, vv;
- long i, j;
-
- hash = ary_make_hash(ary, 0);
-
- if (RARRAY(ary)->len == RHASH(hash)->tbl->num_entries) {
- return Qnil;
- }
- for (i=j=0; i<RARRAY(ary)->len; i++) {
- v = vv = rb_ary_elt(ary, i);
- if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) {
- rb_ary_store(ary, j++, v);
- }
- }
- RARRAY(ary)->len = j;
-
- return ary;
-}
-
-/*
- * call-seq:
- * array.uniq -> an_array
- *
- * Returns a new array by removing duplicate values in <i>self</i>.
- *
- * a = [ "a", "a", "b", "b", "c" ]
- * a.uniq #=> ["a", "b", "c"]
- */
-
-static VALUE
-rb_ary_uniq(ary)
- VALUE ary;
-{
- ary = rb_ary_dup(ary);
- rb_ary_uniq_bang(ary);
- return ary;
-}
-
-/*
- * call-seq:
- * array.compact! -> array or nil
- *
- * Removes +nil+ elements from array.
- * Returns +nil+ if no changes were made.
- *
- * [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
- * [ "a", "b", "c" ].compact! #=> nil
- */
-
-static VALUE
-rb_ary_compact_bang(ary)
- VALUE ary;
-{
- VALUE *p, *t, *end;
-
- rb_ary_modify(ary);
- p = t = RARRAY(ary)->ptr;
- end = p + RARRAY(ary)->len;
-
- while (t < end) {
- if (NIL_P(*t)) t++;
- else *p++ = *t++;
- }
- if (RARRAY(ary)->len == (p - RARRAY(ary)->ptr)) {
- return Qnil;
- }
- RARRAY(ary)->len = RARRAY(ary)->aux.capa = (p - RARRAY(ary)->ptr);
- REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
-
- return ary;
-}
-
-/*
- * call-seq:
- * array.compact -> an_array
- *
- * Returns a copy of _self_ with all +nil+ elements removed.
- *
- * [ "a", nil, "b", nil, "c", nil ].compact
- * #=> [ "a", "b", "c" ]
- */
-
-static VALUE
-rb_ary_compact(ary)
- VALUE ary;
-{
- ary = rb_ary_dup(ary);
- rb_ary_compact_bang(ary);
- return ary;
-}
-
-/*
- * call-seq:
- * array.nitems -> int
- *
- * Returns the number of non-<code>nil</code> elements in _self_.
- * May be zero.
- *
- * [ 1, nil, 3, nil, 5 ].nitems #=> 3
- */
-
-static VALUE
-rb_ary_nitems(ary)
- VALUE ary;
-{
- long n = 0;
- VALUE *p, *pend;
-
- p = RARRAY(ary)->ptr;
- pend = p + RARRAY(ary)->len;
-
- while (p < pend) {
- if (!NIL_P(*p)) n++;
- p++;
- }
- return LONG2NUM(n);
-}
-
-static long
-flatten(ary, idx, ary2, memo)
- VALUE ary;
- long idx;
- VALUE ary2, memo;
-{
- VALUE id;
- long i = idx;
- long n, lim = idx + RARRAY(ary2)->len;
-
- id = rb_obj_id(ary2);
- if (rb_ary_includes(memo, id)) {
- rb_raise(rb_eArgError, "tried to flatten recursive array");
- }
- rb_ary_push(memo, id);
- rb_ary_splice(ary, idx, 1, ary2);
- while (i < lim) {
- VALUE tmp;
-
- tmp = rb_check_array_type(rb_ary_elt(ary, i));
- if (!NIL_P(tmp)) {
- n = flatten(ary, i, tmp, memo);
- i += n; lim += n;
- }
- i++;
- }
- rb_ary_pop(memo);
-
- return lim - idx - 1; /* returns number of increased items */
-}
-
-/*
- * call-seq:
- * array.flatten! -> array or nil
- *
- * Flattens _self_ in place.
- * Returns <code>nil</code> if no modifications were made (i.e.,
- * <i>array</i> contains no subarrays.)
- *
- * a = [ 1, 2, [3, [4, 5] ] ]
- * a.flatten! #=> [1, 2, 3, 4, 5]
- * a.flatten! #=> nil
- * a #=> [1, 2, 3, 4, 5]
- */
-
-static VALUE
-rb_ary_flatten_bang(ary)
- VALUE ary;
-{
- long i = 0;
- int mod = 0;
- VALUE memo = Qnil;
-
- while (i<RARRAY(ary)->len) {
- VALUE ary2 = RARRAY(ary)->ptr[i];
- VALUE tmp;
-
- tmp = rb_check_array_type(ary2);
- if (!NIL_P(tmp)) {
- if (NIL_P(memo)) {
- memo = rb_ary_new();
- }
- i += flatten(ary, i, tmp, memo);
- mod = 1;
- }
- i++;
- }
- if (mod == 0) return Qnil;
- return ary;
-}
-
-/*
- * call-seq:
- * array.flatten -> an_array
- *
- * Returns a new array that is a one-dimensional flattening of this
- * array (recursively). That is, for every element that is an array,
- * extract its elements into the new array.
- *
- * s = [ 1, 2, 3 ] #=> [1, 2, 3]
- * t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
- * a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
- * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10
- */
-
-static VALUE
-rb_ary_flatten(ary)
- VALUE ary;
-{
- ary = rb_ary_dup(ary);
- rb_ary_flatten_bang(ary);
- return ary;
-}
-
-
-/* Arrays are ordered, integer-indexed collections of any object.
- * Array indexing starts at 0, as in C or Java. A negative index is
- * assumed to be relative to the end of the array---that is, an index of -1
- * indicates the last element of the array, -2 is the next to last
- * element in the array, and so on.
- */
-
-void
-Init_Array()
-{
- rb_cArray = rb_define_class("Array", rb_cObject);
- rb_include_module(rb_cArray, rb_mEnumerable);
-
- rb_define_alloc_func(rb_cArray, ary_alloc);
- rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
- rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
- rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
-
- rb_define_method(rb_cArray, "to_s", rb_ary_to_s, 0);
- rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
- rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
- rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
- rb_define_method(rb_cArray, "frozen?", rb_ary_frozen_p, 0);
-
- rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
- rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
- rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
-
- rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
- rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
- rb_define_method(rb_cArray, "at", rb_ary_at, 1);
- rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
- rb_define_method(rb_cArray, "first", rb_ary_first, -1);
- rb_define_method(rb_cArray, "last", rb_ary_last, -1);
- rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
- rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
- rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
- rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
- rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
- rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
- rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
- rb_define_method(rb_cArray, "each", rb_ary_each, 0);
- rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
- rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
- rb_define_method(rb_cArray, "length", rb_ary_length, 0);
- rb_define_alias(rb_cArray, "size", "length");
- rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
- rb_define_method(rb_cArray, "index", rb_ary_index, -1);
- rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
- rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
- rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
- rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
- rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
- rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
- rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
- rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
- rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
- rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
- rb_define_method(rb_cArray, "select", rb_ary_select, 0);
- rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
- rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
- rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
- rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
- rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
- rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
- rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
- rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
- rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
- rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
- rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
- rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
- rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
-
- rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
- rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
-
- rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
- rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
-
- rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
- rb_define_method(rb_cArray, "*", rb_ary_times, 1);
-
- rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
- rb_define_method(rb_cArray, "&", rb_ary_and, 1);
- rb_define_method(rb_cArray, "|", rb_ary_or, 1);
-
- rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
- rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
- rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
- rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
- rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);
- rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, 0);
- rb_define_method(rb_cArray, "nitems", rb_ary_nitems, 0);
-
- id_cmp = rb_intern("<=>");
-
- rb_cValues = rb_define_class("Values", rb_cArray);
-}
-/**********************************************************************
- ascii.c - Oniguruma (regular expression library)
-**********************************************************************/
-/*-
- * Copyright (c) 2002-2004 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"
-
-static int
-ascii_is_code_ctype(OnigCodePoint code, unsigned int ctype)
-{
- if (code < 128)
- return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype);
- else
- return FALSE;
-}
-
-OnigEncodingType OnigEncodingASCII = {
- onigenc_single_byte_mbc_enc_len,
- "US-ASCII", /* name */
- 1, /* max byte length */
- 1, /* min byte 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,
- onigenc_single_byte_mbc_to_code,
- onigenc_single_byte_code_to_mbclen,
- onigenc_single_byte_code_to_mbc,
- onigenc_ascii_mbc_to_normalize,
- onigenc_ascii_is_mbc_ambiguous,
- onigenc_ascii_get_all_pair_ambig_codes,
- onigenc_nothing_get_all_comp_ambig_codes,
- ascii_is_code_ctype,
- onigenc_not_support_get_ctype_code_range,
- onigenc_single_byte_left_adjust_char_head,
- onigenc_always_true_is_allowed_reverse_match
-};
-/**********************************************************************
-
- bignum.c -
-
- $Author: matz $
- $Date: 2005/03/04 06:47:45 $
- created at: Fri Jun 10 00:48:55 JST 1994
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-
-#include <math.h>
-#include <ctype.h>
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
-VALUE rb_cBignum;
-
-#if defined __MINGW32__
-#define USHORT _USHORT
-#endif
-
-#define BDIGITS(x) ((BDIGIT*)RBIGNUM(x)->digits)
-#define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
-#define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
-#define DIGSPERLONG ((unsigned int)(SIZEOF_LONG/SIZEOF_BDIGITS))
-#if HAVE_LONG_LONG
-# define DIGSPERLL ((unsigned int)(SIZEOF_LONG_LONG/SIZEOF_BDIGITS))
-#endif
-#define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG)
-#define BIGDN(x) RSHIFT(x,BITSPERDIG)
-#define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
-#define BDIGMAX ((BDIGIT)-1)
-
-#define BIGZEROP(x) (RBIGNUM(x)->len == 0 || (RBIGNUM(x)->len == 1 && BDIGITS(x)[0] == 0))
-
-static VALUE
-bignew_1(klass, len, sign)
- VALUE klass;
- long len;
- char sign;
-{
- NEWOBJ(big, struct RBignum);
- OBJSETUP(big, klass, T_BIGNUM);
- big->sign = sign;
- big->len = len;
- big->digits = ALLOC_N(BDIGIT, len);
-
- return (VALUE)big;
-}
-
-#define bignew(len,sign) bignew_1(rb_cBignum,len,sign)
-
-VALUE
-rb_big_clone(x)
- VALUE x;
-{
- VALUE z = bignew_1(CLASS_OF(x), RBIGNUM(x)->len, RBIGNUM(x)->sign);
-
- MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, RBIGNUM(x)->len);
- return z;
-}
-
-static void
-get2comp(x, carry) /* get 2's complement */
- VALUE x;
- int carry;
-{
- long i = RBIGNUM(x)->len;
- BDIGIT *ds = BDIGITS(x);
- BDIGIT_DBL num;
-
- while (i--) ds[i] = ~ds[i];
- i = 0; num = 1;
- do {
- num += ds[i];
- ds[i++] = BIGLO(num);
- num = BIGDN(num);
- } while (i < RBIGNUM(x)->len);
- if (!carry) return;
- if ((ds[RBIGNUM(x)->len-1] & (1<<(BITSPERDIG-1))) == 0) {
- REALLOC_N(RBIGNUM(x)->digits, BDIGIT, ++RBIGNUM(x)->len);
- ds = BDIGITS(x);
- ds[RBIGNUM(x)->len-1] = ~0;
- }
-}
-
-void
-rb_big_2comp(x) /* get 2's complement */
- VALUE x;
-{
- get2comp(x, Qtrue);
-}
-
-static VALUE
-bignorm(x)
- VALUE x;
-{
- if (!FIXNUM_P(x)) {
- long len = RBIGNUM(x)->len;
- BDIGIT *ds = BDIGITS(x);
-
- while (len-- && !ds[len]) ;
- RBIGNUM(x)->len = ++len;
-
- if (len*SIZEOF_BDIGITS <= sizeof(VALUE)) {
- long num = 0;
- while (len--) {
- num = BIGUP(num) + ds[len];
- }
- if (num >= 0) {
- if (RBIGNUM(x)->sign) {
- if (POSFIXABLE(num)) return LONG2FIX(num);
- }
- else if (NEGFIXABLE(-(long)num)) return LONG2FIX(-(long)num);
- }
- }
- }
- return x;
-}
-
-VALUE
-rb_big_norm(x)
- VALUE x;
-{
- return bignorm(x);
-}
-
-VALUE
-rb_uint2big(n)
- unsigned long n;
-{
- BDIGIT_DBL num = n;
- long i = 0;
- BDIGIT *digits;
- VALUE big;
-
- big = bignew(DIGSPERLONG, 1);
- digits = BDIGITS(big);
- while (i < DIGSPERLONG) {
- digits[i++] = BIGLO(num);
- num = BIGDN(num);
- }
-
- i = DIGSPERLONG;
- while (--i && !digits[i]) ;
- RBIGNUM(big)->len = i+1;
- return big;
-}
-
-VALUE
-rb_int2big(n)
- long n;
-{
- long neg = 0;
- VALUE big;
-
- if (n < 0) {
- n = -n;
- neg = 1;
- }
- big = rb_uint2big(n);
- if (neg) {
- RBIGNUM(big)->sign = 0;
- }
- return big;
-}
-
-VALUE
-rb_uint2inum(n)
- unsigned long n;
-{
- if (POSFIXABLE(n)) return LONG2FIX(n);
- return rb_uint2big(n);
-}
-
-VALUE
-rb_int2inum(n)
- long n;
-{
- if (FIXABLE(n)) return LONG2FIX(n);
- return rb_int2big(n);
-}
-
-#ifdef HAVE_LONG_LONG
-
-void
-rb_quad_pack(buf, val)
- char *buf;
- VALUE val;
-{
- LONG_LONG q;
-
- val = rb_to_int(val);
- if (FIXNUM_P(val)) {
- q = FIX2LONG(val);
- }
- else {
- long len = RBIGNUM(val)->len;
- BDIGIT *ds;
-
- if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS) {
- len = SIZEOF_LONG/SIZEOF_BDIGITS;
- }
- ds = BDIGITS(val);
- q = 0;
- while (len--) {
- q = BIGUP(q);
- q += ds[len];
- }
- if (!RBIGNUM(val)->sign) q = -q;
- }
- memcpy(buf, (char*)&q, SIZEOF_LONG_LONG);
-}
-
-VALUE
-rb_quad_unpack(buf, sign)
- const char *buf;
- int sign;
-{
- unsigned LONG_LONG q;
- long neg = 0;
- long i;
- BDIGIT *digits;
- VALUE big;
-
- memcpy(&q, buf, SIZEOF_LONG_LONG);
- if (sign) {
- if (FIXABLE((LONG_LONG)q)) return LONG2FIX((LONG_LONG)q);
- if ((LONG_LONG)q < 0) {
- q = -(LONG_LONG)q;
- neg = 1;
- }
- }
- else {
- if (POSFIXABLE(q)) return LONG2FIX(q);
- }
-
- i = 0;
- big = bignew(DIGSPERLL, 1);
- digits = BDIGITS(big);
- while (i < DIGSPERLL) {
- digits[i++] = BIGLO(q);
- q = BIGDN(q);
- }
-
- i = DIGSPERLL;
- while (i-- && !digits[i]) ;
- RBIGNUM(big)->len = i+1;
-
- if (neg) {
- RBIGNUM(big)->sign = 0;
- }
- return bignorm(big);
-}
-
-#else
-
-#define QUAD_SIZE 8
-
-void
-rb_quad_pack(buf, val)
- char *buf;
- VALUE val;
-{
- long len;
-
- memset(buf, 0, QUAD_SIZE);
- val = rb_to_int(val);
- if (FIXNUM_P(val)) {
- val = rb_int2big(FIX2LONG(val));
- }
- len = RBIGNUM(val)->len * SIZEOF_BDIGITS;
- if (len > QUAD_SIZE) {
- rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'");
- }
- memcpy(buf, (char*)BDIGITS(val), len);
- if (!RBIGNUM(val)->sign) {
- len = QUAD_SIZE;
- while (len--) {
- *buf = ~*buf;
- buf++;
- }
- }
-}
-
-#define BNEG(b) (RSHIFT(((BDIGIT*)b)[QUAD_SIZE/SIZEOF_BDIGITS-1],BITSPERDIG-1) != 0)
-
-VALUE
-rb_quad_unpack(buf, sign)
- const char *buf;
- int sign;
-{
- VALUE big = bignew(QUAD_SIZE/SIZEOF_BDIGITS, 1);
-
- memcpy((char*)BDIGITS(big), buf, QUAD_SIZE);
- if (sign && BNEG(buf)) {
- long len = QUAD_SIZE;
- char *tmp = (char*)BDIGITS(big);
-
- RBIGNUM(big)->sign = 0;
- while (len--) {
- *tmp = ~*tmp;
- tmp++;
- }
- }
-
- return bignorm(big);
-}
-
-#endif
-
-VALUE
-rb_cstr_to_inum(str, base, badcheck)
- const char *str;
- int base;
- int badcheck;
-{
- const char *s = str;
- char *end;
- char sign = 1, nondigit = 0;
- int c;
- BDIGIT_DBL num;
- long len, blen = 1;
- long i;
- VALUE z;
- BDIGIT *zds;
-
- if (!str) {
- if (badcheck) goto bad;
- return INT2FIX(0);
- }
- if (badcheck) {
- while (ISSPACE(*str)) str++;
- }
- else {
- while (ISSPACE(*str) || *str == '_') str++;
- }
-
- if (str[0] == '+') {
- str++;
- }
- else if (str[0] == '-') {
- str++;
- sign = 0;
- }
- if (str[0] == '+' || str[0] == '-') {
- if (badcheck) goto bad;
- return INT2FIX(0);
- }
- if (base <= 0) {
- if (str[0] == '0') {
- switch (str[1]) {
- case 'x': case 'X':
- base = 16;
- break;
- case 'b': case 'B':
- base = 2;
- break;
- case 'o': case 'O':
- base = 8;
- break;
- case 'd': case 'D':
- base = 10;
- break;
- default:
- base = 8;
- }
- }
- else if (base < -1) {
- base = -base;
- }
- else {
- base = 10;
- }
- }
- switch (base) {
- case 2:
- len = 1;
- if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
- str += 2;
- }
- break;
- case 3:
- len = 2;
- break;
- case 8:
- if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
- str += 2;
- }
- case 4: case 5: case 6: case 7:
- len = 3;
- break;
- case 10:
- if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
- str += 2;
- }
- case 9: case 11: case 12: case 13: case 14: case 15:
- len = 4;
- break;
- case 16:
- len = 4;
- if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
- str += 2;
- }
- break;
- default:
- if (base < 2 || 36 < base) {
- rb_raise(rb_eArgError, "illegal radix %d", base);
- }
- if (base <= 32) {
- len = 5;
- }
- else {
- len = 6;
- }
- break;
- }
- if (*str == '0') { /* squeeze preceeding 0s */
- while (*++str == '0');
- --str;
- }
- len *= strlen(str)*sizeof(char);
-
- if (len <= (sizeof(VALUE)*CHAR_BIT)) {
- unsigned long val = strtoul((char*)str, &end, base);
-
- if (*end == '_') goto bigparse;
- if (badcheck) {
- if (end == str) goto bad; /* no number */
- while (*end && ISSPACE(*end)) end++;
- if (*end) goto bad; /* trailing garbage */
- }
-
- if (POSFIXABLE(val)) {
- if (sign) return LONG2FIX(val);
- else {
- long result = -(long)val;
- return LONG2FIX(result);
- }
- }
- else {
- VALUE big = rb_uint2big(val);
- RBIGNUM(big)->sign = sign;
- return bignorm(big);
- }
- }
- bigparse:
- len = (len/BITSPERDIG)+1;
- if (badcheck && *str == '_') goto bad;
-
- z = bignew(len, sign);
- zds = BDIGITS(z);
- for (i=len;i--;) zds[i]=0;
- while (c = *str++) {
- if (c == '_') {
- if (badcheck) {
- if (nondigit) goto bad;
- nondigit = c;
- }
- continue;
- }
- else if (!ISASCII(c)) {
- break;
- }
- else if (isdigit(c)) {
- c -= '0';
- }
- else if (islower(c)) {
- c -= 'a' - 10;
- }
- else if (isupper(c)) {
- c -= 'A' - 10;
- }
- else {
- break;
- }
- if (c >= base) break;
- nondigit = 0;
- i = 0;
- num = c;
- for (;;) {
- while (i<blen) {
- num += (BDIGIT_DBL)zds[i]*base;
- zds[i++] = BIGLO(num);
- num = BIGDN(num);
- }
- if (num) {
- blen++;
- continue;
- }
- break;
- }
- }
- if (badcheck) {
- str--;
- if (s+1 < str && str[-1] == '_') goto bad;
- while (*str && ISSPACE(*str)) str++;
- if (*str) {
- bad:
- rb_invalid_str(s, "Integer");
- }
- }
-
- return bignorm(z);
-}
-
-VALUE
-rb_str_to_inum(str, base, badcheck)
- VALUE str;
- int base;
- int badcheck;
-{
- char *s;
- long len;
-
- StringValue(str);
- if (badcheck) {
- s = StringValueCStr(str);
- }
- else {
- s = RSTRING(str)->ptr;
- }
- if (s) {
- len = RSTRING(str)->len;
- if (s[len]) { /* no sentinel somehow */
- char *p = ALLOCA_N(char, len+1);
-
- MEMCPY(p, s, char, len);
- p[len] = '\0';
- s = p;
- }
- }
- return rb_cstr_to_inum(s, base, badcheck);
-}
-
-#if HAVE_LONG_LONG
-
-VALUE
-rb_ull2big(n)
- unsigned LONG_LONG n;
-{
- BDIGIT_DBL num = n;
- long i = 0;
- BDIGIT *digits;
- VALUE big;
-
- big = bignew(DIGSPERLL, 1);
- digits = BDIGITS(big);
- while (i < DIGSPERLL) {
- digits[i++] = BIGLO(num);
- num = BIGDN(num);
- }
-
- i = DIGSPERLL;
- while (i-- && !digits[i]) ;
- RBIGNUM(big)->len = i+1;
- return big;
-}
-
-VALUE
-rb_ll2big(n)
- LONG_LONG n;
-{
- long neg = 0;
- VALUE big;
-
- if (n < 0) {
- n = -n;
- neg = 1;
- }
- big = rb_ull2big(n);
- if (neg) {
- RBIGNUM(big)->sign = 0;
- }
- return big;
-}
-
-VALUE
-rb_ull2inum(n)
- unsigned LONG_LONG n;
-{
- if (POSFIXABLE(n)) return LONG2FIX(n);
- return rb_ull2big(n);
-}
-
-VALUE
-rb_ll2inum(n)
- LONG_LONG n;
-{
- if (FIXABLE(n)) return LONG2FIX(n);
- return rb_ll2big(n);
-}
-
-#endif /* HAVE_LONG_LONG */
-
-VALUE
-rb_cstr2inum(str, base)
- const char *str;
- int base;
-{
- return rb_cstr_to_inum(str, base, base==0);
-}
-
-VALUE
-rb_str2inum(str, base)
- VALUE str;
- int base;
-{
- return rb_str_to_inum(str, base, base==0);
-}
-
-const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-VALUE
-rb_big2str(x, base)
- VALUE x;
- int base;
-{
- volatile VALUE t;
- BDIGIT *ds;
- long i, j, hbase;
- VALUE ss;
- char *s, c;
-
- if (FIXNUM_P(x)) {
- return rb_fix2str(x, base);
- }
- i = RBIGNUM(x)->len;
- if (BIGZEROP(x)) {
- return rb_str_new2("0");
- }
- j = SIZEOF_BDIGITS*CHAR_BIT*i;
- switch (base) {
- case 2: break;
- case 3:
- j = j * 647L / 1024;
- break;
- case 4: case 5: case 6: case 7:
- j /= 2;
- break;
- case 8: case 9:
- j /= 3;
- break;
- case 10: case 11: case 12: case 13: case 14: case 15:
- j = j * 241L / 800;
- break;
- case 16: case 17: case 18: case 19: case 20: case 21:
- case 22: case 23: case 24: case 25: case 26: case 27:
- case 28: case 29: case 30: case 31:
- j /= 4;
- break;
- case 32: case 33: case 34: case 35: case 36:
- j /= 5;
- break;
- default:
- rb_raise(rb_eArgError, "illegal radix %d", base);
- break;
- }
- j += 2;
-
- hbase = base * base;
-#if SIZEOF_BDIGITS > 2
- hbase *= hbase;
-#endif
-
- t = rb_big_clone(x);
- ds = BDIGITS(t);
- ss = rb_str_new(0, j);
- s = RSTRING(ss)->ptr;
-
- s[0] = RBIGNUM(x)->sign ? '+' : '-';
- while (i && j) {
- long k = i;
- BDIGIT_DBL num = 0;
-
- while (k--) {
- num = BIGUP(num) + ds[k];
- ds[k] = (BDIGIT)(num / hbase);
- num %= hbase;
- }
- if (ds[i-1] == 0) i--;
- k = SIZEOF_BDIGITS;
- while (k--) {
- c = (char)(num % base);
- s[--j] = ruby_digitmap[(int)c];
- num /= base;
- if (i == 0 && num == 0) break;
- }
- }
- while (s[j] == '0') j++;
- RSTRING(ss)->len -= RBIGNUM(x)->sign?j:j-1;
- memmove(RBIGNUM(x)->sign?s:s+1, s+j, RSTRING(ss)->len);
- s[RSTRING(ss)->len] = '\0';
-
- return ss;
-}
-
-/*
- * call-seq:
- * big.to_s(base=10) => string
- *
- * Returns a string containing the representation of <i>big</i> radix
- * <i>base</i> (2 through 36).
- *
- * 12345654321.to_s #=> "12345654321"
- * 12345654321.to_s(2) #=> "1011011111110110111011110000110001"
- * 12345654321.to_s(8) #=> "133766736061"
- * 12345654321.to_s(16) #=> "2dfdbbc31"
- * 78546939656932.to_s(36) #=> "rubyrules"
- */
-
-static VALUE
-rb_big_to_s(argc, argv, x)
- int argc;
- VALUE *argv;
- VALUE x;
-{
- VALUE b;
- int base;
-
- rb_scan_args(argc, argv, "01", &b);
- if (argc == 0) base = 10;
- else base = NUM2INT(b);
- return rb_big2str(x, base);
-}
-
-static unsigned long
-big2ulong(x, type, check)
- VALUE x;
- char *type;
- int check;
-{
- long len = RBIGNUM(x)->len;
- BDIGIT_DBL num;
- BDIGIT *ds;
-
- if (len > SIZEOF_LONG/SIZEOF_BDIGITS) {
- if (check)
- rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
- len = SIZEOF_LONG/SIZEOF_BDIGITS;
- }
- ds = BDIGITS(x);
- num = 0;
- while (len--) {
- num = BIGUP(num);
- num += ds[len];
- }
- return num;
-}
-
-unsigned long
-rb_big2ulong_pack(x)
- VALUE x;
-{
- unsigned long num = big2ulong(x, "unsigned long", Qfalse);
- if (!RBIGNUM(x)->sign) {
- return -num;
- }
- return num;
-}
-
-unsigned long
-rb_big2ulong(x)
- VALUE x;
-{
- unsigned long num = big2ulong(x, "unsigned long", Qtrue);
-
- if (!RBIGNUM(x)->sign) {
- if ((long)num < 0) {
- rb_raise(rb_eRangeError, "bignum out of range of unsigned long");
- }
- return -num;
- }
- return num;
-}
-
-long
-rb_big2long(x)
- VALUE x;
-{
- unsigned long num = big2ulong(x, "long", Qtrue);
-
- if ((long)num < 0 && (RBIGNUM(x)->sign || (long)num != LONG_MIN)) {
- rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
- }
- if (!RBIGNUM(x)->sign) return -(long)num;
- return num;
-}
-
-#if HAVE_LONG_LONG
-
-static unsigned LONG_LONG
-big2ull(x, type)
- VALUE x;
- char *type;
-{
- long len = RBIGNUM(x)->len;
- BDIGIT_DBL num;
- BDIGIT *ds;
-
- if (len > SIZEOF_LONG_LONG/SIZEOF_BDIGITS)
- rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
- ds = BDIGITS(x);
- num = 0;
- while (len--) {
- num = BIGUP(num);
- num += ds[len];
- }
- return num;
-}
-
-unsigned LONG_LONG
-rb_big2ull(x)
- VALUE x;
-{
- unsigned LONG_LONG num = big2ull(x, "unsigned long long");
-
- if (!RBIGNUM(x)->sign) return -num;
- return num;
-}
-
-LONG_LONG
-rb_big2ll(x)
- VALUE x;
-{
- unsigned LONG_LONG num = big2ull(x, "long long");
-
- if ((LONG_LONG)num < 0 && (RBIGNUM(x)->sign
- || (LONG_LONG)num != LLONG_MIN)) {
- rb_raise(rb_eRangeError, "bignum too big to convert into `long long'");
- }
- if (!RBIGNUM(x)->sign) return -(LONG_LONG)num;
- return num;
-}
-
-#endif /* HAVE_LONG_LONG */
-
-static VALUE
-dbl2big(d)
- double d;
-{
- long i = 0;
- BDIGIT c;
- BDIGIT *digits;
- VALUE z;
- double u = (d < 0)?-d:d;
-
- if (isinf(d)) {
- rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity");
- }
- if (isnan(d)) {
- rb_raise(rb_eFloatDomainError, "NaN");
- }
-
- while (!POSFIXABLE(u) || 0 != (long)u) {
- u /= (double)(BIGRAD);
- i++;
- }
- z = bignew(i, d>=0);
- digits = BDIGITS(z);
- while (i--) {
- u *= BIGRAD;
- c = (BDIGIT)u;
- u -= c;
- digits[i] = c;
- }
-
- return z;
-}
-
-VALUE
-rb_dbl2big(d)
- double d;
-{
- return bignorm(dbl2big(d));
-}
-
-double
-rb_big2dbl(x)
- VALUE x;
-{
- double d = 0.0;
- long i = RBIGNUM(x)->len;
- BDIGIT *ds = BDIGITS(x);
-
- while (i--) {
- d = ds[i] + BIGRAD*d;
- }
- if (isinf(d)) {
- rb_warn("Bignum out of Float range");
- d = HUGE_VAL;
- }
- if (!RBIGNUM(x)->sign) d = -d;
- return d;
-}
-
-/*
- * call-seq:
- * big.to_f -> float
- *
- * Converts <i>big</i> to a <code>Float</code>. If <i>big</i> doesn't
- * fit in a <code>Float</code>, the result is infinity.
- *
- */
-
-static VALUE
-rb_big_to_f(x)
- VALUE x;
-{
- return rb_float_new(rb_big2dbl(x));
-}
-
-/*
- * call-seq:
- * big <=> numeric => -1, 0, +1
- *
- * Comparison---Returns -1, 0, or +1 depending on whether <i>big</i> is
- * less than, equal to, or greater than <i>numeric</i>. This is the
- * basis for the tests in <code>Comparable</code>.
- *
- */
-
-static VALUE
-rb_big_cmp(x, y)
- VALUE x, y;
-{
- long xlen = RBIGNUM(x)->len;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- break;
-
- case T_BIGNUM:
- break;
-
- case T_FLOAT:
- return rb_dbl_cmp(rb_big2dbl(x), RFLOAT(y)->value);
-
- default:
- return rb_num_coerce_cmp(x, y);
- }
-
- if (RBIGNUM(x)->sign > RBIGNUM(y)->sign) return INT2FIX(1);
- if (RBIGNUM(x)->sign < RBIGNUM(y)->sign) return INT2FIX(-1);
- if (xlen < RBIGNUM(y)->len)
- return (RBIGNUM(x)->sign) ? INT2FIX(-1) : INT2FIX(1);
- if (xlen > RBIGNUM(y)->len)
- return (RBIGNUM(x)->sign) ? INT2FIX(1) : INT2FIX(-1);
-
- while(xlen-- && (BDIGITS(x)[xlen]==BDIGITS(y)[xlen]));
- if (-1 == xlen) return INT2FIX(0);
- return (BDIGITS(x)[xlen] > BDIGITS(y)[xlen]) ?
- (RBIGNUM(x)->sign ? INT2FIX(1) : INT2FIX(-1)) :
- (RBIGNUM(x)->sign ? INT2FIX(-1) : INT2FIX(1));
-}
-
-/*
- * call-seq:
- * big == obj => true or false
- *
- * Returns <code>true</code> only if <i>obj</i> has the same value
- * as <i>big</i>. Contrast this with <code>Bignum#eql?</code>, which
- * requires <i>obj</i> to be a <code>Bignum</code>.
- *
- * 68719476736 == 68719476736.0 #=> true
- */
-
-static VALUE
-rb_big_eq(x, y)
- VALUE x, y;
-{
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- break;
- case T_BIGNUM:
- break;
- case T_FLOAT:
- {
- volatile double a, b;
-
- a = RFLOAT(y)->value;
- b = rb_big2dbl(x);
- if (isnan(a) || isnan(b)) return Qfalse;
- return (a == b)?Qtrue:Qfalse;
- }
- default:
- return rb_equal(y, x);
- }
- if (RBIGNUM(x)->sign != RBIGNUM(y)->sign) return Qfalse;
- if (RBIGNUM(x)->len != RBIGNUM(y)->len) return Qfalse;
- if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM(y)->len) != 0) return Qfalse;
- return Qtrue;
-}
-
-/*
- * call-seq:
- * big.eql?(obj) => true or false
- *
- * Returns <code>true</code> only if <i>obj</i> is a
- * <code>Bignum</code> with the same value as <i>big</i>. Contrast this
- * with <code>Bignum#==</code>, which performs type conversions.
- *
- * 68719476736.eql?(68719476736.0) #=> false
- */
-
-static VALUE
-rb_big_eql(x, y)
- VALUE x, y;
-{
- if (TYPE(y) != T_BIGNUM) return Qfalse;
- if (RBIGNUM(x)->sign != RBIGNUM(y)->sign) return Qfalse;
- if (RBIGNUM(x)->len != RBIGNUM(y)->len) return Qfalse;
- if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM(y)->len) != 0) return Qfalse;
- return Qtrue;
-}
-
-/*
- * call-seq:
- * -big => other_big
- *
- * Unary minus (returns a new Bignum whose value is 0-big)
- */
-
-static VALUE
-rb_big_uminus(x)
- VALUE x;
-{
- VALUE z = rb_big_clone(x);
-
- RBIGNUM(z)->sign = !RBIGNUM(x)->sign;
-
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * ~big => integer
- *
- * Inverts the bits in big. As Bignums are conceptually infinite
- * length, the result acts as if it had an infinite number of one
- * bits to the left. In hex representations, this is displayed
- * as two periods to the left of the digits.
- *
- * sprintf("%X", ~0x1122334455) #=> "..FEEDDCCBBAA"
- */
-
-static VALUE
-rb_big_neg(x)
- VALUE x;
-{
- VALUE z = rb_big_clone(x);
- long i = RBIGNUM(x)->len;
- BDIGIT *ds = BDIGITS(z);
-
- if (!RBIGNUM(x)->sign) get2comp(z, Qtrue);
- while (i--) ds[i] = ~ds[i];
- if (RBIGNUM(x)->sign) get2comp(z, Qfalse);
- RBIGNUM(z)->sign = !RBIGNUM(z)->sign;
-
- return bignorm(z);
-}
-
-static VALUE
-bigsub(x, y)
- VALUE x, y;
-{
- VALUE z = 0;
- BDIGIT *zds;
- BDIGIT_DBL_SIGNED num;
- long i = RBIGNUM(x)->len;
-
- /* if x is larger than y, swap */
- if (RBIGNUM(x)->len < RBIGNUM(y)->len) {
- z = x; x = y; y = z; /* swap x y */
- }
- else if (RBIGNUM(x)->len == RBIGNUM(y)->len) {
- while (i > 0) {
- i--;
- if (BDIGITS(x)[i] > BDIGITS(y)[i]) {
- break;
- }
- if (BDIGITS(x)[i] < BDIGITS(y)[i]) {
- z = x; x = y; y = z; /* swap x y */
- break;
- }
- }
- }
-
- z = bignew(RBIGNUM(x)->len, (z == 0)?1:0);
- zds = BDIGITS(z);
-
- for (i = 0, num = 0; i < RBIGNUM(y)->len; i++) {
- num += (BDIGIT_DBL_SIGNED)BDIGITS(x)[i] - BDIGITS(y)[i];
- zds[i] = BIGLO(num);
- num = BIGDN(num);
- }
- while (num && i < RBIGNUM(x)->len) {
- num += BDIGITS(x)[i];
- zds[i++] = BIGLO(num);
- num = BIGDN(num);
- }
- while (i < RBIGNUM(x)->len) {
- zds[i] = BDIGITS(x)[i];
- i++;
- }
-
- return z;
-}
-
-static VALUE
-bigadd(x, y, sign)
- VALUE x, y;
- char sign;
-{
- VALUE z;
- BDIGIT_DBL num;
- long i, len;
-
- sign = (sign == RBIGNUM(y)->sign);
- if (RBIGNUM(x)->sign != sign) {
- if (sign) return bigsub(y, x);
- return bigsub(x, y);
- }
-
- if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
- len = RBIGNUM(x)->len + 1;
- z = x; x = y; y = z;
- }
- else {
- len = RBIGNUM(y)->len + 1;
- }
- z = bignew(len, sign);
-
- len = RBIGNUM(x)->len;
- for (i = 0, num = 0; i < len; i++) {
- num += (BDIGIT_DBL)BDIGITS(x)[i] + BDIGITS(y)[i];
- BDIGITS(z)[i] = BIGLO(num);
- num = BIGDN(num);
- }
- len = RBIGNUM(y)->len;
- while (num && i < len) {
- num += BDIGITS(y)[i];
- BDIGITS(z)[i++] = BIGLO(num);
- num = BIGDN(num);
- }
- while (i < len) {
- BDIGITS(z)[i] = BDIGITS(y)[i];
- i++;
- }
- BDIGITS(z)[i] = (BDIGIT)num;
-
- return z;
-}
-
-/*
- * call-seq:
- * big + other => Numeric
- *
- * Adds big and other, returning the result.
- */
-
-VALUE
-rb_big_plus(x, y)
- VALUE x, y;
-{
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- /* fall through */
- case T_BIGNUM:
- return bignorm(bigadd(x, y, 1));
-
- case T_FLOAT:
- return rb_float_new(rb_big2dbl(x) + RFLOAT(y)->value);
-
- default:
- return rb_num_coerce_bin(x, y);
- }
-}
-
-/*
- * call-seq:
- * big - other => Numeric
- *
- * Subtracts other from big, returning the result.
- */
-
-VALUE
-rb_big_minus(x, y)
- VALUE x, y;
-{
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- /* fall through */
- case T_BIGNUM:
- return bignorm(bigadd(x, y, 0));
-
- case T_FLOAT:
- return rb_float_new(rb_big2dbl(x) - RFLOAT(y)->value);
-
- default:
- return rb_num_coerce_bin(x, y);
- }
-}
-
-/*
- * call-seq:
- * big * other => Numeric
- *
- * Multiplies big and other, returning the result.
- */
-
-VALUE
-rb_big_mul(x, y)
- VALUE x, y;
-{
- long i, j;
- BDIGIT_DBL n = 0;
- VALUE z;
- BDIGIT *zds;
-
- if (FIXNUM_P(x)) x = rb_int2big(FIX2LONG(x));
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- break;
-
- case T_BIGNUM:
- break;
-
- case T_FLOAT:
- return rb_float_new(rb_big2dbl(x) * RFLOAT(y)->value);
-
- default:
- return rb_num_coerce_bin(x, y);
- }
-
- j = RBIGNUM(x)->len + RBIGNUM(y)->len + 1;
- z = bignew(j, RBIGNUM(x)->sign==RBIGNUM(y)->sign);
- zds = BDIGITS(z);
- while (j--) zds[j] = 0;
- for (i = 0; i < RBIGNUM(x)->len; i++) {
- BDIGIT_DBL dd = BDIGITS(x)[i];
- if (dd == 0) continue;
- n = 0;
- for (j = 0; j < RBIGNUM(y)->len; j++) {
- BDIGIT_DBL ee = n + (BDIGIT_DBL)dd * BDIGITS(y)[j];
- n = zds[i + j] + ee;
- if (ee) zds[i + j] = BIGLO(n);
- n = BIGDN(n);
- }
- if (n) {
- zds[i + j] = n;
- }
- }
-
- return bignorm(z);
-}
-
-static void
-bigdivrem(x, y, divp, modp)
- VALUE x, y;
- VALUE *divp, *modp;
-{
- long nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len;
- long i, j;
- VALUE yy, z;
- BDIGIT *xds, *yds, *zds, *tds;
- BDIGIT_DBL t2;
- BDIGIT_DBL_SIGNED num;
- BDIGIT dd, q;
-
- if (BIGZEROP(y)) rb_num_zerodiv();
- yds = BDIGITS(y);
- if (nx < ny || (nx == ny && BDIGITS(x)[nx - 1] < BDIGITS(y)[ny - 1])) {
- if (divp) *divp = rb_int2big(0);
- if (modp) *modp = x;
- return;
- }
- xds = BDIGITS(x);
- if (ny == 1) {
- dd = yds[0];
- z = rb_big_clone(x);
- zds = BDIGITS(z);
- t2 = 0; i = nx;
- while (i--) {
- t2 = BIGUP(t2) + zds[i];
- zds[i] = (BDIGIT)(t2 / dd);
- t2 %= dd;
- }
- RBIGNUM(z)->sign = RBIGNUM(x)->sign==RBIGNUM(y)->sign;
- if (modp) {
- *modp = rb_uint2big((unsigned long)t2);
- RBIGNUM(*modp)->sign = RBIGNUM(x)->sign;
- }
- if (divp) *divp = z;
- return;
- }
- z = bignew(nx==ny?nx+2:nx+1, RBIGNUM(x)->sign==RBIGNUM(y)->sign);
- zds = BDIGITS(z);
- if (nx==ny) zds[nx+1] = 0;
- while (!yds[ny-1]) ny--;
-
- dd = 0;
- q = yds[ny-1];
- while ((q & (1<<(BITSPERDIG-1))) == 0) {
- q <<= 1;
- dd++;
- }
- if (dd) {
- yy = rb_big_clone(y);
- tds = BDIGITS(yy);
- j = 0;
- t2 = 0;
- while (j<ny) {
- t2 += (BDIGIT_DBL)yds[j]<<dd;
- tds[j++] = BIGLO(t2);
- t2 = BIGDN(t2);
- }
- yds = tds;
- j = 0;
- t2 = 0;
- while (j<nx) {
- t2 += (BDIGIT_DBL)xds[j]<<dd;
- zds[j++] = BIGLO(t2);
- t2 = BIGDN(t2);
- }
- zds[j] = (BDIGIT)t2;
- }
- else {
- zds[nx] = 0;
- j = nx;
- while (j--) zds[j] = xds[j];
- }
-
- j = nx==ny?nx+1:nx;
- do {
- if (zds[j] == yds[ny-1]) q = BIGRAD-1;
- else q = (BDIGIT)((BIGUP(zds[j]) + zds[j-1])/yds[ny-1]);
- if (q) {
- i = 0; num = 0; t2 = 0;
- do { /* multiply and subtract */
- BDIGIT_DBL ee;
- t2 += (BDIGIT_DBL)yds[i] * q;
- ee = num - BIGLO(t2);
- num = (BDIGIT_DBL)zds[j - ny + i] + ee;
- if (ee) zds[j - ny + i] = BIGLO(num);
- num = BIGDN(num);
- t2 = BIGDN(t2);
- } while (++i < ny);
- num += zds[j - ny + i] - t2;/* borrow from high digit; don't update */
- while (num) { /* "add back" required */
- i = 0; num = 0; q--;
- do {
- BDIGIT_DBL ee = num + yds[i];
- num = (BDIGIT_DBL)zds[j - ny + i] + ee;
- if (ee) zds[j - ny + i] = BIGLO(num);
- num = BIGDN(num);
- } while (++i < ny);
- num--;
- }
- }
- zds[j] = q;
- } while (--j >= ny);
- if (divp) { /* move quotient down in z */
- *divp = rb_big_clone(z);
- zds = BDIGITS(*divp);
- j = (nx==ny ? nx+2 : nx+1) - ny;
- for (i = 0;i < j;i++) zds[i] = zds[i+ny];
- RBIGNUM(*divp)->len = i;
- }
- if (modp) { /* normalize remainder */
- *modp = rb_big_clone(z);
- zds = BDIGITS(*modp);
- while (--ny && !zds[ny]); ++ny;
- if (dd) {
- t2 = 0; i = ny;
- while(i--) {
- t2 = (t2 | zds[i]) >> dd;
- q = zds[i];
- zds[i] = BIGLO(t2);
- t2 = BIGUP(q);
- }
- }
- RBIGNUM(*modp)->len = ny;
- RBIGNUM(*modp)->sign = RBIGNUM(x)->sign;
- }
-}
-
-static void
-bigdivmod(x, y, divp, modp)
- VALUE x, y;
- VALUE *divp, *modp;
-{
- VALUE mod;
-
- bigdivrem(x, y, divp, &mod);
- if (RBIGNUM(x)->sign != RBIGNUM(y)->sign && !BIGZEROP(mod)) {
- if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
- if (modp) *modp = bigadd(mod, y, 1);
- }
- else {
- if (divp) *divp = *divp;
- if (modp) *modp = mod;
- }
-}
-
-/*
- * call-seq:
- * big / other => Numeric
- * big.div(other) => Numeric
- *
- * Divides big by other, returning the result.
- */
-
-static VALUE
-rb_big_div(x, y)
- VALUE x, y;
-{
- VALUE z;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- break;
-
- case T_BIGNUM:
- break;
-
- case T_FLOAT:
- return rb_float_new(rb_big2dbl(x) / RFLOAT(y)->value);
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- bigdivmod(x, y, &z, 0);
-
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big % other => Numeric
- * big.modulo(other) => Numeric
- *
- * Returns big modulo other. See Numeric.divmod for more
- * information.
- */
-
-static VALUE
-rb_big_modulo(x, y)
- VALUE x, y;
-{
- VALUE z;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- break;
-
- case T_BIGNUM:
- break;
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- bigdivmod(x, y, 0, &z);
-
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big.remainder(numeric) => number
- *
- * Returns the remainder after dividing <i>big</i> by <i>numeric</i>.
- *
- * -1234567890987654321.remainder(13731) #=> -6966
- * -1234567890987654321.remainder(13731.24) #=> -9906.22531493148
- */
-static VALUE
-rb_big_remainder(x, y)
- VALUE x, y;
-{
- VALUE z;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- break;
-
- case T_BIGNUM:
- break;
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- bigdivrem(x, y, 0, &z);
-
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big.divmod(numeric) => array
- *
- * See <code>Numeric#divmod</code>.
- *
- */
-VALUE
-rb_big_divmod(x, y)
- VALUE x, y;
-{
- VALUE div, mod;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- break;
-
- case T_BIGNUM:
- break;
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- bigdivmod(x, y, &div, &mod);
-
- return rb_assoc_new(bignorm(div), bignorm(mod));
-}
-
-/*
- * call-seq:
- * big.quo(numeric) -> float
- *
- * Returns the floating point result of dividing <i>big</i> by
- * <i>numeric</i>.
- *
- * -1234567890987654321.quo(13731) #=> -89910996357705.5
- * -1234567890987654321.quo(13731.24) #=> -89909424858035.7
- *
- */
-
-static VALUE
-rb_big_quo(x, y)
- VALUE x, y;
-{
- double dx = rb_big2dbl(x);
- double dy;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- dy = (double)FIX2LONG(y);
- break;
-
- case T_BIGNUM:
- dy = rb_big2dbl(y);
- break;
-
- case T_FLOAT:
- dy = RFLOAT(y)->value;
- break;
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- return rb_float_new(dx / dy);
-}
-
-/*
- * call-seq:
- * big ** exponent #=> numeric
- *
- * Raises _big_ to the _exponent_ power (which may be an integer, float,
- * or anything that will coerce to a number). The result may be
- * a Fixnum, Bignum, or Float
- *
- * 123456789 ** 2 #=> 15241578750190521
- * 123456789 ** 1.2 #=> 5126464716.09932
- * 123456789 ** -2 #=> 6.5610001194102e-17
- */
-
-VALUE
-rb_big_pow(x, y)
- VALUE x, y;
-{
- double d;
- long yy;
-
- if (y == INT2FIX(0)) return INT2FIX(1);
- switch (TYPE(y)) {
- case T_FLOAT:
- d = RFLOAT(y)->value;
- break;
-
- case T_BIGNUM:
- rb_warn("in a**b, b may be too big");
- d = rb_big2dbl(y);
- break;
-
- case T_FIXNUM:
- yy = FIX2LONG(y);
- if (yy > 0) {
- VALUE z = x;
-
- for (;;) {
- yy -= 1;
- if (yy == 0) break;
- while (yy % 2 == 0) {
- yy /= 2;
- x = rb_big_mul(x, x);
- }
- z = rb_big_mul(z, x);
- }
- return bignorm(z);
- }
- d = (double)yy;
- break;
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- return rb_float_new(pow(rb_big2dbl(x), d));
-}
-
-/*
- * call-seq:
- * big & numeric => integer
- *
- * Performs bitwise +and+ between _big_ and _numeric_.
- */
-
-VALUE
-rb_big_and(xx, yy)
- VALUE xx, yy;
-{
- volatile VALUE x, y, z;
- BDIGIT *ds1, *ds2, *zds;
- long i, l1, l2;
- char sign;
-
- x = xx;
- y = rb_to_int(yy);
- if (FIXNUM_P(y)) {
- y = rb_int2big(FIX2LONG(y));
- }
- if (!RBIGNUM(y)->sign) {
- y = rb_big_clone(y);
- get2comp(y, Qtrue);
- }
- if (!RBIGNUM(x)->sign) {
- x = rb_big_clone(x);
- get2comp(x, Qtrue);
- }
- if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
- l1 = RBIGNUM(y)->len;
- l2 = RBIGNUM(x)->len;
- ds1 = BDIGITS(y);
- ds2 = BDIGITS(x);
- sign = RBIGNUM(y)->sign;
- }
- else {
- l1 = RBIGNUM(x)->len;
- l2 = RBIGNUM(y)->len;
- ds1 = BDIGITS(x);
- ds2 = BDIGITS(y);
- sign = RBIGNUM(x)->sign;
- }
- z = bignew(l2, RBIGNUM(x)->sign || RBIGNUM(y)->sign);
- zds = BDIGITS(z);
-
- for (i=0; i<l1; i++) {
- zds[i] = ds1[i] & ds2[i];
- }
- for (; i<l2; i++) {
- zds[i] = sign?0:ds2[i];
- }
- if (!RBIGNUM(z)->sign) get2comp(z, Qfalse);
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big | numeric => integer
- *
- * Performs bitwise +or+ between _big_ and _numeric_.
- */
-
-VALUE
-rb_big_or(xx, yy)
- VALUE xx, yy;
-{
- volatile VALUE x, y, z;
- BDIGIT *ds1, *ds2, *zds;
- long i, l1, l2;
- char sign;
-
- x = xx;
- y = rb_to_int(yy);
- if (FIXNUM_P(y)) {
- y = rb_int2big(FIX2LONG(y));
- }
-
- if (!RBIGNUM(y)->sign) {
- y = rb_big_clone(y);
- get2comp(y, Qtrue);
- }
- if (!RBIGNUM(x)->sign) {
- x = rb_big_clone(x);
- get2comp(x, Qtrue);
- }
- if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
- l1 = RBIGNUM(y)->len;
- l2 = RBIGNUM(x)->len;
- ds1 = BDIGITS(y);
- ds2 = BDIGITS(x);
- sign = RBIGNUM(y)->sign;
- }
- else {
- l1 = RBIGNUM(x)->len;
- l2 = RBIGNUM(y)->len;
- ds1 = BDIGITS(x);
- ds2 = BDIGITS(y);
- sign = RBIGNUM(x)->sign;
- }
- z = bignew(l2, RBIGNUM(x)->sign && RBIGNUM(y)->sign);
- zds = BDIGITS(z);
-
- for (i=0; i<l1; i++) {
- zds[i] = ds1[i] | ds2[i];
- }
- for (; i<l2; i++) {
- zds[i] = sign?ds2[i]:(BIGRAD-1);
- }
- if (!RBIGNUM(z)->sign) get2comp(z, Qfalse);
-
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big ^ numeric => integer
- *
- * Performs bitwise +exclusive or+ between _big_ and _numeric_.
- */
-
-VALUE
-rb_big_xor(xx, yy)
- VALUE xx, yy;
-{
- volatile VALUE x, y;
- VALUE z;
- BDIGIT *ds1, *ds2, *zds;
- long i, l1, l2;
- char sign;
-
- x = xx;
- y = rb_to_int(yy);
- if (FIXNUM_P(y)) {
- y = rb_int2big(FIX2LONG(y));
- }
-
- if (!RBIGNUM(y)->sign) {
- y = rb_big_clone(y);
- get2comp(y, Qtrue);
- }
- if (!RBIGNUM(x)->sign) {
- x = rb_big_clone(x);
- get2comp(x, Qtrue);
- }
- if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
- l1 = RBIGNUM(y)->len;
- l2 = RBIGNUM(x)->len;
- ds1 = BDIGITS(y);
- ds2 = BDIGITS(x);
- sign = RBIGNUM(y)->sign;
- }
- else {
- l1 = RBIGNUM(x)->len;
- l2 = RBIGNUM(y)->len;
- ds1 = BDIGITS(x);
- ds2 = BDIGITS(y);
- sign = RBIGNUM(x)->sign;
- }
- RBIGNUM(x)->sign = RBIGNUM(x)->sign?1:0;
- RBIGNUM(y)->sign = RBIGNUM(y)->sign?1:0;
- z = bignew(l2, !(RBIGNUM(x)->sign ^ RBIGNUM(y)->sign));
- zds = BDIGITS(z);
-
- for (i=0; i<l1; i++) {
- zds[i] = ds1[i] ^ ds2[i];
- }
- for (; i<l2; i++) {
- zds[i] = sign?ds2[i]:~ds2[i];
- }
- if (!RBIGNUM(z)->sign) get2comp(z, Qfalse);
-
- return bignorm(z);
-}
-
-static VALUE rb_big_rshift _((VALUE,VALUE));
-
-/*
- * call-seq:
- * big << numeric => integer
- *
- * Shifts big left _numeric_ positions (right if _numeric_ is negative).
- */
-
-VALUE
-rb_big_lshift(x, y)
- VALUE x, y;
-{
- BDIGIT *xds, *zds;
- int shift = NUM2INT(y);
- int s1 = shift/BITSPERDIG;
- int s2 = shift%BITSPERDIG;
- VALUE z;
- BDIGIT_DBL num = 0;
- long len, i;
-
- if (shift < 0) return rb_big_rshift(x, INT2FIX(-shift));
- len = RBIGNUM(x)->len;
- z = bignew(len+s1+1, RBIGNUM(x)->sign);
- zds = BDIGITS(z);
- for (i=0; i<s1; i++) {
- *zds++ = 0;
- }
- xds = BDIGITS(x);
- for (i=0; i<len; i++) {
- num = num | (BDIGIT_DBL)*xds++<<s2;
- *zds++ = BIGLO(num);
- num = BIGDN(num);
- }
- *zds = BIGLO(num);
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big >> numeric => integer
- *
- * Shifts big right _numeric_ positions (left if _numeric_ is negative).
- */
-
-static VALUE
-rb_big_rshift(x, y)
- VALUE x, y;
-{
- BDIGIT *xds, *zds;
- int shift = NUM2INT(y);
- long s1 = shift/BITSPERDIG;
- long s2 = shift%BITSPERDIG;
- VALUE z;
- BDIGIT_DBL num = 0;
- long i, j;
-
- if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift));
-
- if (s1 > RBIGNUM(x)->len) {
- if (RBIGNUM(x)->sign)
- return INT2FIX(0);
- else
- return INT2FIX(-1);
- }
- if (!RBIGNUM(x)->sign) {
- x = rb_big_clone(x);
- get2comp(x, Qtrue);
- }
- xds = BDIGITS(x);
- i = RBIGNUM(x)->len; j = i - s1;
- z = bignew(j, RBIGNUM(x)->sign);
- if (!RBIGNUM(x)->sign) {
- num = ((BDIGIT_DBL)~0) << BITSPERDIG;
- }
- zds = BDIGITS(z);
- while (i--, j--) {
- num = (num | xds[i]) >> s2;
- zds[j] = BIGLO(num);
- num = BIGUP(xds[i]);
- }
- if (!RBIGNUM(x)->sign) {
- get2comp(z, Qfalse);
- }
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big[n] -> 0, 1
- *
- * Bit Reference---Returns the <em>n</em>th bit in the (assumed) binary
- * representation of <i>big</i>, where <i>big</i>[0] is the least
- * significant bit.
- *
- * a = 9**15
- * 50.downto(0) do |n|
- * print a[n]
- * end
- *
- * <em>produces:</em>
- *
- * 000101110110100000111000011110010100111100010111001
- *
- */
-
-static VALUE
-rb_big_aref(x, y)
- VALUE x, y;
-{
- BDIGIT *xds;
- int shift;
- long s1, s2;
-
- if (TYPE(y) == T_BIGNUM) {
- if (!RBIGNUM(y)->sign || RBIGNUM(x)->sign)
- return INT2FIX(0);
- return INT2FIX(1);
- }
- shift = NUM2INT(y);
- if (shift < 0) return INT2FIX(0);
- s1 = shift/BITSPERDIG;
- s2 = shift%BITSPERDIG;
-
- if (!RBIGNUM(x)->sign) {
- if (s1 >= RBIGNUM(x)->len) return INT2FIX(1);
- x = rb_big_clone(x);
- get2comp(x, Qtrue);
- }
- else {
- if (s1 >= RBIGNUM(x)->len) return INT2FIX(0);
- }
- xds = BDIGITS(x);
- if (xds[s1] & (1<<s2))
- return INT2FIX(1);
- return INT2FIX(0);
-}
-
-/*
- * call-seq:
- * big.hash => fixnum
- *
- * Compute a hash based on the value of _big_.
- */
-
-static VALUE
-rb_big_hash(x)
- VALUE x;
-{
- long i, len, key;
- BDIGIT *digits;
-
- key = 0; digits = BDIGITS(x); len = RBIGNUM(x)->len;
- for (i=0; i<len; i++) {
- key ^= *digits++;
- }
- return LONG2FIX(key);
-}
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-rb_big_coerce(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- return rb_assoc_new(rb_int2big(FIX2LONG(y)), x);
- }
- else {
- rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
- rb_obj_classname(y));
- }
- /* not reached */
- return Qnil;
-}
-
-/*
- * call-seq:
- * big.abs -> aBignum
- *
- * Returns the absolute value of <i>big</i>.
- *
- * -1234567890987654321.abs #=> 1234567890987654321
- */
-
-static VALUE
-rb_big_abs(x)
- VALUE x;
-{
- if (!RBIGNUM(x)->sign) {
- x = rb_big_clone(x);
- RBIGNUM(x)->sign = 1;
- }
- return x;
-}
-
-VALUE
-rb_big_rand(max, rand_buf)
- VALUE max;
- double *rand_buf;
-{
- VALUE v;
- long len = RBIGNUM(max)->len;
-
- if (BIGZEROP(max)) {
- return rb_float_new(rand_buf[0]);
- }
- v = bignew(len,1);
- len--;
- BDIGITS(v)[len] = BDIGITS(max)[len] * rand_buf[len];
- while (len--) {
- BDIGITS(v)[len] = ((BDIGIT)~0) * rand_buf[len];
- }
-
- return v;
-}
-
-/*
- * call-seq:
- * big.size -> integer
- *
- * Returns the number of bytes in the machine representation of
- * <i>big</i>.
- *
- * (256**10 - 1).size #=> 12
- * (256**20 - 1).size #=> 20
- * (256**40 - 1).size #=> 40
- */
-
-static VALUE
-rb_big_size(big)
- VALUE big;
-{
- return LONG2FIX(RBIGNUM(big)->len*SIZEOF_BDIGITS);
-}
-
-/*
- * Bignum objects hold integers outside the range of
- * Fixnum. Bignum objects are created
- * automatically when integer calculations would otherwise overflow a
- * Fixnum. When a calculation involving
- * Bignum objects returns a result that will fit in a
- * Fixnum, the result is automatically converted.
- *
- * For the purposes of the bitwise operations and <code>[]</code>, a
- * Bignum is treated as if it were an infinite-length
- * bitstring with 2's complement representation.
- *
- * While Fixnum values are immediate, Bignum
- * objects are not---assignment and parameter passing work with
- * references to objects, not the objects themselves.
- *
- */
-
-void
-Init_Bignum()
-{
- rb_cBignum = rb_define_class("Bignum", rb_cInteger);
-
- rb_define_method(rb_cBignum, "to_s", rb_big_to_s, -1);
- rb_define_method(rb_cBignum, "coerce", rb_big_coerce, 1);
- rb_define_method(rb_cBignum, "-@", rb_big_uminus, 0);
- rb_define_method(rb_cBignum, "+", rb_big_plus, 1);
- rb_define_method(rb_cBignum, "-", rb_big_minus, 1);
- rb_define_method(rb_cBignum, "*", rb_big_mul, 1);
- rb_define_method(rb_cBignum, "/", rb_big_div, 1);
- rb_define_method(rb_cBignum, "%", rb_big_modulo, 1);
- rb_define_method(rb_cBignum, "div", rb_big_div, 1);
- rb_define_method(rb_cBignum, "divmod", rb_big_divmod, 1);
- rb_define_method(rb_cBignum, "modulo", rb_big_modulo, 1);
- rb_define_method(rb_cBignum, "remainder", rb_big_remainder, 1);
- rb_define_method(rb_cBignum, "quo", rb_big_quo, 1);
- rb_define_method(rb_cBignum, "**", rb_big_pow, 1);
- rb_define_method(rb_cBignum, "&", rb_big_and, 1);
- rb_define_method(rb_cBignum, "|", rb_big_or, 1);
- rb_define_method(rb_cBignum, "^", rb_big_xor, 1);
- rb_define_method(rb_cBignum, "~", rb_big_neg, 0);
- rb_define_method(rb_cBignum, "<<", rb_big_lshift, 1);
- rb_define_method(rb_cBignum, ">>", rb_big_rshift, 1);
- rb_define_method(rb_cBignum, "[]", rb_big_aref, 1);
-
- rb_define_method(rb_cBignum, "<=>", rb_big_cmp, 1);
- rb_define_method(rb_cBignum, "==", rb_big_eq, 1);
- rb_define_method(rb_cBignum, "eql?", rb_big_eql, 1);
- rb_define_method(rb_cBignum, "hash", rb_big_hash, 0);
- rb_define_method(rb_cBignum, "to_f", rb_big_to_f, 0);
- rb_define_method(rb_cBignum, "abs", rb_big_abs, 0);
- rb_define_method(rb_cBignum, "size", rb_big_size, 0);
-}
-/**********************************************************************
-
- class.c -
-
- $Author: matz $
- $Date: 2005/03/04 06:47:45 $
- created at: Tue Aug 10 15:05:44 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include "rubysig.h"
-#include "node.h"
-#include "st.h"
-#include <ctype.h>
-
-extern st_table *rb_class_tbl;
-
-VALUE
-rb_class_boot(super)
- VALUE super;
-{
- NEWOBJ(klass, struct RClass);
- OBJSETUP(klass, rb_cClass, T_CLASS);
-
- klass->super = super;
- klass->iv_tbl = 0;
- klass->m_tbl = 0; /* safe GC */
- klass->m_tbl = st_init_numtable();
-
- OBJ_INFECT(klass, super);
- return (VALUE)klass;
-}
-
-void
-rb_check_inheritable(super)
- VALUE super;
-{
- if (TYPE(super) != T_CLASS) {
- rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
- rb_obj_classname(super));
- }
- if (RBASIC(super)->flags & FL_SINGLETON) {
- rb_raise(rb_eTypeError, "can't make subclass of singleton class");
- }
-}
-
-VALUE
-rb_class_new(super)
- VALUE super;
-{
- Check_Type(super, T_CLASS);
- rb_check_inheritable(super);
- if (super == rb_cClass) {
- rb_raise(rb_eTypeError, "can't make subclass of Class");
- }
- return rb_class_boot(super);
-}
-
-static int
-clone_method(mid, body, tbl)
- ID mid;
- NODE *body;
- st_table *tbl;
-{
- st_insert(tbl, mid, (st_data_t)NEW_METHOD(body->nd_body, body->nd_noex));
- return ST_CONTINUE;
-}
-
-/* :nodoc: */
-VALUE
-rb_mod_init_copy(clone, orig)
- VALUE clone, orig;
-{
- rb_obj_init_copy(clone, orig);
- if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
- RBASIC(clone)->klass = rb_singleton_class_clone(orig);
- }
- RCLASS(clone)->super = RCLASS(orig)->super;
- if (RCLASS(orig)->iv_tbl) {
- ID id;
-
- RCLASS(clone)->iv_tbl = st_copy(RCLASS(orig)->iv_tbl);
- id = rb_intern("__classpath__");
- st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0);
- id = rb_intern("__classid__");
- st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0);
- }
- if (RCLASS(orig)->m_tbl) {
- RCLASS(clone)->m_tbl = st_init_numtable();
- st_foreach(RCLASS(orig)->m_tbl, clone_method,
- (st_data_t)RCLASS(clone)->m_tbl);
- }
-
- return clone;
-}
-
-/* :nodoc: */
-VALUE
-rb_class_init_copy(clone, orig)
- VALUE clone, orig;
-{
- if (RCLASS(clone)->super != 0) {
- rb_raise(rb_eTypeError, "already initialized class");
- }
- return rb_mod_init_copy(clone, orig);
-}
-
-VALUE
-rb_singleton_class_clone(obj)
- VALUE obj;
-{
- VALUE klass = RBASIC(obj)->klass;
-
- if (!FL_TEST(klass, FL_SINGLETON))
- return klass;
- else {
- /* copy singleton(unnamed) class */
- NEWOBJ(clone, struct RClass);
- OBJSETUP(clone, 0, RBASIC(klass)->flags);
-
- if (BUILTIN_TYPE(obj) == T_CLASS) {
- RBASIC(clone)->klass = (VALUE)clone;
- }
- else {
- RBASIC(clone)->klass = rb_singleton_class_clone(klass);
- }
-
- clone->super = RCLASS(klass)->super;
- clone->iv_tbl = 0;
- clone->m_tbl = 0;
- if (RCLASS(klass)->iv_tbl) {
- clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
- }
- clone->m_tbl = st_init_numtable();
- st_foreach(RCLASS(klass)->m_tbl, clone_method,
- (st_data_t)clone->m_tbl);
- rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
- FL_SET(clone, FL_SINGLETON);
- return (VALUE)clone;
- }
-}
-
-void
-rb_singleton_class_attached(klass, obj)
- VALUE klass, obj;
-{
- if (FL_TEST(klass, FL_SINGLETON)) {
- if (!RCLASS(klass)->iv_tbl) {
- RCLASS(klass)->iv_tbl = st_init_numtable();
- }
- st_insert(RCLASS(klass)->iv_tbl, rb_intern("__attached__"), obj);
- }
-}
-
-VALUE
-rb_make_metaclass(obj, super)
- VALUE obj, super;
-{
- if (BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) {
- return RBASIC(obj)->klass = rb_cClass;
- }
- else {
- VALUE metasuper;
- VALUE klass = rb_class_boot(super);
-
- FL_SET(klass, FL_SINGLETON);
- RBASIC(obj)->klass = klass;
- rb_singleton_class_attached(klass, obj);
-
- metasuper = RBASIC(rb_class_real(super))->klass;
- /* metaclass of a superclass may be NULL at boot time */
- if (metasuper) {
- RBASIC(klass)->klass = metasuper;
- }
- return klass;
- }
-}
-
-VALUE
-rb_define_class_id(id, super)
- ID id;
- VALUE super;
-{
- VALUE klass;
-
- if (!super) super = rb_cObject;
- klass = rb_class_new(super);
- rb_make_metaclass(klass, RBASIC(super)->klass);
-
- return klass;
-}
-
-VALUE
-rb_class_inherited(super, klass)
- VALUE super, klass;
-{
- if (!super) super = rb_cObject;
- return rb_funcall(super, rb_intern("inherited"), 1, klass);
-}
-
-VALUE
-rb_define_class(name, super)
- const char *name;
- VALUE super;
-{
- VALUE klass;
- ID id;
-
- id = rb_intern(name);
- if (rb_const_defined(rb_cObject, id)) {
- klass = rb_const_get(rb_cObject, id);
- if (TYPE(klass) != T_CLASS) {
- rb_raise(rb_eTypeError, "%s is not a class", name);
- }
- if (rb_class_real(RCLASS(klass)->super) != super) {
- rb_name_error(id, "%s is already defined", name);
- }
- return klass;
- }
- if (!super) {
- rb_warn("no super class for `%s', Object assumed", name);
- }
- klass = rb_define_class_id(id, super);
- st_add_direct(rb_class_tbl, id, klass);
- rb_name_class(klass, id);
- rb_const_set(rb_cObject, id, klass);
- rb_class_inherited(super, klass);
-
- return klass;
-}
-
-VALUE
-rb_define_class_under(outer, name, super)
- VALUE outer;
- const char *name;
- VALUE super;
-{
- VALUE klass;
- ID id;
-
- id = rb_intern(name);
- if (rb_const_defined_at(outer, id)) {
- klass = rb_const_get_at(outer, id);
- if (TYPE(klass) != T_CLASS) {
- rb_raise(rb_eTypeError, "%s is not a class", name);
- }
- if (rb_class_real(RCLASS(klass)->super) != super) {
- rb_name_error(id, "%s is already defined", name);
- }
- return klass;
- }
- if (!super) {
- rb_warn("no super class for `%s::%s', Object assumed",
- rb_class2name(outer), name);
- }
- klass = rb_define_class_id(id, super);
- rb_set_class_path(klass, outer, name);
- rb_const_set(outer, id, klass);
- rb_class_inherited(super, klass);
-
- return klass;
-}
-
-VALUE
-rb_module_new()
-{
- NEWOBJ(mdl, struct RClass);
- OBJSETUP(mdl, rb_cModule, T_MODULE);
-
- mdl->super = 0;
- mdl->iv_tbl = 0;
- mdl->m_tbl = 0;
- mdl->m_tbl = st_init_numtable();
-
- return (VALUE)mdl;
-}
-
-VALUE
-rb_define_module_id(id)
- ID id;
-{
- VALUE mdl;
-
- mdl = rb_module_new();
- rb_name_class(mdl, id);
-
- return mdl;
-}
-
-VALUE
-rb_define_module(name)
- const char *name;
-{
- VALUE module;
- ID id;
-
- id = rb_intern(name);
- if (rb_const_defined(rb_cObject, id)) {
- module = rb_const_get(rb_cObject, id);
- if (TYPE(module) == T_MODULE)
- return module;
- rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
- }
- module = rb_define_module_id(id);
- st_add_direct(rb_class_tbl, id, module);
- rb_const_set(rb_cObject, id, module);
-
- return module;
-}
-
-VALUE
-rb_define_module_under(outer, name)
- VALUE outer;
- const char *name;
-{
- VALUE module;
- ID id;
-
- id = rb_intern(name);
- if (rb_const_defined_at(outer, id)) {
- module = rb_const_get_at(outer, id);
- if (TYPE(module) == T_MODULE)
- return module;
- rb_raise(rb_eTypeError, "%s::%s is not a module",
- rb_class2name(outer), rb_obj_classname(module));
- }
- module = rb_define_module_id(id);
- rb_const_set(outer, id, module);
- rb_set_class_path(module, outer, name);
-
- return module;
-}
-
-static VALUE
-include_class_new(module, super)
- VALUE module, super;
-{
- NEWOBJ(klass, struct RClass);
- OBJSETUP(klass, rb_cClass, T_ICLASS);
-
- if (BUILTIN_TYPE(module) == T_ICLASS) {
- module = RBASIC(module)->klass;
- }
- if (!RCLASS(module)->iv_tbl) {
- RCLASS(module)->iv_tbl = st_init_numtable();
- }
- klass->iv_tbl = RCLASS(module)->iv_tbl;
- klass->m_tbl = RCLASS(module)->m_tbl;
- klass->super = super;
- if (TYPE(module) == T_ICLASS) {
- RBASIC(klass)->klass = RBASIC(module)->klass;
- }
- else {
- RBASIC(klass)->klass = module;
- }
- OBJ_INFECT(klass, module);
- OBJ_INFECT(klass, super);
-
- return (VALUE)klass;
-}
-
-void
-rb_include_module(klass, module)
- VALUE klass, module;
-{
- VALUE p, c;
- int changed = 0;
-
- rb_frozen_class_p(klass);
- if (!OBJ_TAINTED(klass)) {
- rb_secure(4);
- }
-
- if (NIL_P(module)) return;
- if (klass == module) return;
-
- if (TYPE(module) != T_MODULE) {
- Check_Type(module, T_MODULE);
- }
-
- OBJ_INFECT(klass, module);
- c = klass;
- while (module) {
- int superclass_seen = Qfalse;
-
- if (RCLASS(klass)->m_tbl == RCLASS(module)->m_tbl)
- rb_raise(rb_eArgError, "cyclic include detected");
- /* ignore if the module included already in superclasses */
- for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) {
- switch (BUILTIN_TYPE(p)) {
- case T_ICLASS:
- if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) {
- if (!superclass_seen) {
- c = p; /* move insertion point */
- }
- goto skip;
- }
- break;
- case T_CLASS:
- superclass_seen = Qtrue;
- break;
- }
- }
- c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super);
- changed = 1;
- skip:
- module = RCLASS(module)->super;
- }
- if (changed) rb_clear_cache();
-}
-
-/*
- * call-seq:
- * mod.included_modules -> array
- *
- * Returns the list of modules included in <i>mod</i>.
- *
- * module Mixin
- * end
- *
- * module Outer
- * include Mixin
- * end
- *
- * Mixin.included_modules #=> []
- * Outer.included_modules #=> [Mixin]
- */
-
-VALUE
-rb_mod_included_modules(mod)
- VALUE mod;
-{
- VALUE ary = rb_ary_new();
- VALUE p;
-
- for (p = RCLASS(mod)->super; p; p = RCLASS(p)->super) {
- if (BUILTIN_TYPE(p) == T_ICLASS) {
- rb_ary_push(ary, RBASIC(p)->klass);
- }
- }
- return ary;
-}
-
-/*
- * call-seq:
- * mod.include?(module) => true or false
- *
- * Returns <code>true</code> if <i>module</i> is included in
- * <i>mod</i> or one of <i>mod</i>'s ancestors.
- *
- * module A
- * end
- * class B
- * include A
- * end
- * class C < B
- * end
- * B.include?(A) #=> true
- * C.include?(A) #=> true
- * A.include?(A) #=> false
- */
-
-VALUE
-rb_mod_include_p(mod, mod2)
- VALUE mod;
- VALUE mod2;
-{
- VALUE p;
-
- Check_Type(mod2, T_MODULE);
- for (p = RCLASS(mod)->super; p; p = RCLASS(p)->super) {
- if (BUILTIN_TYPE(p) == T_ICLASS) {
- if (RBASIC(p)->klass == mod2) return Qtrue;
- }
- }
- return Qfalse;
-}
-
-/*
- * call-seq:
- * mod.ancestors -> array
- *
- * Returns a list of modules included in <i>mod</i> (including
- * <i>mod</i> itself).
- *
- * module Mod
- * include Math
- * include Comparable
- * end
- *
- * Mod.ancestors #=> [Mod, Comparable, Math]
- * Math.ancestors #=> [Math]
- */
-
-VALUE
-rb_mod_ancestors(mod)
- VALUE mod;
-{
- VALUE p, ary = rb_ary_new();
-
- for (p = mod; p; p = RCLASS(p)->super) {
- if (FL_TEST(p, FL_SINGLETON))
- continue;
- if (BUILTIN_TYPE(p) == T_ICLASS) {
- rb_ary_push(ary, RBASIC(p)->klass);
- }
- else {
- rb_ary_push(ary, p);
- }
- }
- return ary;
-}
-
-#define VISI(x) ((x)&NOEX_MASK)
-#define VISI_CHECK(x,f) (VISI(x) == (f))
-
-static int
-ins_methods_push(name, type, ary, visi)
- ID name;
- long type;
- VALUE ary;
- long visi;
-{
- if (type == -1) return ST_CONTINUE;
- switch (visi) {
- case NOEX_PRIVATE:
- case NOEX_PROTECTED:
- case NOEX_PUBLIC:
- visi = (type == visi);
- break;
- default:
- visi = (type != NOEX_PRIVATE);
- break;
- }
- if (visi) {
- rb_ary_push(ary, rb_str_new2(rb_id2name(name)));
- }
- return ST_CONTINUE;
-}
-
-static int
-ins_methods_i(name, type, ary)
- ID name;
- long type;
- VALUE ary;
-{
- return ins_methods_push(name, type, ary, -1); /* everything but private */
-}
-
-static int
-ins_methods_prot_i(name, type, ary)
- ID name;
- long type;
- VALUE ary;
-{
- return ins_methods_push(name, type, ary, NOEX_PROTECTED);
-}
-
-static int
-ins_methods_priv_i(name, type, ary)
- ID name;
- long type;
- VALUE ary;
-{
- return ins_methods_push(name, type, ary, NOEX_PRIVATE);
-}
-
-static int
-ins_methods_pub_i(name, type, ary)
- ID name;
- long type;
- VALUE ary;
-{
- return ins_methods_push(name, type, ary, NOEX_PUBLIC);
-}
-
-static int
-method_entry(key, body, list)
- ID key;
- NODE *body;
- st_table *list;
-{
- long type;
-
- if (key == ID_ALLOCATOR) return ST_CONTINUE;
- if (!st_lookup(list, key, 0)) {
- if (!body->nd_body) type = -1; /* none */
- else type = VISI(body->nd_noex);
- st_add_direct(list, key, type);
- }
- return ST_CONTINUE;
-}
-
-static VALUE
-class_instance_method_list(argc, argv, mod, func)
- int argc;
- VALUE *argv;
- VALUE mod;
- int (*func) _((ID, long, VALUE));
-{
- VALUE ary;
- int recur;
- st_table *list;
-
- if (argc == 0) {
- recur = Qtrue;
- }
- else {
- VALUE r;
- rb_scan_args(argc, argv, "01", &r);
- recur = RTEST(r);
- }
-
- list = st_init_numtable();
- for (; mod; mod = RCLASS(mod)->super) {
- st_foreach(RCLASS(mod)->m_tbl, method_entry, (st_data_t)list);
- if (BUILTIN_TYPE(mod) == T_ICLASS) continue;
- if (FL_TEST(mod, FL_SINGLETON)) continue;
- if (!recur) break;
- }
- ary = rb_ary_new();
- st_foreach(list, func, ary);
- st_free_table(list);
-
- return ary;
-}
-
-/*
- * call-seq:
- * mod.instance_methods(include_super=true) => array
- *
- * Returns an array containing the names of public instance methods in
- * the receiver. For a module, these are the public methods; for a
- * class, they are the instance (not singleton) methods. With no
- * argument, or with an argument that is <code>false</code>, the
- * instance methods in <i>mod</i> are returned, otherwise the methods
- * in <i>mod</i> and <i>mod</i>'s superclasses are returned.
- *
- * module A
- * def method1() end
- * end
- * class B
- * def method2() end
- * end
- * class C < B
- * def method3() end
- * end
- *
- * A.instance_methods #=> ["method1"]
- * B.instance_methods(false) #=> ["method2"]
- * C.instance_methods(false) #=> ["method3"]
- * C.instance_methods(true).length #=> 43
- */
-
-VALUE
-rb_class_instance_methods(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
-{
- return class_instance_method_list(argc, argv, mod, ins_methods_i);
-}
-
-/*
- * call-seq:
- * mod.protected_instance_methods(include_super=true) => array
- *
- * Returns a list of the protected instance methods defined in
- * <i>mod</i>. If the optional parameter is not <code>false</code>, the
- * methods of any ancestors are included.
- */
-
-VALUE
-rb_class_protected_instance_methods(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
-{
- return class_instance_method_list(argc, argv, mod, ins_methods_prot_i);
-}
-
-/*
- * call-seq:
- * mod.private_instance_methods(include_super=true) => array
- *
- * Returns a list of the private instance methods defined in
- * <i>mod</i>. If the optional parameter is not <code>false</code>, the
- * methods of any ancestors are included.
- *
- * module Mod
- * def method1() end
- * private :method1
- * def method2() end
- * end
- * Mod.instance_methods #=> ["method2"]
- * Mod.private_instance_methods #=> ["method1"]
- */
-
-VALUE
-rb_class_private_instance_methods(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
-{
- return class_instance_method_list(argc, argv, mod, ins_methods_priv_i);
-}
-
-/*
- * call-seq:
- * mod.public_instance_methods(include_super=true) => array
- *
- * Returns a list of the public instance methods defined in <i>mod</i>.
- * If the optional parameter is not <code>false</code>, the methods of
- * any ancestors are included.
- */
-
-VALUE
-rb_class_public_instance_methods(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
-{
- return class_instance_method_list(argc, argv, mod, ins_methods_pub_i);
-}
-
-/*
- * call-seq:
- * obj.singleton_methods(all=true) => array
- *
- * Returns an array of the names of singleton methods for <i>obj</i>.
- * If the optional <i>all</i> parameter is true, the list will include
- * methods in modules included in <i>obj</i>.
- *
- * module Other
- * def three() end
- * end
- *
- * class Single
- * def Single.four() end
- * end
- *
- * a = Single.new
- *
- * def a.one()
- * end
- *
- * class << a
- * include Other
- * def two()
- * end
- * end
- *
- * Single.singleton_methods #=> ["four"]
- * a.singleton_methods(false) #=> ["two", "one"]
- * a.singleton_methods #=> ["two", "one", "three"]
- */
-
-VALUE
-rb_obj_singleton_methods(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE recur, ary, klass;
- st_table *list;
-
- rb_scan_args(argc, argv, "01", &recur);
- if (argc == 0) {
- recur = Qtrue;
- }
- klass = CLASS_OF(obj);
- list = st_init_numtable();
- if (klass && FL_TEST(klass, FL_SINGLETON)) {
- st_foreach(RCLASS(klass)->m_tbl, method_entry, (st_data_t)list);
- klass = RCLASS(klass)->super;
- }
- if (RTEST(recur)) {
- while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) {
- st_foreach(RCLASS(klass)->m_tbl, method_entry, (st_data_t)list);
- klass = RCLASS(klass)->super;
- }
- }
- ary = rb_ary_new();
- st_foreach(list, ins_methods_i, ary);
- st_free_table(list);
-
- return ary;
-}
-
-void
-rb_define_method_id(klass, name, func, argc)
- VALUE klass;
- ID name;
- VALUE (*func)();
- int argc;
-{
- rb_add_method(klass, name, NEW_CFUNC(func,argc), NOEX_PUBLIC);
-}
-
-void
-rb_define_method(klass, name, func, argc)
- VALUE klass;
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PUBLIC);
-}
-
-void
-rb_define_protected_method(klass, name, func, argc)
- VALUE klass;
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PROTECTED);
-}
-
-void
-rb_define_private_method(klass, name, func, argc)
- VALUE klass;
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PRIVATE);
-}
-
-void
-rb_undef_method(klass, name)
- VALUE klass;
- const char *name;
-{
- rb_add_method(klass, rb_intern(name), 0, NOEX_UNDEF);
-}
-
-#define SPECIAL_SINGLETON(x,c) do {\
- if (obj == (x)) {\
- return c;\
- }\
-} while (0)
-
-VALUE
-rb_singleton_class(obj)
- VALUE obj;
-{
- VALUE klass;
-
- if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
- rb_raise(rb_eTypeError, "can't define singleton");
- }
- if (rb_special_const_p(obj)) {
- SPECIAL_SINGLETON(Qnil, rb_cNilClass);
- SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
- SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
- rb_bug("unknown immediate %ld", obj);
- }
-
- DEFER_INTS;
- if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
- rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj) {
- klass = RBASIC(obj)->klass;
- }
- else {
- klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
- }
- if (OBJ_TAINTED(obj)) {
- OBJ_TAINT(klass);
- }
- else {
- FL_UNSET(klass, FL_TAINT);
- }
- if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
- ALLOW_INTS;
-
- return klass;
-}
-
-void
-rb_define_singleton_method(obj, name, func, argc)
- VALUE obj;
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_define_method(rb_singleton_class(obj), name, func, argc);
-}
-
-void
-rb_define_module_function(module, name, func, argc)
- VALUE module;
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_define_private_method(module, name, func, argc);
- rb_define_singleton_method(module, name, func, argc);
-}
-
-void
-rb_define_global_function(name, func, argc)
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_define_module_function(rb_mKernel, name, func, argc);
-}
-
-void
-rb_define_alias(klass, name1, name2)
- VALUE klass;
- const char *name1, *name2;
-{
- rb_alias(klass, rb_intern(name1), rb_intern(name2));
-}
-
-void
-rb_define_attr(klass, name, read, write)
- VALUE klass;
- const char *name;
- int read, write;
-{
- rb_attr(klass, rb_intern(name), read, write, Qfalse);
-}
-
-#ifdef HAVE_STDARG_PROTOTYPES
-#include <stdarg.h>
-#define va_init_list(a,b) va_start(a,b)
-#else
-#include <varargs.h>
-#define va_init_list(a,b) va_start(a)
-#endif
-
-int
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
-#else
-rb_scan_args(argc, argv, fmt, va_alist)
- int argc;
- const VALUE *argv;
- const char *fmt;
- va_dcl
-#endif
-{
- int n, i = 0;
- const char *p = fmt;
- VALUE *var;
- va_list vargs;
-
- va_init_list(vargs, fmt);
-
- if (*p == '*') goto rest_arg;
-
- if (ISDIGIT(*p)) {
- n = *p - '0';
- if (n > argc)
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, n);
- for (i=0; i<n; i++) {
- var = va_arg(vargs, VALUE*);
- if (var) *var = argv[i];
- }
- p++;
- }
- else {
- goto error;
- }
-
- if (ISDIGIT(*p)) {
- n = i + *p - '0';
- for (; i<n; i++) {
- var = va_arg(vargs, VALUE*);
- if (argc > i) {
- if (var) *var = argv[i];
- }
- else {
- if (var) *var = Qnil;
- }
- }
- p++;
- }
-
- if(*p == '*') {
- rest_arg:
- var = va_arg(vargs, VALUE*);
- if (argc > i) {
- if (var) *var = rb_ary_new4(argc-i, argv+i);
- i = argc;
- }
- else {
- if (var) *var = rb_ary_new();
- }
- p++;
- }
-
- if (*p == '&') {
- var = va_arg(vargs, VALUE*);
- if (rb_block_given_p()) {
- *var = rb_block_proc();
- }
- else {
- *var = Qnil;
- }
- p++;
- }
- va_end(vargs);
-
- if (*p != '\0') {
- goto error;
- }
-
- if (argc > i) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, i);
- }
-
- return argc;
-
- error:
- rb_fatal("bad scan arg format: %s", fmt);
- return 0;
-}
-/**********************************************************************
-
- compar.c -
-
- $Author: michal $
- $Date: 2004/06/22 06:30:41 $
- created at: Thu Aug 26 14:39:48 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-
-VALUE rb_mComparable;
-
-static ID cmp;
-
-int
-rb_cmpint(val, a, b)
- VALUE val, a, b;
-{
- if (NIL_P(val)) {
- rb_cmperr(a, b);
- }
- if (FIXNUM_P(val)) return FIX2INT(val);
- if (TYPE(val) == T_BIGNUM) {
- if (RBIGNUM(val)->sign) return 1;
- return -1;
- }
- if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
- if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1;
- return 0;
-}
-
-void
-rb_cmperr(x, y)
- VALUE x, y;
-{
- const char *classname;
-
- if (SPECIAL_CONST_P(y)) {
- y = rb_inspect(y);
- classname = StringValuePtr(y);
- }
- else {
- classname = rb_obj_classname(y);
- }
- rb_raise(rb_eArgError, "comparison of %s with %s failed",
- rb_obj_classname(x), classname);
-}
-
-static VALUE
-cmp_eq(a)
- VALUE *a;
-{
- VALUE c = rb_funcall(a[0], cmp, 1, a[1]);
-
- if (NIL_P(c)) return Qnil;
- if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue;
- return Qfalse;
-}
-
-static VALUE
-cmp_failed()
-{
- return Qnil;
-}
-
-/*
- * call-seq:
- * obj == other => true or false
- *
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns 0. Also returns true if
- * _obj_ and _other_ are the same object.
- */
-
-static VALUE
-cmp_equal(x, y)
- VALUE x, y;
-{
- VALUE a[2];
-
- if (x == y) return Qtrue;
-
- a[0] = x; a[1] = y;
- return rb_rescue(cmp_eq, (VALUE)a, cmp_failed, 0);
-}
-
-/*
- * call-seq:
- * obj > other => true or false
- *
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns 1.
- */
-
-static VALUE
-cmp_gt(x, y)
- VALUE x, y;
-{
- VALUE c = rb_funcall(x, cmp, 1, y);
-
- if (rb_cmpint(c, x, y) > 0) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * obj >= other => true or false
- *
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns 0 or 1.
- */
-
-static VALUE
-cmp_ge(x, y)
- VALUE x, y;
-{
- VALUE c = rb_funcall(x, cmp, 1, y);
-
- if (rb_cmpint(c, x, y) >= 0) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * obj < other => true or false
- *
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns -1.
- */
-
-static VALUE
-cmp_lt(x, y)
- VALUE x, y;
-{
- VALUE c = rb_funcall(x, cmp, 1, y);
-
- if (rb_cmpint(c, x, y) < 0) return Qtrue;
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * obj <= other => true or false
- *
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns -1 or 0.
- */
-
-static VALUE
-cmp_le(x, y)
- VALUE x, y;
-{
- VALUE c = rb_funcall(x, cmp, 1, y);
-
- if (rb_cmpint(c, x, y) <= 0) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * obj.between?(min, max) => true or false
- *
- * Returns <code>false</code> if <i>obj</i> <code><=></code>
- * <i>min</i> is less than zero or if <i>anObject</i> <code><=></code>
- * <i>max</i> is greater than zero, <code>true</code> otherwise.
- *
- * 3.between?(1, 5) #=> true
- * 6.between?(1, 5) #=> false
- * 'cat'.between?('ant', 'dog') #=> true
- * 'gnu'.between?('ant', 'dog') #=> false
- *
- */
-
-static VALUE
-cmp_between(x, min, max)
- VALUE x, min, max;
-{
- if (RTEST(cmp_lt(x, min))) return Qfalse;
- if (RTEST(cmp_gt(x, max))) return Qfalse;
- return Qtrue;
-}
-
-/*
- * The <code>Comparable</code> mixin is used by classes whose objects
- * may be ordered. The class must define the <code><=></code> operator,
- * which compares the receiver against another object, returning -1, 0,
- * or +1 depending on whether the receiver is less than, equal to, or
- * greater than the other object. <code>Comparable</code> uses
- * <code><=></code> to implement the conventional comparison operators
- * (<code><</code>, <code><=</code>, <code>==</code>, <code>>=</code>,
- * and <code>></code>) and the method <code>between?</code>.
- *
- * class SizeMatters
- * include Comparable
- * attr :str
- * def <=>(anOther)
- * str.size <=> anOther.str.size
- * end
- * def initialize(str)
- * @str = str
- * end
- * def inspect
- * @str
- * end
- * end
- *
- * s1 = SizeMatters.new("Z")
- * s2 = SizeMatters.new("YY")
- * s3 = SizeMatters.new("XXX")
- * s4 = SizeMatters.new("WWWW")
- * s5 = SizeMatters.new("VVVVV")
- *
- * s1 < s2 #=> true
- * s4.between?(s1, s3) #=> false
- * s4.between?(s3, s5) #=> true
- * [ s3, s2, s5, s4, s1 ].sort #=> [Z, YY, XXX, WWWW, VVVVV]
- *
- */
-
-void
-Init_Comparable()
-{
- rb_mComparable = rb_define_module("Comparable");
- rb_define_method(rb_mComparable, "==", cmp_equal, 1);
- rb_define_method(rb_mComparable, ">", cmp_gt, 1);
- rb_define_method(rb_mComparable, ">=", cmp_ge, 1);
- rb_define_method(rb_mComparable, "<", cmp_lt, 1);
- rb_define_method(rb_mComparable, "<=", cmp_le, 1);
- rb_define_method(rb_mComparable, "between?", cmp_between, 2);
-
- cmp = rb_intern("<=>");
-}
-/**********************************************************************
-
- dir.c -
-
- $Author: eban $
- $Date: 2005/04/11 13:30:10 $
- created at: Wed Jan 5 09:51:01 JST 1994
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
-#include "ruby.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#if defined HAVE_DIRENT_H && !defined _WIN32
-# include <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-#elif defined HAVE_DIRECT_H && !defined _WIN32
-# include <direct.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-#else
-# define dirent direct
-# if !defined __NeXT__
-# define NAMLEN(dirent) (dirent)->d_namlen
-# else
-# /* On some versions of NextStep, d_namlen is always zero, so avoid it. */
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-# endif
-# if HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# if HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# if HAVE_NDIR_H
-# include <ndir.h>
-# endif
-# ifdef _WIN32
-# include "win32/dir.h"
-# endif
-#endif
-
-#include <errno.h>
-
-#ifndef HAVE_STDLIB_H
-char *getenv();
-#endif
-
-#ifndef HAVE_STRING_H
-char *strchr _((char*,char));
-#endif
-
-#include <ctype.h>
-
-#include "util.h"
-
-#if !defined HAVE_LSTAT && !defined lstat
-#define lstat stat
-#endif
-
-#define FNM_NOESCAPE 0x01
-#define FNM_PATHNAME 0x02
-#define FNM_DOTMATCH 0x04
-#define FNM_CASEFOLD 0x08
-
-#define FNM_NOMATCH 1
-#define FNM_ERROR 2
-
-#define downcase(c) (nocase && ISUPPER(c) ? tolower(c) : (c))
-#define compare(c1, c2) (((unsigned char)(c1)) - ((unsigned char)(c2)))
-
-/* caution: in case *p == '\0'
- Next(p) == p + 1 in single byte environment
- Next(p) == p in multi byte environment
-*/
-#if defined(CharNext)
-# define Next(p) CharNext(p)
-#elif defined(DJGPP)
-# define Next(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE))
-#elif defined(__EMX__)
-# define Next(p) ((p) + emx_mblen(p))
-static inline int
-emx_mblen(p)
- const char *p;
-{
- int n = mblen(p, RUBY_MBCHAR_MAXSIZE);
- return (n < 0) ? 1 : n;
-}
-#endif
-
-#ifndef Next /* single byte environment */
-# define Next(p) ((p) + 1)
-# define Inc(p) (++(p))
-# define Compare(p1, p2) (compare(downcase(*(p1)), downcase(*(p2))))
-#else /* multi byte environment */
-# define Inc(p) ((p) = Next(p))
-# define Compare(p1, p2) (CompareImpl(p1, p2, nocase))
-static int
-CompareImpl(p1, p2, nocase)
- const char *p1;
- const char *p2;
- int nocase;
-{
- const int len1 = Next(p1) - p1;
- const int len2 = Next(p2) - p2;
-#ifdef _WIN32
- char buf1[10], buf2[10]; /* large enough? */
-#endif
-
- if (len1 < 0 || len2 < 0) {
- rb_fatal("CompareImpl: negative len");
- }
-
- if (len1 == 0) return len2;
- if (len2 == 0) return -len1;
-
-#ifdef _WIN32
- if (nocase) {
- if (len1 > 1) {
- if (len1 >= sizeof(buf1)) {
- rb_fatal("CompareImpl: too large len");
- }
- memcpy(buf1, p1, len1);
- buf1[len1] = '\0';
- CharLower(buf1);
- p1 = buf1; /* trick */
- }
- if (len2 > 1) {
- if (len2 >= sizeof(buf2)) {
- rb_fatal("CompareImpl: too large len");
- }
- memcpy(buf2, p2, len2);
- buf2[len2] = '\0';
- CharLower(buf2);
- p2 = buf2; /* trick */
- }
- }
-#endif
- if (len1 == 1)
- if (len2 == 1)
- return compare(downcase(*p1), downcase(*p2));
- else {
- const int ret = compare(downcase(*p1), *p2);
- return ret ? ret : -1;
- }
- else
- if (len2 == 1) {
- const int ret = compare(*p1, downcase(*p2));
- return ret ? ret : 1;
- }
- else {
- const int ret = memcmp(p1, p2, len1 < len2 ? len1 : len2);
- return ret ? ret : len1 - len2;
- }
-}
-#endif /* environment */
-
-static char *
-bracket(p, s, flags)
- const char *p; /* pattern (next to '[') */
- const char *s; /* string */
- int flags;
-{
- const int nocase = flags & FNM_CASEFOLD;
- const int escape = !(flags & FNM_NOESCAPE);
-
- int ok = 0, not = 0;
-
- if (*p == '!' || *p == '^') {
- not = 1;
- p++;
- }
-
- while (*p != ']') {
- const char *t1 = p;
- if (escape && *t1 == '\\')
- t1++;
- if (!*t1)
- return NULL;
- p = Next(t1);
- if (p[0] == '-' && p[1] != ']') {
- const char *t2 = p + 1;
- if (escape && *t2 == '\\')
- t2++;
- if (!*t2)
- return NULL;
- p = Next(t2);
- if (!ok && Compare(t1, s) <= 0 && Compare(s, t2) <= 0)
- ok = 1;
- }
- else
- if (!ok && Compare(t1, s) == 0)
- ok = 1;
- }
-
- return ok == not ? NULL : (char *)p + 1;
-}
-
-/* If FNM_PATHNAME is set, only path element will be matched. (upto '/' or '\0')
- Otherwise, entire string will be matched.
- End marker itself won't be compared.
- And if function succeeds, *pcur reaches end marker.
-*/
-#define UNESCAPE(p) (escape && *(p) == '\\' ? (p) + 1 : (p))
-#define ISEND(p) (!*(p) || (pathname && *(p) == '/'))
-#define RETURN(val) return *pcur = p, *scur = s, (val);
-
-static int
-fnmatch_helper(pcur, scur, flags)
- const char **pcur; /* pattern */
- const char **scur; /* string */
- int flags;
-{
- const int period = !(flags & FNM_DOTMATCH);
- const int pathname = flags & FNM_PATHNAME;
- const int escape = !(flags & FNM_NOESCAPE);
- const int nocase = flags & FNM_CASEFOLD;
-
- const char *ptmp = 0;
- const char *stmp = 0;
-
- const char *p = *pcur;
- const char *s = *scur;
-
- if (period && *s == '.' && *UNESCAPE(p) != '.') /* leading period */
- RETURN(FNM_NOMATCH);
-
- while (1) {
- switch (*p) {
- case '*':
- do { p++; } while (*p == '*');
- if (ISEND(UNESCAPE(p))) {
- p = UNESCAPE(p);
- RETURN(0);
- }
- if (ISEND(s))
- RETURN(FNM_NOMATCH);
- ptmp = p;
- stmp = s;
- continue;
-
- case '?':
- if (ISEND(s))
- RETURN(FNM_NOMATCH);
- p++;
- Inc(s);
- continue;
-
- case '[': {
- const char *t;
- if (ISEND(s))
- RETURN(FNM_NOMATCH);
- if (t = bracket(p + 1, s, flags)) {
- p = t;
- Inc(s);
- continue;
- }
- goto failed;
- }
- }
-
- /* ordinary */
- p = UNESCAPE(p);
- if (ISEND(s))
- RETURN(ISEND(p) ? 0 : FNM_NOMATCH);
- if (ISEND(p))
- goto failed;
- if (Compare(p, s) != 0)
- goto failed;
- Inc(p);
- Inc(s);
- continue;
-
- failed: /* try next '*' position */
- if (ptmp && stmp) {
- p = ptmp;
- Inc(stmp); /* !ISEND(*stmp) */
- s = stmp;
- continue;
- }
- RETURN(FNM_NOMATCH);
- }
-}
-
-static int
-fnmatch(p, s, flags)
- const char *p; /* pattern */
- const char *s; /* string */
- int flags;
-{
- const int period = !(flags & FNM_DOTMATCH);
- const int pathname = flags & FNM_PATHNAME;
-
- const char *ptmp = 0;
- const char *stmp = 0;
-
- if (pathname) {
- while (1) {
- if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
- do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
- ptmp = p;
- stmp = s;
- }
- if (fnmatch_helper(&p, &s, flags) == 0) {
- while (*s && *s != '/') Inc(s);
- if (*p && *s) {
- p++;
- s++;
- continue;
- }
- if (!*p && !*s)
- return 0;
- }
- /* failed : try next recursion */
- if (ptmp && stmp && !(period && *stmp == '.')) {
- while (*stmp && *stmp != '/') Inc(stmp);
- if (*stmp) {
- p = ptmp;
- stmp++;
- s = stmp;
- continue;
- }
- }
- return FNM_NOMATCH;
- }
- }
- else
- return fnmatch_helper(&p, &s, flags);
-}
-
-VALUE rb_cDir;
-
-struct dir_data {
- DIR *dir;
- char *path;
-};
-
-static void
-free_dir(dir)
- struct dir_data *dir;
-{
- if (dir) {
- if (dir->dir) closedir(dir->dir);
- if (dir->path) free(dir->path);
- }
- free(dir);
-}
-
-static VALUE dir_close _((VALUE));
-
-static VALUE dir_s_alloc _((VALUE));
-static VALUE
-dir_s_alloc(klass)
- VALUE klass;
-{
- struct dir_data *dirp;
- VALUE obj = Data_Make_Struct(klass, struct dir_data, 0, free_dir, dirp);
-
- dirp->dir = NULL;
- dirp->path = NULL;
-
- return obj;
-}
-
-/*
- * call-seq:
- * Dir.new( string ) -> aDir
- *
- * Returns a new directory object for the named directory.
- */
-static VALUE
-dir_initialize(dir, dirname)
- VALUE dir, dirname;
-{
- struct dir_data *dp;
-
- FilePathValue(dirname);
- Data_Get_Struct(dir, struct dir_data, dp);
- if (dp->dir) closedir(dp->dir);
- if (dp->path) free(dp->path);
- dp->dir = NULL;
- dp->path = NULL;
- dp->dir = opendir(RSTRING(dirname)->ptr);
- if (dp->dir == NULL) {
- if (errno == EMFILE || errno == ENFILE) {
- rb_gc();
- dp->dir = opendir(RSTRING(dirname)->ptr);
- }
- if (dp->dir == NULL) {
- rb_sys_fail(RSTRING(dirname)->ptr);
- }
- }
- dp->path = strdup(RSTRING(dirname)->ptr);
-
- return dir;
-}
-
-/*
- * call-seq:
- * Dir.open( string ) => aDir
- * Dir.open( string ) {| aDir | block } => anObject
- *
- * With no block, <code>open</code> is a synonym for
- * <code>Dir::new</code>. If a block is present, it is passed
- * <i>aDir</i> as a parameter. The directory is closed at the end of
- * the block, and <code>Dir::open</code> returns the value of the
- * block.
- */
-static VALUE
-dir_s_open(klass, dirname)
- VALUE klass, dirname;
-{
- struct dir_data *dp;
- VALUE dir = Data_Make_Struct(klass, struct dir_data, 0, free_dir, dp);
-
- dir_initialize(dir, dirname);
- if (rb_block_given_p()) {
- return rb_ensure(rb_yield, dir, dir_close, dir);
- }
-
- return dir;
-}
-
-static void
-dir_closed()
-{
- rb_raise(rb_eIOError, "closed directory");
-}
-
-#define GetDIR(obj, dirp) do {\
- Data_Get_Struct(obj, struct dir_data, dirp);\
- if (dirp->dir == NULL) dir_closed();\
-} while (0)
-
-/*
- * call-seq:
- * dir.inspect => string
- *
- * Return a string describing this Dir object.
- */
-static VALUE
-dir_inspect(dir)
- VALUE dir;
-{
- struct dir_data *dirp;
-
- GetDIR(dir, dirp);
- if (dirp->path) {
- char *c = rb_obj_classname(dir);
- int len = strlen(c) + strlen(dirp->path) + 4;
- VALUE s = rb_str_new(0, len);
- snprintf(RSTRING(s)->ptr, len+1, "#<%s:%s>", c, dirp->path);
- return s;
- }
- return rb_funcall(dir, rb_intern("to_s"), 0, 0);
-}
-
-/*
- * call-seq:
- * dir.path => string or nil
- *
- * Returns the path parameter passed to <em>dir</em>'s constructor.
- *
- * d = Dir.new("..")
- * d.path #=> ".."
- */
-static VALUE
-dir_path(dir)
- VALUE dir;
-{
- struct dir_data *dirp;
-
- GetDIR(dir, dirp);
- if (!dirp->path) return Qnil;
- return rb_str_new2(dirp->path);
-}
-
-/*
- * call-seq:
- * dir.read => string or nil
- *
- * Reads the next entry from <em>dir</em> and returns it as a string.
- * Returns <code>nil</code> at the end of the stream.
- *
- * d = Dir.new("testdir")
- * d.read #=> "."
- * d.read #=> ".."
- * d.read #=> "config.h"
- */
-static VALUE
-dir_read(dir)
- VALUE dir;
-{
- struct dir_data *dirp;
- struct dirent *dp;
-
- GetDIR(dir, dirp);
- errno = 0;
- dp = readdir(dirp->dir);
- if (dp) {
- return rb_tainted_str_new(dp->d_name, NAMLEN(dp));
- }
- else if (errno == 0) { /* end of stream */
- return Qnil;
- }
- else {
- rb_sys_fail(0);
- }
- return Qnil; /* not reached */
-}
-
-/*
- * call-seq:
- * dir.each { |filename| block } => dir
- *
- * Calls the block once for each entry in this directory, passing the
- * filename of each entry as a parameter to the block.
- *
- * d = Dir.new("testdir")
- * d.each {|x| puts "Got #{x}" }
- *
- * <em>produces:</em>
- *
- * Got .
- * Got ..
- * Got config.h
- * Got main.rb
- */
-static VALUE
-dir_each(dir)
- VALUE dir;
-{
- struct dir_data *dirp;
- struct dirent *dp;
-
- GetDIR(dir, dirp);
- for (dp = readdir(dirp->dir); dp != NULL; dp = readdir(dirp->dir)) {
- rb_yield(rb_tainted_str_new(dp->d_name, NAMLEN(dp)));
- if (dirp->dir == NULL) dir_closed();
- }
- return dir;
-}
-
-/*
- * call-seq:
- * dir.pos => integer
- * dir.tell => integer
- *
- * Returns the current position in <em>dir</em>. See also
- * <code>Dir#seek</code>.
- *
- * d = Dir.new("testdir")
- * d.tell #=> 0
- * d.read #=> "."
- * d.tell #=> 12
- */
-static VALUE
-dir_tell(dir)
- VALUE dir;
-{
-#ifdef HAVE_TELLDIR
- struct dir_data *dirp;
- long pos;
-
- GetDIR(dir, dirp);
- pos = telldir(dirp->dir);
- return rb_int2inum(pos);
-#else
- rb_notimplement();
-#endif
-}
-
-/*
- * call-seq:
- * dir.seek( integer ) => dir
- *
- * Seeks to a particular location in <em>dir</em>. <i>integer</i>
- * must be a value returned by <code>Dir#tell</code>.
- *
- * d = Dir.new("testdir") #=> #<Dir:0x401b3c40>
- * d.read #=> "."
- * i = d.tell #=> 12
- * d.read #=> ".."
- * d.seek(i) #=> #<Dir:0x401b3c40>
- * d.read #=> ".."
- */
-static VALUE
-dir_seek(dir, pos)
- VALUE dir, pos;
-{
- struct dir_data *dirp;
- off_t p = NUM2OFFT(pos);
-
- GetDIR(dir, dirp);
-#ifdef HAVE_SEEKDIR
- seekdir(dirp->dir, p);
- return dir;
-#else
- rb_notimplement();
-#endif
-}
-
-/*
- * call-seq:
- * dir.pos( integer ) => integer
- *
- * Synonym for <code>Dir#seek</code>, but returns the position
- * parameter.
- *
- * d = Dir.new("testdir") #=> #<Dir:0x401b3c40>
- * d.read #=> "."
- * i = d.pos #=> 12
- * d.read #=> ".."
- * d.pos = i #=> 12
- * d.read #=> ".."
- */
-static VALUE
-dir_set_pos(dir, pos)
- VALUE dir, pos;
-{
- dir_seek(dir, pos);
- return pos;
-}
-
-/*
- * call-seq:
- * dir.rewind => dir
- *
- * Repositions <em>dir</em> to the first entry.
- *
- * d = Dir.new("testdir")
- * d.read #=> "."
- * d.rewind #=> #<Dir:0x401b3fb0>
- * d.read #=> "."
- */
-static VALUE
-dir_rewind(dir)
- VALUE dir;
-{
- struct dir_data *dirp;
-
- GetDIR(dir, dirp);
- rewinddir(dirp->dir);
- return dir;
-}
-
-/*
- * call-seq:
- * dir.close => nil
- *
- * Closes the directory stream. Any further attempts to access
- * <em>dir</em> will raise an <code>IOError</code>.
- *
- * d = Dir.new("testdir")
- * d.close #=> nil
- */
-static VALUE
-dir_close(dir)
- VALUE dir;
-{
- struct dir_data *dirp;
-
- GetDIR(dir, dirp);
- closedir(dirp->dir);
- dirp->dir = NULL;
-
- return Qnil;
-}
-
-static void
-dir_chdir(path)
- VALUE path;
-{
- if (chdir(RSTRING(path)->ptr) < 0)
- rb_sys_fail(RSTRING(path)->ptr);
-}
-
-static int chdir_blocking = 0;
-static VALUE chdir_thread = Qnil;
-
-struct chdir_data {
- VALUE old_path, new_path;
- int done;
-};
-
-static VALUE
-chdir_yield(args)
- struct chdir_data *args;
-{
- dir_chdir(args->new_path);
- args->done = Qtrue;
- chdir_blocking++;
- if (chdir_thread == Qnil)
- chdir_thread = rb_thread_current();
- return rb_yield(args->new_path);
-}
-
-static VALUE
-chdir_restore(args)
- struct chdir_data *args;
-{
- if (args->done) {
- chdir_blocking--;
- if (chdir_blocking == 0)
- chdir_thread = Qnil;
- dir_chdir(args->old_path);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * Dir.chdir( [ string] ) => 0
- * Dir.chdir( [ string] ) {| path | block } => anObject
- *
- * Changes the current working directory of the process to the given
- * string. When called without an argument, changes the directory to
- * the value of the environment variable <code>HOME</code>, or
- * <code>LOGDIR</code>. <code>SystemCallError</code> (probably
- * <code>Errno::ENOENT</code>) if the target directory does not exist.
- *
- * If a block is given, it is passed the name of the new current
- * directory, and the block is executed with that as the current
- * directory. The original working directory is restored when the block
- * exits. The return value of <code>chdir</code> is the value of the
- * block. <code>chdir</code> blocks can be nested, but in a
- * multi-threaded program an error will be raised if a thread attempts
- * to open a <code>chdir</code> block while another thread has one
- * open.
- *
- * Dir.chdir("/var/spool/mail")
- * puts Dir.pwd
- * Dir.chdir("/tmp") do
- * puts Dir.pwd
- * Dir.chdir("/usr") do
- * puts Dir.pwd
- * end
- * puts Dir.pwd
- * end
- * puts Dir.pwd
- *
- * <em>produces:</em>
- *
- * /var/spool/mail
- * /tmp
- * /usr
- * /tmp
- * /var/spool/mail
- */
-static VALUE
-dir_s_chdir(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE path = Qnil;
-
- rb_secure(2);
- if (rb_scan_args(argc, argv, "01", &path) == 1) {
- FilePathValue(path);
- }
- else {
- const char *dist = getenv("HOME");
- if (!dist) {
- dist = getenv("LOGDIR");
- if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
- }
- path = rb_str_new2(dist);
- }
-
- if (chdir_blocking > 0) {
- if (!rb_block_given_p() || rb_thread_current() != chdir_thread)
- rb_warn("conflicting chdir during another chdir block");
- }
-
- if (rb_block_given_p()) {
- struct chdir_data args;
- char *cwd = my_getcwd();
-
- args.old_path = rb_tainted_str_new2(cwd); free(cwd);
- args.new_path = path;
- args.done = Qfalse;
- return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
- }
- dir_chdir(path);
-
- return INT2FIX(0);
-}
-
-/*
- * call-seq:
- * Dir.getwd => string
- * Dir.pwd => string
- *
- * Returns the path to the current working directory of this process as
- * a string.
- *
- * Dir.chdir("/tmp") #=> 0
- * Dir.getwd #=> "/tmp"
- */
-static VALUE
-dir_s_getwd(dir)
- VALUE dir;
-{
- char *path;
- VALUE cwd;
-
- rb_secure(4);
- path = my_getcwd();
- cwd = rb_tainted_str_new2(path);
-
- free(path);
- return cwd;
-}
-
-static void check_dirname _((volatile VALUE *));
-static void
-check_dirname(dir)
- volatile VALUE *dir;
-{
- char *path, *pend;
-
- rb_secure(2);
- FilePathValue(*dir);
- path = RSTRING(*dir)->ptr;
- if (path && *(pend = rb_path_end(rb_path_skip_prefix(path)))) {
- *dir = rb_str_new(path, pend - path);
- }
-}
-
-/*
- * call-seq:
- * Dir.chroot( string ) => 0
- *
- * Changes this process's idea of the file system root. Only a
- * privileged process may make this call. Not available on all
- * platforms. On Unix systems, see <code>chroot(2)</code> for more
- * information.
- */
-static VALUE
-dir_s_chroot(dir, path)
- VALUE dir, path;
-{
-#if defined(HAVE_CHROOT) && !defined(__CHECKER__)
- check_dirname(&path);
-
- if (chroot(RSTRING(path)->ptr) == -1)
- rb_sys_fail(RSTRING(path)->ptr);
-
- return INT2FIX(0);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-/*
- * call-seq:
- * Dir.mkdir( string [, integer] ) => 0
- *
- * Makes a new directory named by <i>string</i>, with permissions
- * specified by the optional parameter <i>anInteger</i>. The
- * permissions may be modified by the value of
- * <code>File::umask</code>, and are ignored on NT. Raises a
- * <code>SystemCallError</code> if the directory cannot be created. See
- * also the discussion of permissions in the class documentation for
- * <code>File</code>.
- *
- */
-static VALUE
-dir_s_mkdir(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE path, vmode;
- int mode;
-
- if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) {
- mode = NUM2INT(vmode);
- }
- else {
- mode = 0777;
- }
-
- check_dirname(&path);
- if (mkdir(RSTRING(path)->ptr, mode) == -1)
- rb_sys_fail(RSTRING(path)->ptr);
-
- return INT2FIX(0);
-}
-
-/*
- * call-seq:
- * Dir.delete( string ) => 0
- * Dir.rmdir( string ) => 0
- * Dir.unlink( string ) => 0
- *
- * Deletes the named directory. Raises a subclass of
- * <code>SystemCallError</code> if the directory isn't empty.
- */
-static VALUE
-dir_s_rmdir(obj, dir)
- VALUE obj, dir;
-{
- check_dirname(&dir);
- if (rmdir(RSTRING(dir)->ptr) < 0)
- rb_sys_fail(RSTRING(dir)->ptr);
-
- return INT2FIX(0);
-}
-
-/* System call with warning */
-static int
-do_stat(path, pst)
- const char *path;
- struct stat *pst;
-{
- int ret = stat(path, pst);
- if (ret < 0 && errno != ENOENT)
- rb_sys_warning(path);
-
- return ret;
-}
-
-static int
-do_lstat(path, pst)
- const char *path;
- struct stat *pst;
-{
- int ret = lstat(path, pst);
- if (ret < 0 && errno != ENOENT)
- rb_sys_warning(path);
-
- return ret;
-}
-
-static DIR *
-do_opendir(path)
- const char *path;
-{
- DIR *dirp = opendir(path);
- if (dirp == NULL && errno != ENOENT && errno != ENOTDIR)
- rb_sys_warning(path);
-
- return dirp;
-}
-
-/* Return nonzero if S has any special globbing chars in it. */
-static int
-has_magic(s, flags)
- const char *s;
- int flags;
-{
- const int escape = !(flags & FNM_NOESCAPE);
-
- register const char *p = s;
- register char c;
-
- while (c = *p++) {
- switch (c) {
- case '*':
- case '?':
- case '[':
- return 1;
-
- case '\\':
- if (escape && !(c = *p++))
- return 0;
- continue;
- }
-
- p = Next(p-1);
- }
-
- return 0;
-}
-
-/* Find separator in globbing pattern. */
-static char *
-find_dirsep(s, flags)
- const char *s;
- int flags;
-{
- const int escape = !(flags & FNM_NOESCAPE);
-
- register const char *p = s;
- register char c;
- int open = 0;
-
- while (c = *p++) {
- switch (c) {
- case '[':
- open = 1;
- continue;
- case ']':
- open = 0;
- continue;
-
- case '/':
- if (!open)
- return (char *)p-1;
- continue;
-
- case '\\':
- if (escape && !(c = *p++))
- return (char *)p-1;
- continue;
- }
-
- p = Next(p-1);
- }
-
- return (char *)p-1;
-}
-
-/* Remove escaping baskclashes */
-static void
-remove_backslashes(p)
- char *p;
-{
- char *t = p;
- char *s = p;
-
- while (*p) {
- if (*p == '\\') {
- if (t != s)
- memmove(t, s, p - s);
- t += p - s;
- s = ++p;
- if (!*p) break;
- }
- Inc(p);
- }
-
- while (*p++);
-
- if (t != s)
- memmove(t, s, p - s); /* move '\0' too */
-}
-
-/* Globing pattern */
-enum glob_pattern_type { PLAIN, MAGICAL, RECURSIVE, MATCH_ALL, MATCH_DIR };
-
-struct glob_pattern {
- char *str;
- enum glob_pattern_type type;
- struct glob_pattern *next;
-};
-
-static struct glob_pattern *
-glob_make_pattern(p, flags)
- const char *p;
- int flags;
-{
- struct glob_pattern *list, *tmp, **tail = &list;
- int dirsep = 0; /* pattern is terminated with '/' */
-
- while (*p) {
- tmp = ALLOC(struct glob_pattern);
- if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
- /* fold continuous RECURSIVEs (needed in glob_helper) */
- do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
- tmp->type = RECURSIVE;
- tmp->str = 0;
- dirsep = 1;
- }
- else {
- const char *m = find_dirsep(p, flags);
- char *buf = ALLOC_N(char, m-p+1);
- memcpy(buf, p, m-p);
- buf[m-p] = '\0';
- tmp->type = has_magic(buf, flags) ? MAGICAL : PLAIN;
- tmp->str = buf;
- if (*m) {
- dirsep = 1;
- p = m + 1;
- }
- else {
- dirsep = 0;
- p = m;
- }
- }
- *tail = tmp;
- tail = &tmp->next;
- }
-
- tmp = ALLOC(struct glob_pattern);
- tmp->type = dirsep ? MATCH_DIR : MATCH_ALL;
- tmp->str = 0;
- *tail = tmp;
- tmp->next = 0;
-
- return list;
-}
-
-static void
-glob_free_pattern(list)
- struct glob_pattern *list;
-{
- while (list) {
- struct glob_pattern *tmp = list;
- list = list->next;
- if (tmp->str)
- free(tmp->str);
- free(tmp);
- }
-}
-
-static VALUE
-join_path(path, dirsep, name)
- VALUE path;
- int dirsep;
- const char *name;
-{
- long len = RSTRING(path)->len;
- VALUE buf = rb_str_new(0, RSTRING(path)->len+strlen(name)+(dirsep?1:0));
-
- memcpy(RSTRING(buf)->ptr, RSTRING(path)->ptr, len);
- if (dirsep) {
- strcpy(RSTRING(buf)->ptr+len, "/");
- len++;
- }
- strcpy(RSTRING(buf)->ptr+len, name);
- return buf;
-}
-
-enum answer { YES, NO, UNKNOWN };
-
-#ifndef S_ISDIR
-# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
-#endif
-
-#ifndef S_ISLNK
-# ifndef S_IFLNK
-# define S_ISLNK(m) (0)
-# else
-# define S_ISLNK(m) ((m & S_IFMT) == S_IFLNK)
-# endif
-#endif
-
-struct glob_args {
- void (*func) _((VALUE, VALUE));
- VALUE c;
- VALUE v;
-};
-
-static VALUE glob_func_caller _((VALUE));
-
-static VALUE
-glob_func_caller(val)
- VALUE val;
-{
- struct glob_args *args = (struct glob_args *)val;
- VALUE path = args->c;
-
- OBJ_TAINT(path);
- (*args->func)(path, args->v);
- return Qnil;
-}
-
-static int
-glob_call_func(func, path, arg)
- void (*func) _((VALUE, VALUE));
- VALUE path;
- VALUE arg;
-{
- int status;
- struct glob_args args;
-
- args.func = func;
- args.c = path;
- args.v = arg;
-
- rb_protect(glob_func_caller, (VALUE)&args, &status);
- return status;
-}
-
-static int
-glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
- VALUE path;
- int dirsep; /* '/' should be placed before appending child entry's name to 'path'. */
- enum answer exist; /* Does 'path' indicate an existing entry? */
- enum answer isdir; /* Does 'path' indicate a directory or a symlink to a directory? */
- struct glob_pattern **beg;
- struct glob_pattern **end;
- int flags;
- void (*func) _((VALUE, VALUE));
- VALUE arg;
-{
- struct stat st;
- int status = 0;
- struct glob_pattern **cur, **new_beg, **new_end;
- int plain = 0, magical = 0, recursive = 0, match_all = 0, match_dir = 0;
- int escape = !(flags & FNM_NOESCAPE);
-
- for (cur = beg; cur < end; ++cur) {
- struct glob_pattern *p = *cur;
- if (p->type == RECURSIVE) {
- recursive = 1;
- p = p->next;
- }
- switch (p->type) {
- case PLAIN:
- plain = 1;
- break;
- case MAGICAL:
- magical = 1;
- break;
- case MATCH_ALL:
- match_all = 1;
- break;
- case MATCH_DIR:
- match_dir = 1;
- break;
- }
- }
-
- if (RSTRING(path)->len > 0) {
- if (match_all && exist == UNKNOWN) {
- if (do_lstat(RSTRING(path)->ptr, &st) == 0) {
- exist = YES;
- isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
- }
- else {
- exist = NO;
- isdir = NO;
- }
- }
-
- if (match_dir && isdir == UNKNOWN) {
- if (do_stat(RSTRING(path)->ptr, &st) == 0) {
- exist = YES;
- isdir = S_ISDIR(st.st_mode) ? YES : NO;
- }
- else {
- exist = NO;
- isdir = NO;
- }
- }
-
- if (match_all && exist == YES) {
- status = glob_call_func(func, path, arg);
- if (status) return status;
- }
-
- if (match_dir && isdir == YES) {
- status = glob_call_func(func, join_path(path, dirsep, ""), arg);
- if (status) return status;
- }
- }
-
- if (exist == NO || isdir == NO) return 0;
-
- if (magical || recursive) {
- struct dirent *dp;
- DIR *dirp = do_opendir(RSTRING(path)->len > 0 ? RSTRING(path)->ptr : ".");
- if (dirp == NULL) return 0;
-
- for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- VALUE buf = join_path(path, dirsep, dp->d_name);
-
- enum answer new_isdir = UNKNOWN;
- if (recursive && strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0
- && fnmatch("*", dp->d_name, flags) == 0) {
-#ifndef _WIN32
- if (do_lstat(RSTRING(buf)->ptr, &st) == 0)
- new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
- else
- new_isdir = NO;
-#else
- new_isdir = dp->d_isdir ? (!dp->d_isrep ? YES : UNKNOWN) : NO;
-#endif
- }
-
- new_beg = new_end = ALLOC_N(struct glob_pattern *, (end - beg) * 2);
-
- for (cur = beg; cur < end; ++cur) {
- struct glob_pattern *p = *cur;
- if (p->type == RECURSIVE) {
- if (new_isdir == YES) /* not symlink but real directory */
- *new_end++ = p; /* append recursive pattern */
- p = p->next; /* 0 times recursion */
- }
- if (p->type == PLAIN || p->type == MAGICAL) {
- if (fnmatch(p->str, dp->d_name, flags) == 0)
- *new_end++ = p->next;
- }
- }
-
- status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end, flags, func, arg);
- free(new_beg);
- if (status) break;
- }
-
- closedir(dirp);
- }
- else if (plain) {
- struct glob_pattern **copy_beg, **copy_end, **cur2;
-
- copy_beg = copy_end = ALLOC_N(struct glob_pattern *, end - beg);
- for (cur = beg; cur < end; ++cur)
- *copy_end++ = (*cur)->type == PLAIN ? *cur : 0;
-
- for (cur = copy_beg; cur < copy_end; ++cur) {
- if (*cur) {
- VALUE buf;
- char *name;
- name = ALLOC_N(char, strlen((*cur)->str) + 1);
- strcpy(name, (*cur)->str);
- if (escape) remove_backslashes(name);
-
- new_beg = new_end = ALLOC_N(struct glob_pattern *, end - beg);
- *new_end++ = (*cur)->next;
- for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
- if (*cur2 && fnmatch((*cur2)->str, name, flags) == 0) {
- *new_end++ = (*cur2)->next;
- *cur2 = 0;
- }
- }
-
- buf = join_path(path, dirsep, name);
- free(name);
- status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg, new_end, flags, func, arg);
- free(new_beg);
- if (status) break;
- }
- }
-
- free(copy_beg);
- }
-
- return status;
-}
-
-static int
-rb_glob2(path, offset, flags, func, arg)
- VALUE path;
- long offset;
- int flags;
- void (*func) _((VALUE, VALUE));
- VALUE arg;
-{
- struct glob_pattern *list;
- const char *root, *start;
- VALUE buf;
- int n;
- int status;
-
- if (flags & FNM_CASEFOLD) {
- rb_warn("Dir.glob() ignores File::FNM_CASEFOLD");
- }
-
- start = root = StringValuePtr(path) + offset;
-#if defined DOSISH
- flags |= FNM_CASEFOLD;
- root = rb_path_skip_prefix(root);
-#else
- flags &= ~FNM_CASEFOLD;
-#endif
-
- if (root && *root == '/') root++;
-
- n = root - start;
- buf = rb_str_new(start, n);
-
- list = glob_make_pattern(root, flags);
- status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg);
- glob_free_pattern(list);
-
- return status;
-}
-
-struct rb_glob_args {
- void (*func) _((const char*, VALUE));
- VALUE arg;
-};
-
-static VALUE
-rb_glob_caller(path, a)
- VALUE path, a;
-{
- struct rb_glob_args *args = (struct rb_glob_args *)a;
- (*args->func)(RSTRING(path)->ptr, args->arg);
- return Qnil;
-}
-
-void
-rb_glob(path, func, arg)
- const char *path;
- void (*func) _((const char*, VALUE));
- VALUE arg;
-{
- struct rb_glob_args args;
- int status;
-
- args.func = func;
- args.arg = arg;
- status = rb_glob2(rb_str_new2(path), 0, 0, rb_glob_caller, &args);
-
- if (status) rb_jump_tag(status);
-}
-
-static void
-push_pattern(path, ary)
- VALUE path, ary;
-{
- rb_ary_push(ary, path);
-}
-
-static int
-push_glob(VALUE ary, VALUE s, long offset, int flags);
-
-static int
-push_glob(ary, str, offset, flags)
- VALUE ary;
- VALUE str;
- long offset;
- int flags;
-{
- const int escape = !(flags & FNM_NOESCAPE);
-
- const char *p = RSTRING(str)->ptr + offset;
- const char *s = p;
- const char *lbrace = 0, *rbrace = 0;
- int nest = 0, status = 0;
-
- while (*p) {
- if (*p == '{' && nest++ == 0) {
- lbrace = p;
- }
- if (*p == '}' && --nest <= 0) {
- rbrace = p;
- break;
- }
- if (*p == '\\' && escape) {
- if (!*++p) break;
- }
- Inc(p);
- }
-
- if (lbrace && rbrace) {
- VALUE buffer = rb_str_new(0, strlen(s));
- char *buf;
- long shift;
-
- buf = RSTRING(buffer)->ptr;
- memcpy(buf, s, lbrace-s);
- shift = (lbrace-s);
- p = lbrace;
- while (p < rbrace) {
- const char *t = ++p;
- nest = 0;
- while (p < rbrace && !(*p == ',' && nest == 0)) {
- if (*p == '{') nest++;
- if (*p == '}') nest--;
- if (*p == '\\' && escape) {
- if (++p == rbrace) break;
- }
- Inc(p);
- }
- memcpy(buf+shift, t, p-t);
- strcpy(buf+shift+(p-t), rbrace+1);
- status = push_glob(ary, buffer, offset, flags);
- if (status) break;
- }
- }
- else if (!lbrace && !rbrace) {
- status = rb_glob2(str, offset, flags, push_pattern, ary);
- }
-
- return status;
-}
-
-static VALUE
-rb_push_glob(str, flags) /* '\0' is delimiter */
- VALUE str;
- int flags;
-{
- long offset = 0;
- VALUE ary;
-
- FilePathValue(str);
-
- ary = rb_ary_new();
-
- while (offset < RSTRING(str)->len) {
- int status = push_glob(ary, str, offset, flags);
- char *p, *pend;
- if (status) rb_jump_tag(status);
- p = RSTRING(str)->ptr + offset;
- p += strlen(p) + 1;
- pend = RSTRING(str)->ptr + RSTRING(str)->len;
- while (p < pend && !*p)
- p++;
- offset = p - RSTRING(str)->ptr;
- }
-
- if (rb_block_given_p()) {
- rb_ary_each(ary);
- return Qnil;
- }
- return ary;
-}
-
-/*
- * call-seq:
- * Dir[ string ] => array
- *
- * Equivalent to calling
- * <em>dir</em>.<code>glob(</code><i>string,</i><code>0)</code>.
- *
- */
-static VALUE
-dir_s_aref(obj, str)
- VALUE obj, str;
-{
- return rb_push_glob(str, 0);
-}
-
-/*
- * call-seq:
- * Dir.glob( string, [flags] ) => array
- * Dir.glob( string, [flags] ) {| filename | block } => nil
- *
- * Returns the filenames found by expanding the pattern given in
- * <i>string</i>, either as an <i>array</i> or as parameters to the
- * block. Note that this pattern is not a regexp (it's closer to a
- * shell glob). See <code>File::fnmatch</code> for the meaning of
- * the <i>flags</i> parameter. Note that case sensitivity
- * depends on your system (so <code>File::FNM_CASEFOLD</code> is ignored)
- *
- * <code>*</code>:: Matches any file. Can be restricted by
- * other values in the glob. <code>*</code>
- * will match all files; <code>c*</code> will
- * match all files beginning with
- * <code>c</code>; <code>*c</code> will match
- * all files ending with <code>c</code>; and
- * <code>*c*</code> will match all files that
- * have <code>c</code> in them (including at
- * the beginning or end). Equivalent to
- * <code>/ .* /x</code> in regexp.
- * <code>**</code>:: Matches directories recursively.
- * <code>?</code>:: Matches any one character. Equivalent to
- * <code>/.{1}/</code> in regexp.
- * <code>[set]</code>:: Matches any one character in +set+.
- * Behaves exactly like character sets in
- * Regexp, including set negation
- * (<code>[^a-z]</code>).
- * <code>{p,q}</code>:: Matches either literal <code>p</code> or
- * literal <code>q</code>. Matching literals
- * may be more than one character in length.
- * More than two literals may be specified.
- * Equivalent to pattern alternation in
- * regexp.
- * <code>\</code>:: Escapes the next metacharacter.
- *
- * Dir["config.?"] #=> ["config.h"]
- * Dir.glob("config.?") #=> ["config.h"]
- * Dir.glob("*.[a-z][a-z]") #=> ["main.rb"]
- * Dir.glob("*.[^r]*") #=> ["config.h"]
- * Dir.glob("*.{rb,h}") #=> ["main.rb", "config.h"]
- * Dir.glob("*") #=> ["config.h", "main.rb"]
- * Dir.glob("*", File::FNM_DOTMATCH) #=> [".", "..", "config.h", "main.rb"]
- *
- * rbfiles = File.join("**", "*.rb")
- * Dir.glob(rbfiles) #=> ["main.rb",
- * "lib/song.rb",
- * "lib/song/karaoke.rb"]
- * libdirs = File.join("**", "lib")
- * Dir.glob(libdirs) #=> ["lib"]
- *
- * librbfiles = File.join("**", "lib", "**", "*.rb")
- * Dir.glob(librbfiles) #=> ["lib/song.rb",
- * "lib/song/karaoke.rb"]
- *
- * librbfiles = File.join("**", "lib", "*.rb")
- * Dir.glob(librbfiles) #=> ["lib/song.rb"]
- */
-static VALUE
-dir_s_glob(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE str, rflags;
- int flags;
-
- if (rb_scan_args(argc, argv, "11", &str, &rflags) == 2)
- flags = NUM2INT(rflags);
- else
- flags = 0;
-
- return rb_push_glob(str, flags);
-}
-
-static VALUE
-dir_open_dir(path)
- VALUE path;
-{
- struct dir_data *dp;
- VALUE dir = rb_funcall(rb_cDir, rb_intern("open"), 1, path);
-
- if (TYPE(dir) != T_DATA ||
- RDATA(dir)->dfree != (RUBY_DATA_FUNC)free_dir) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected Dir)",
- rb_obj_classname(dir));
- }
- return dir;
-}
-
-
-/*
- * call-seq:
- * Dir.foreach( dirname ) {| filename | block } => nil
- *
- * Calls the block once for each entry in the named directory, passing
- * the filename of each entry as a parameter to the block.
- *
- * Dir.foreach("testdir") {|x| puts "Got #{x}" }
- *
- * <em>produces:</em>
- *
- * Got .
- * Got ..
- * Got config.h
- * Got main.rb
- *
- */
-static VALUE
-dir_foreach(io, dirname)
- VALUE io, dirname;
-{
- VALUE dir;
-
- dir = dir_open_dir(dirname);
- rb_ensure(dir_each, dir, dir_close, dir);
- return Qnil;
-}
-
-/*
- * call-seq:
- * Dir.entries( dirname ) => array
- *
- * Returns an array containing all of the filenames in the given
- * directory. Will raise a <code>SystemCallError</code> if the named
- * directory doesn't exist.
- *
- * Dir.entries("testdir") #=> [".", "..", "config.h", "main.rb"]
- *
- */
-static VALUE
-dir_entries(io, dirname)
- VALUE io, dirname;
-{
- VALUE dir;
-
- dir = dir_open_dir(dirname);
- return rb_ensure(rb_Array, dir, dir_close, dir);
-}
-
-/*
- * call-seq:
- * File.fnmatch( pattern, path, [flags] ) => (true or false)
- * File.fnmatch?( pattern, path, [flags] ) => (true or false)
- *
- * Returns true if <i>path</i> matches against <i>pattern</i> The
- * pattern is not a regular expression; instead it follows rules
- * similar to shell filename globbing. It may contain the following
- * metacharacters:
- *
- * <code>*</code>:: Matches any file. Can be restricted by
- * other values in the glob. <code>*</code>
- * will match all files; <code>c*</code> will
- * match all files beginning with
- * <code>c</code>; <code>*c</code> will match
- * all files ending with <code>c</code>; and
- * <code>*c*</code> will match all files that
- * have <code>c</code> in them (including at
- * the beginning or end). Equivalent to
- * <code>/ .* /x</code> in regexp.
- * <code>**</code>:: Matches directories recursively or files
- * expansively.
- * <code>?</code>:: Matches any one character. Equivalent to
- * <code>/.{1}/</code> in regexp.
- * <code>[set]</code>:: Matches any one character in +set+.
- * Behaves exactly like character sets in
- * Regexp, including set negation
- * (<code>[^a-z]</code>).
- * <code>\</code>:: Escapes the next metacharacter.
- *
- * <i>flags</i> is a bitwise OR of the <code>FNM_xxx</code>
- * parameters. The same glob pattern and flags are used by
- * <code>Dir::glob</code>.
- *
- * File.fnmatch('cat', 'cat') #=> true : match entire string
- * File.fnmatch('cat', 'category') #=> false : only match partial string
- * File.fnmatch('c{at,ub}s', 'cats') #=> false : { } isn't supported
- *
- * File.fnmatch('c?t', 'cat') #=> true : '?' match only 1 character
- * File.fnmatch('c??t', 'cat') #=> false : ditto
- * File.fnmatch('c*', 'cats') #=> true : '*' match 0 or more characters
- * File.fnmatch('c*t', 'c/a/b/t') #=> true : ditto
- * File.fnmatch('ca[a-z]', 'cat') #=> true : inclusive bracket expression
- * File.fnmatch('ca[^t]', 'cat') #=> false : exclusive bracket expression ('^' or '!')
- *
- * File.fnmatch('cat', 'CAT') #=> false : case sensitive
- * File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true : case insensitive
- *
- * File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false : wildcard doesn't match '/' on FNM_PATHNAME
- * File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false : ditto
- * File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false : ditto
- *
- * File.fnmatch('\?', '?') #=> true : escaped wildcard becomes ordinary
- * File.fnmatch('\a', 'a') #=> true : escaped ordinary remains ordinary
- * File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true : FNM_NOESACPE makes '\' ordinary
- * File.fnmatch('[\?]', '?') #=> true : can escape inside bracket expression
- *
- * File.fnmatch('*', '.profile') #=> false : wildcard doesn't match leading
- * File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true period by default.
- * File.fnmatch('.*', '.profile') #=> true
- *
- * rbfiles = File.join("**", "*.rb")
- * File.fnmatch(rbfiles, 'main.rb') #=> false
- * File.fnmatch(rbfiles, './main.rb') #=> false
- * File.fnmatch(rbfiles, 'lib/song.rb') #=> true
- * File.fnmatch('**.rb', 'main.rb') #=> true
- * File.fnmatch('**.rb', './main.rb') #=> false
- * File.fnmatch('**.rb', 'lib/song.rb') #=> true
- * File.fnmatch('*', 'dave/.profile') #=> true
- *
- * File.fnmatch('* IGNORE /*', 'dave/.profile', File::FNM_PATHNAME) #=> false
- * File.fnmatch('* IGNORE /*', 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
- *
- * File.fnmatch('** IGNORE /foo', 'a/b/c/foo', File::FNM_PATHNAME) #=> true
- * File.fnmatch('** IGNORE /foo', '/a/b/c/foo', File::FNM_PATHNAME) #=> true
- * File.fnmatch('** IGNORE /foo', 'c:/a/b/c/foo', File::FNM_PATHNAME) #=> true
- * File.fnmatch('** IGNORE /foo', 'a/.b/c/foo', File::FNM_PATHNAME) #=> false
- * File.fnmatch('** IGNORE /foo', 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
- */
-static VALUE
-file_s_fnmatch(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE pattern, path;
- VALUE rflags;
- int flags;
-
- if (rb_scan_args(argc, argv, "21", &pattern, &path, &rflags) == 3)
- flags = NUM2INT(rflags);
- else
- flags = 0;
-
- StringValue(pattern);
- StringValue(path);
-
- if (fnmatch(RSTRING(pattern)->ptr, RSTRING(path)->ptr, flags) == 0)
- return Qtrue;
-
- return Qfalse;
-}
-
-/*
- * Objects of class <code>Dir</code> are directory streams representing
- * directories in the underlying file system. They provide a variety of
- * ways to list directories and their contents. See also
- * <code>File</code>.
- *
- * The directory used in these examples contains the two regular files
- * (<code>config.h</code> and <code>main.rb</code>), the parent
- * directory (<code>..</code>), and the directory itself
- * (<code>.</code>).
- */
-void
-Init_Dir()
-{
- rb_cDir = rb_define_class("Dir", rb_cObject);
-
- rb_include_module(rb_cDir, rb_mEnumerable);
-
- rb_define_alloc_func(rb_cDir, dir_s_alloc);
- rb_define_singleton_method(rb_cDir, "open", dir_s_open, 1);
- rb_define_singleton_method(rb_cDir, "foreach", dir_foreach, 1);
- rb_define_singleton_method(rb_cDir, "entries", dir_entries, 1);
-
- rb_define_method(rb_cDir,"initialize", dir_initialize, 1);
- rb_define_method(rb_cDir,"path", dir_path, 0);
- rb_define_method(rb_cDir,"inspect", dir_inspect, 0);
- rb_define_method(rb_cDir,"read", dir_read, 0);
- rb_define_method(rb_cDir,"each", dir_each, 0);
- rb_define_method(rb_cDir,"rewind", dir_rewind, 0);
- rb_define_method(rb_cDir,"tell", dir_tell, 0);
- rb_define_method(rb_cDir,"seek", dir_seek, 1);
- rb_define_method(rb_cDir,"pos", dir_tell, 0);
- rb_define_method(rb_cDir,"pos=", dir_set_pos, 1);
- rb_define_method(rb_cDir,"close", dir_close, 0);
-
- rb_define_singleton_method(rb_cDir,"chdir", dir_s_chdir, -1);
- rb_define_singleton_method(rb_cDir,"getwd", dir_s_getwd, 0);
- rb_define_singleton_method(rb_cDir,"pwd", dir_s_getwd, 0);
- rb_define_singleton_method(rb_cDir,"chroot", dir_s_chroot, 1);
- rb_define_singleton_method(rb_cDir,"mkdir", dir_s_mkdir, -1);
- rb_define_singleton_method(rb_cDir,"rmdir", dir_s_rmdir, 1);
- rb_define_singleton_method(rb_cDir,"delete", dir_s_rmdir, 1);
- rb_define_singleton_method(rb_cDir,"unlink", dir_s_rmdir, 1);
-
- rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, -1);
- rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, 1);
-
- rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1);
- rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1);
-
- rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE));
- rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME));
- rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH));
- rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD));
-}
-/**********************************************************************
-
- dln.c -
-
- $Author: nobu $
- $Date: 2005/04/20 14:22:57 $
- created at: Tue Jan 18 17:05:06 JST 1994
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include "dln.h"
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
-
-#ifdef __CHECKER__
-#undef HAVE_DLOPEN
-#undef USE_DLN_A_OUT
-#undef USE_DLN_DLOPEN
-#endif
-
-#ifdef USE_DLN_A_OUT
-char *dln_argv0;
-#endif
-
-#ifdef _AIX
-#pragma alloca
-#endif
-
-#if defined(HAVE_ALLOCA_H)
-#include <alloca.h>
-#endif
-
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else
-# include <strings.h>
-#endif
-
-#ifndef xmalloc
-void *xmalloc();
-void *xcalloc();
-void *xrealloc();
-#endif
-
-#include <stdio.h>
-#if defined(_WIN32) || defined(__VMS)
-#include "missing/file.h"
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifndef S_ISDIR
-# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-#ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-#endif
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#ifndef _WIN32
-char *getenv();
-#endif
-
-#if defined(__VMS)
-#pragma builtins
-#include <dlfcn.h>
-#endif
-
-#ifdef __MACOS__
-# include <TextUtils.h>
-# include <CodeFragments.h>
-# include <Aliases.h>
-# include "macruby_private.h"
-#endif
-
-#ifdef __BEOS__
-# include <image.h>
-#endif
-
-int eaccess();
-
-#ifndef NO_DLN_LOAD
-
-#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) && !defined(_AIX) && !defined(__APPLE__) && !defined(_UNICOSMP)
-/* dynamic load with dlopen() */
-# define USE_DLN_DLOPEN
-#endif
-
-#ifndef FUNCNAME_PATTERN
-# if defined(__hp9000s300) || (defined(__NetBSD__) && !defined(__ELF__)) || defined(__BORLANDC__) || (defined(__FreeBSD__) && !defined(__ELF__)) || (defined(__OpenBSD__) && !defined(__ELF__)) || defined(NeXT) || defined(__WATCOMC__) || defined(__APPLE__)
-# define FUNCNAME_PATTERN "_Init_%s"
-# else
-# define FUNCNAME_PATTERN "Init_%s"
-# endif
-#endif
-
-static int
-init_funcname_len(buf, file)
- char **buf;
- const char *file;
-{
- char *p;
- const char *slash;
- int len;
-
- /* Load the file as an object one */
- for (slash = file-1; *file; file++) /* Find position of last '/' */
-#ifdef __MACOS__
- if (*file == ':') slash = file;
-#else
- if (*file == '/') slash = file;
-#endif
-
- len = strlen(FUNCNAME_PATTERN) + strlen(slash + 1);
- *buf = xmalloc(len);
- snprintf(*buf, len, FUNCNAME_PATTERN, slash + 1);
- for (p = *buf; *p; p++) { /* Delete suffix if it exists */
- if (*p == '.') {
- *p = '\0'; break;
- }
- }
- return p - *buf;
-}
-
-#define init_funcname(buf, file) do {\
- int len = init_funcname_len(buf, file);\
- char *tmp = ALLOCA_N(char, len+1);\
- if (!tmp) {\
- free(*buf);\
- rb_memerror();\
- }\
- strcpy(tmp, *buf);\
- free(*buf);\
- *buf = tmp;\
-} while (0)
-
-#ifdef USE_DLN_A_OUT
-
-#ifndef LIBC_NAME
-# define LIBC_NAME "libc.a"
-#endif
-
-#ifndef DLN_DEFAULT_LIB_PATH
-# define DLN_DEFAULT_LIB_PATH "/lib:/usr/lib:/usr/local/lib:."
-#endif
-
-#include <errno.h>
-
-static int dln_errno;
-
-#define DLN_ENOEXEC ENOEXEC /* Exec format error */
-#define DLN_ECONFL 1201 /* Symbol name conflict */
-#define DLN_ENOINIT 1202 /* No initializer given */
-#define DLN_EUNDEF 1203 /* Undefine symbol remains */
-#define DLN_ENOTLIB 1204 /* Not a library file */
-#define DLN_EBADLIB 1205 /* Malformed library file */
-#define DLN_EINIT 1206 /* Not initialized */
-
-static int dln_init_p = 0;
-
-#include <ar.h>
-#include <a.out.h>
-#ifndef N_COMM
-# define N_COMM 0x12
-#endif
-#ifndef N_MAGIC
-# define N_MAGIC(x) (x).a_magic
-#endif
-
-#define INVALID_OBJECT(h) (N_MAGIC(h) != OMAGIC)
-
-#include "util.h"
-#include "st.h"
-
-static st_table *sym_tbl;
-static st_table *undef_tbl;
-
-static int load_lib();
-
-static int
-load_header(fd, hdrp, disp)
- int fd;
- struct exec *hdrp;
- long disp;
-{
- int size;
-
- lseek(fd, disp, 0);
- size = read(fd, hdrp, sizeof(struct exec));
- if (size == -1) {
- dln_errno = errno;
- return -1;
- }
- if (size != sizeof(struct exec) || N_BADMAG(*hdrp)) {
- dln_errno = DLN_ENOEXEC;
- return -1;
- }
- return 0;
-}
-
-#if defined(sequent)
-#define RELOC_SYMBOL(r) ((r)->r_symbolnum)
-#define RELOC_MEMORY_SUB_P(r) ((r)->r_bsr)
-#define RELOC_PCREL_P(r) ((r)->r_pcrel || (r)->r_bsr)
-#define RELOC_TARGET_SIZE(r) ((r)->r_length)
-#endif
-
-/* Default macros */
-#ifndef RELOC_ADDRESS
-#define RELOC_ADDRESS(r) ((r)->r_address)
-#define RELOC_EXTERN_P(r) ((r)->r_extern)
-#define RELOC_SYMBOL(r) ((r)->r_symbolnum)
-#define RELOC_MEMORY_SUB_P(r) 0
-#define RELOC_PCREL_P(r) ((r)->r_pcrel)
-#define RELOC_TARGET_SIZE(r) ((r)->r_length)
-#endif
-
-#if defined(sun) && defined(sparc)
-/* Sparc (Sun 4) macros */
-# undef relocation_info
-# define relocation_info reloc_info_sparc
-# define R_RIGHTSHIFT(r) (reloc_r_rightshift[(r)->r_type])
-# define R_BITSIZE(r) (reloc_r_bitsize[(r)->r_type])
-# define R_LENGTH(r) (reloc_r_length[(r)->r_type])
-static int reloc_r_rightshift[] = {
- 0, 0, 0, 0, 0, 0, 2, 2, 10, 0, 0, 0, 0, 0, 0,
-};
-static int reloc_r_bitsize[] = {
- 8, 16, 32, 8, 16, 32, 30, 22, 22, 22, 13, 10, 32, 32, 16,
-};
-static int reloc_r_length[] = {
- 0, 1, 2, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-};
-# define R_PCREL(r) \
- ((r)->r_type >= RELOC_DISP8 && (r)->r_type <= RELOC_WDISP22)
-# define R_SYMBOL(r) ((r)->r_index)
-#endif
-
-#if defined(sequent)
-#define R_SYMBOL(r) ((r)->r_symbolnum)
-#define R_MEMORY_SUB(r) ((r)->r_bsr)
-#define R_PCREL(r) ((r)->r_pcrel || (r)->r_bsr)
-#define R_LENGTH(r) ((r)->r_length)
-#endif
-
-#ifndef R_SYMBOL
-# define R_SYMBOL(r) ((r)->r_symbolnum)
-# define R_MEMORY_SUB(r) 0
-# define R_PCREL(r) ((r)->r_pcrel)
-# define R_LENGTH(r) ((r)->r_length)
-#endif
-
-static struct relocation_info *
-load_reloc(fd, hdrp, disp)
- int fd;
- struct exec *hdrp;
- long disp;
-{
- struct relocation_info *reloc;
- int size;
-
- lseek(fd, disp + N_TXTOFF(*hdrp) + hdrp->a_text + hdrp->a_data, 0);
- size = hdrp->a_trsize + hdrp->a_drsize;
- reloc = (struct relocation_info*)xmalloc(size);
- if (reloc == NULL) {
- dln_errno = errno;
- return NULL;
- }
-
- if (read(fd, reloc, size) != size) {
- dln_errno = errno;
- free(reloc);
- return NULL;
- }
-
- return reloc;
-}
-
-static struct nlist *
-load_sym(fd, hdrp, disp)
- int fd;
- struct exec *hdrp;
- long disp;
-{
- struct nlist * buffer;
- struct nlist * sym;
- struct nlist * end;
- long displ;
- int size;
-
- lseek(fd, N_SYMOFF(*hdrp) + hdrp->a_syms + disp, 0);
- if (read(fd, &size, sizeof(int)) != sizeof(int)) {
- goto err_noexec;
- }
-
- buffer = (struct nlist*)xmalloc(hdrp->a_syms + size);
- if (buffer == NULL) {
- dln_errno = errno;
- return NULL;
- }
-
- lseek(fd, disp + N_SYMOFF(*hdrp), 0);
- if (read(fd, buffer, hdrp->a_syms + size) != hdrp->a_syms + size) {
- free(buffer);
- goto err_noexec;
- }
-
- sym = buffer;
- end = sym + hdrp->a_syms / sizeof(struct nlist);
- displ = (long)buffer + (long)(hdrp->a_syms);
-
- while (sym < end) {
- sym->n_un.n_name = (char*)sym->n_un.n_strx + displ;
- sym++;
- }
- return buffer;
-
- err_noexec:
- dln_errno = DLN_ENOEXEC;
- return NULL;
-}
-
-static st_table *
-sym_hash(hdrp, syms)
- struct exec *hdrp;
- struct nlist *syms;
-{
- st_table *tbl;
- struct nlist *sym = syms;
- struct nlist *end = syms + (hdrp->a_syms / sizeof(struct nlist));
-
- tbl = st_init_strtable();
- if (tbl == NULL) {
- dln_errno = errno;
- return NULL;
- }
-
- while (sym < end) {
- st_insert(tbl, sym->n_un.n_name, sym);
- sym++;
- }
- return tbl;
-}
-
-static int
-dln_init(prog)
- const char *prog;
-{
- char *file;
- int fd;
- struct exec hdr;
- struct nlist *syms;
-
- if (dln_init_p == 1) return 0;
-
- file = dln_find_exe(prog, NULL);
- if (file == NULL || (fd = open(file, O_RDONLY)) < 0) {
- dln_errno = errno;
- return -1;
- }
-
- if (load_header(fd, &hdr, 0) == -1) return -1;
- syms = load_sym(fd, &hdr, 0);
- if (syms == NULL) {
- close(fd);
- return -1;
- }
- sym_tbl = sym_hash(&hdr, syms);
- if (sym_tbl == NULL) { /* file may be start with #! */
- char c = '\0';
- char buf[MAXPATHLEN];
- char *p;
-
- free(syms);
- lseek(fd, 0L, 0);
- if (read(fd, &c, 1) == -1) {
- dln_errno = errno;
- return -1;
- }
- if (c != '#') goto err_noexec;
- if (read(fd, &c, 1) == -1) {
- dln_errno = errno;
- return -1;
- }
- if (c != '!') goto err_noexec;
-
- p = buf;
- /* skip forwarding spaces */
- while (read(fd, &c, 1) == 1) {
- if (c == '\n') goto err_noexec;
- if (c != '\t' && c != ' ') {
- *p++ = c;
- break;
- }
- }
- /* read in command name */
- while (read(fd, p, 1) == 1) {
- if (*p == '\n' || *p == '\t' || *p == ' ') break;
- p++;
- if (p-buf >= MAXPATHLEN) {
- dln_errno = ENAMETOOLONG;
- return -1;
- }
- }
- *p = '\0';
-
- return dln_init(buf);
- }
- dln_init_p = 1;
- undef_tbl = st_init_strtable();
- close(fd);
- return 0;
-
- err_noexec:
- close(fd);
- dln_errno = DLN_ENOEXEC;
- return -1;
-}
-
-static long
-load_text_data(fd, hdrp, bss, disp)
- int fd;
- struct exec *hdrp;
- int bss;
- long disp;
-{
- int size;
- unsigned char* addr;
-
- lseek(fd, disp + N_TXTOFF(*hdrp), 0);
- size = hdrp->a_text + hdrp->a_data;
-
- if (bss == -1) size += hdrp->a_bss;
- else if (bss > 1) size += bss;
-
- addr = (unsigned char*)xmalloc(size);
- if (addr == NULL) {
- dln_errno = errno;
- return 0;
- }
-
- if (read(fd, addr, size) != size) {
- dln_errno = errno;
- free(addr);
- return 0;
- }
-
- if (bss == -1) {
- memset(addr + hdrp->a_text + hdrp->a_data, 0, hdrp->a_bss);
- }
- else if (bss > 0) {
- memset(addr + hdrp->a_text + hdrp->a_data, 0, bss);
- }
-
- return (long)addr;
-}
-
-static int
-undef_print(key, value)
- char *key, *value;
-{
- fprintf(stderr, " %s\n", key);
- return ST_CONTINUE;
-}
-
-static void
-dln_print_undef()
-{
- fprintf(stderr, " Undefined symbols:\n");
- st_foreach(undef_tbl, undef_print, NULL);
-}
-
-static void
-dln_undefined()
-{
- if (undef_tbl->num_entries > 0) {
- fprintf(stderr, "dln: Calling undefined function\n");
- dln_print_undef();
- rb_exit(1);
- }
-}
-
-struct undef {
- char *name;
- struct relocation_info reloc;
- long base;
- char *addr;
- union {
- char c;
- short s;
- long l;
- } u;
-};
-
-static st_table *reloc_tbl = NULL;
-static void
-link_undef(name, base, reloc)
- const char *name;
- long base;
- struct relocation_info *reloc;
-{
- static int u_no = 0;
- struct undef *obj;
- char *addr = (char*)(reloc->r_address + base);
-
- obj = (struct undef*)xmalloc(sizeof(struct undef));
- obj->name = strdup(name);
- obj->reloc = *reloc;
- obj->base = base;
- switch (R_LENGTH(reloc)) {
- case 0: /* byte */
- obj->u.c = *addr;
- break;
- case 1: /* word */
- obj->u.s = *(short*)addr;
- break;
- case 2: /* long */
- obj->u.l = *(long*)addr;
- break;
- }
- if (reloc_tbl == NULL) {
- reloc_tbl = st_init_numtable();
- }
- st_insert(reloc_tbl, u_no++, obj);
-}
-
-struct reloc_arg {
- const char *name;
- long value;
-};
-
-static int
-reloc_undef(no, undef, arg)
- int no;
- struct undef *undef;
- struct reloc_arg *arg;
-{
- int datum;
- char *address;
-#if defined(sun) && defined(sparc)
- unsigned int mask = 0;
-#endif
-
- if (strcmp(arg->name, undef->name) != 0) return ST_CONTINUE;
- address = (char*)(undef->base + undef->reloc.r_address);
- datum = arg->value;
-
- if (R_PCREL(&(undef->reloc))) datum -= undef->base;
-#if defined(sun) && defined(sparc)
- datum += undef->reloc.r_addend;
- datum >>= R_RIGHTSHIFT(&(undef->reloc));
- mask = (1 << R_BITSIZE(&(undef->reloc))) - 1;
- mask |= mask -1;
- datum &= mask;
- switch (R_LENGTH(&(undef->reloc))) {
- case 0:
- *address = undef->u.c;
- *address &= ~mask;
- *address |= datum;
- break;
- case 1:
- *(short *)address = undef->u.s;
- *(short *)address &= ~mask;
- *(short *)address |= datum;
- break;
- case 2:
- *(long *)address = undef->u.l;
- *(long *)address &= ~mask;
- *(long *)address |= datum;
- break;
- }
-#else
- switch (R_LENGTH(&(undef->reloc))) {
- case 0: /* byte */
- if (R_MEMORY_SUB(&(undef->reloc)))
- *address = datum - *address;
- else *address = undef->u.c + datum;
- break;
- case 1: /* word */
- if (R_MEMORY_SUB(&(undef->reloc)))
- *(short*)address = datum - *(short*)address;
- else *(short*)address = undef->u.s + datum;
- break;
- case 2: /* long */
- if (R_MEMORY_SUB(&(undef->reloc)))
- *(long*)address = datum - *(long*)address;
- else *(long*)address = undef->u.l + datum;
- break;
- }
-#endif
- free(undef->name);
- free(undef);
- return ST_DELETE;
-}
-
-static void
-unlink_undef(name, value)
- const char *name;
- long value;
-{
- struct reloc_arg arg;
-
- arg.name = name;
- arg.value = value;
- st_foreach(reloc_tbl, reloc_undef, &arg);
-}
-
-#ifdef N_INDR
-struct indr_data {
- char *name0, *name1;
-};
-
-static int
-reloc_repl(no, undef, data)
- int no;
- struct undef *undef;
- struct indr_data *data;
-{
- if (strcmp(data->name0, undef->name) == 0) {
- free(undef->name);
- undef->name = strdup(data->name1);
- }
- return ST_CONTINUE;
-}
-#endif
-
-static int
-load_1(fd, disp, need_init)
- int fd;
- long disp;
- const char *need_init;
-{
- static char *libc = LIBC_NAME;
- struct exec hdr;
- struct relocation_info *reloc = NULL;
- long block = 0;
- long new_common = 0; /* Length of new common */
- struct nlist *syms = NULL;
- struct nlist *sym;
- struct nlist *end;
- int init_p = 0;
-
- if (load_header(fd, &hdr, disp) == -1) return -1;
- if (INVALID_OBJECT(hdr)) {
- dln_errno = DLN_ENOEXEC;
- return -1;
- }
- reloc = load_reloc(fd, &hdr, disp);
- if (reloc == NULL) return -1;
-
- syms = load_sym(fd, &hdr, disp);
- if (syms == NULL) {
- free(reloc);
- return -1;
- }
-
- sym = syms;
- end = syms + (hdr.a_syms / sizeof(struct nlist));
- while (sym < end) {
- struct nlist *old_sym;
- int value = sym->n_value;
-
-#ifdef N_INDR
- if (sym->n_type == (N_INDR | N_EXT)) {
- char *key = sym->n_un.n_name;
-
- if (st_lookup(sym_tbl, sym[1].n_un.n_name, &old_sym)) {
- if (st_delete(undef_tbl, (st_data_t*)&key, NULL)) {
- unlink_undef(key, old_sym->n_value);
- free(key);
- }
- }
- else {
- struct indr_data data;
-
- data.name0 = sym->n_un.n_name;
- data.name1 = sym[1].n_un.n_name;
- st_foreach(reloc_tbl, reloc_repl, &data);
-
- st_insert(undef_tbl, strdup(sym[1].n_un.n_name), NULL);
- if (st_delete(undef_tbl, (st_data_t*)&key, NULL)) {
- free(key);
- }
- }
- sym += 2;
- continue;
- }
-#endif
- if (sym->n_type == (N_UNDF | N_EXT)) {
- if (st_lookup(sym_tbl, sym->n_un.n_name, &old_sym) == 0) {
- old_sym = NULL;
- }
-
- if (value) {
- if (old_sym) {
- sym->n_type = N_EXT | N_COMM;
- sym->n_value = old_sym->n_value;
- }
- else {
- int rnd =
- value >= sizeof(double) ? sizeof(double) - 1
- : value >= sizeof(long) ? sizeof(long) - 1
- : sizeof(short) - 1;
-
- sym->n_type = N_COMM;
- new_common += rnd;
- new_common &= ~(long)rnd;
- sym->n_value = new_common;
- new_common += value;
- }
- }
- else {
- if (old_sym) {
- sym->n_type = N_EXT | N_COMM;
- sym->n_value = old_sym->n_value;
- }
- else {
- sym->n_value = (long)dln_undefined;
- st_insert(undef_tbl, strdup(sym->n_un.n_name), NULL);
- }
- }
- }
- sym++;
- }
-
- block = load_text_data(fd, &hdr, hdr.a_bss + new_common, disp);
- if (block == 0) goto err_exit;
-
- sym = syms;
- while (sym < end) {
- struct nlist *new_sym;
- char *key;
-
- switch (sym->n_type) {
- case N_COMM:
- sym->n_value += hdr.a_text + hdr.a_data;
- case N_TEXT|N_EXT:
- case N_DATA|N_EXT:
-
- sym->n_value += block;
-
- if (st_lookup(sym_tbl, sym->n_un.n_name, &new_sym) != 0
- && new_sym->n_value != (long)dln_undefined) {
- dln_errno = DLN_ECONFL;
- goto err_exit;
- }
-
- key = sym->n_un.n_name;
- if (st_delete(undef_tbl, (st_data_t*)&key, NULL) != 0) {
- unlink_undef(key, sym->n_value);
- free(key);
- }
-
- new_sym = (struct nlist*)xmalloc(sizeof(struct nlist));
- *new_sym = *sym;
- new_sym->n_un.n_name = strdup(sym->n_un.n_name);
- st_insert(sym_tbl, new_sym->n_un.n_name, new_sym);
- break;
-
- case N_TEXT:
- case N_DATA:
- sym->n_value += block;
- break;
- }
- sym++;
- }
-
- /*
- * First comes the text-relocation
- */
- {
- struct relocation_info * rel = reloc;
- struct relocation_info * rel_beg = reloc +
- (hdr.a_trsize/sizeof(struct relocation_info));
- struct relocation_info * rel_end = reloc +
- (hdr.a_trsize+hdr.a_drsize)/sizeof(struct relocation_info);
-
- while (rel < rel_end) {
- char *address = (char*)(rel->r_address + block);
- long datum = 0;
-#if defined(sun) && defined(sparc)
- unsigned int mask = 0;
-#endif
-
- if(rel >= rel_beg)
- address += hdr.a_text;
-
- if (rel->r_extern) { /* Look it up in symbol-table */
- sym = &(syms[R_SYMBOL(rel)]);
- switch (sym->n_type) {
- case N_EXT|N_UNDF:
- link_undef(sym->n_un.n_name, block, rel);
- case N_EXT|N_COMM:
- case N_COMM:
- datum = sym->n_value;
- break;
- default:
- goto err_exit;
- }
- } /* end.. look it up */
- else { /* is static */
- switch (R_SYMBOL(rel)) {
- case N_TEXT:
- case N_DATA:
- datum = block;
- break;
- case N_BSS:
- datum = block + new_common;
- break;
- case N_ABS:
- break;
- }
- } /* end .. is static */
- if (R_PCREL(rel)) datum -= block;
-
-#if defined(sun) && defined(sparc)
- datum += rel->r_addend;
- datum >>= R_RIGHTSHIFT(rel);
- mask = (1 << R_BITSIZE(rel)) - 1;
- mask |= mask -1;
- datum &= mask;
-
- switch (R_LENGTH(rel)) {
- case 0:
- *address &= ~mask;
- *address |= datum;
- break;
- case 1:
- *(short *)address &= ~mask;
- *(short *)address |= datum;
- break;
- case 2:
- *(long *)address &= ~mask;
- *(long *)address |= datum;
- break;
- }
-#else
- switch (R_LENGTH(rel)) {
- case 0: /* byte */
- if (datum < -128 || datum > 127) goto err_exit;
- *address += datum;
- break;
- case 1: /* word */
- *(short *)address += datum;
- break;
- case 2: /* long */
- *(long *)address += datum;
- break;
- }
-#endif
- rel++;
- }
- }
-
- if (need_init) {
- int len;
- char **libs_to_be_linked = 0;
- char *buf;
-
- if (undef_tbl->num_entries > 0) {
- if (load_lib(libc) == -1) goto err_exit;
- }
-
- init_funcname(&buf, need_init);
- len = strlen(buf);
-
- for (sym = syms; sym<end; sym++) {
- char *name = sym->n_un.n_name;
- if (name[0] == '_' && sym->n_value >= block) {
- if (strcmp(name+1, "dln_libs_to_be_linked") == 0) {
- libs_to_be_linked = (char**)sym->n_value;
- }
- else if (strcmp(name+1, buf) == 0) {
- init_p = 1;
- ((int (*)())sym->n_value)();
- }
- }
- }
- if (libs_to_be_linked && undef_tbl->num_entries > 0) {
- while (*libs_to_be_linked) {
- load_lib(*libs_to_be_linked);
- libs_to_be_linked++;
- }
- }
- }
- free(reloc);
- free(syms);
- if (need_init) {
- if (init_p == 0) {
- dln_errno = DLN_ENOINIT;
- return -1;
- }
- if (undef_tbl->num_entries > 0) {
- if (load_lib(libc) == -1) goto err_exit;
- if (undef_tbl->num_entries > 0) {
- dln_errno = DLN_EUNDEF;
- return -1;
- }
- }
- }
- return 0;
-
- err_exit:
- if (syms) free(syms);
- if (reloc) free(reloc);
- if (block) free((char*)block);
- return -1;
-}
-
-static int target_offset;
-static int
-search_undef(key, value, lib_tbl)
- const char *key;
- int value;
- st_table *lib_tbl;
-{
- long offset;
-
- if (st_lookup(lib_tbl, key, &offset) == 0) return ST_CONTINUE;
- target_offset = offset;
- return ST_STOP;
-}
-
-struct symdef {
- int rb_str_index;
- int lib_offset;
-};
-
-char *dln_librrb_ary_path = DLN_DEFAULT_LIB_PATH;
-
-static int
-load_lib(lib)
- const char *lib;
-{
- char *path, *file;
- char armagic[SARMAG];
- int fd, size;
- struct ar_hdr ahdr;
- st_table *lib_tbl = NULL;
- int *data, nsym;
- struct symdef *base;
- char *name_base;
-
- if (dln_init_p == 0) {
- dln_errno = DLN_ENOINIT;
- return -1;
- }
-
- if (undef_tbl->num_entries == 0) return 0;
- dln_errno = DLN_EBADLIB;
-
- if (lib[0] == '-' && lib[1] == 'l') {
- char *p = alloca(strlen(lib) + 4);
- sprintf(p, "lib%s.a", lib+2);
- lib = p;
- }
-
- /* library search path: */
- /* look for environment variable DLN_LIBRARY_PATH first. */
- /* then variable dln_librrb_ary_path. */
- /* if path is still NULL, use "." for path. */
- path = getenv("DLN_LIBRARY_PATH");
- if (path == NULL) path = dln_librrb_ary_path;
-
- file = dln_find_file(lib, path);
- fd = open(file, O_RDONLY);
- if (fd == -1) goto syserr;
- size = read(fd, armagic, SARMAG);
- if (size == -1) goto syserr;
-
- if (size != SARMAG) {
- dln_errno = DLN_ENOTLIB;
- goto badlib;
- }
- size = read(fd, &ahdr, sizeof(ahdr));
- if (size == -1) goto syserr;
- if (size != sizeof(ahdr) || sscanf(ahdr.ar_size, "%d", &size) != 1) {
- goto badlib;
- }
-
- if (strncmp(ahdr.ar_name, "__.SYMDEF", 9) == 0) {
- /* make hash table from __.SYMDEF */
-
- lib_tbl = st_init_strtable();
- data = (int*)xmalloc(size);
- if (data == NULL) goto syserr;
- size = read(fd, data, size);
- nsym = *data / sizeof(struct symdef);
- base = (struct symdef*)(data + 1);
- name_base = (char*)(base + nsym) + sizeof(int);
- while (nsym > 0) {
- char *name = name_base + base->rb_str_index;
-
- st_insert(lib_tbl, name, base->lib_offset + sizeof(ahdr));
- nsym--;
- base++;
- }
- for (;;) {
- target_offset = -1;
- st_foreach(undef_tbl, search_undef, lib_tbl);
- if (target_offset == -1) break;
- if (load_1(fd, target_offset, 0) == -1) {
- st_free_table(lib_tbl);
- free(data);
- goto badlib;
- }
- if (undef_tbl->num_entries == 0) break;
- }
- free(data);
- st_free_table(lib_tbl);
- }
- else {
- /* linear library, need to scan (FUTURE) */
-
- for (;;) {
- int offset = SARMAG;
- int found = 0;
- struct exec hdr;
- struct nlist *syms, *sym, *end;
-
- while (undef_tbl->num_entries > 0) {
- found = 0;
- lseek(fd, offset, 0);
- size = read(fd, &ahdr, sizeof(ahdr));
- if (size == -1) goto syserr;
- if (size == 0) break;
- if (size != sizeof(ahdr)
- || sscanf(ahdr.ar_size, "%d", &size) != 1) {
- goto badlib;
- }
- offset += sizeof(ahdr);
- if (load_header(fd, &hdr, offset) == -1)
- goto badlib;
- syms = load_sym(fd, &hdr, offset);
- if (syms == NULL) goto badlib;
- sym = syms;
- end = syms + (hdr.a_syms / sizeof(struct nlist));
- while (sym < end) {
- if (sym->n_type == N_EXT|N_TEXT
- && st_lookup(undef_tbl, sym->n_un.n_name, NULL)) {
- break;
- }
- sym++;
- }
- if (sym < end) {
- found++;
- free(syms);
- if (load_1(fd, offset, 0) == -1) {
- goto badlib;
- }
- }
- offset += size;
- if (offset & 1) offset++;
- }
- if (found) break;
- }
- }
- close(fd);
- return 0;
-
- syserr:
- dln_errno = errno;
- badlib:
- if (fd >= 0) close(fd);
- return -1;
-}
-
-static int
-load(file)
- const char *file;
-{
- int fd;
- int result;
-
- if (dln_init_p == 0) {
- if (dln_init(dln_argv0) == -1) return -1;
- }
- result = strlen(file);
- if (file[result-1] == 'a') {
- return load_lib(file);
- }
-
- fd = open(file, O_RDONLY);
- if (fd == -1) {
- dln_errno = errno;
- return -1;
- }
- result = load_1(fd, 0, file);
- close(fd);
-
- return result;
-}
-
-void*
-dln_sym(name)
- const char *name;
-{
- struct nlist *sym;
-
- if (st_lookup(sym_tbl, name, &sym))
- return (void*)sym->n_value;
- return NULL;
-}
-
-#endif /* USE_DLN_A_OUT */
-
-#ifdef USE_DLN_DLOPEN
-# include <dlfcn.h>
-#endif
-
-#ifdef __hpux
-#include <errno.h>
-#include "dl.h"
-#endif
-
-#if defined(_AIX)
-#include <ctype.h> /* for isdigit() */
-#include <errno.h> /* for global errno */
-#include <sys/ldr.h>
-#endif
-
-#ifdef NeXT
-#if NS_TARGET_MAJOR < 4
-#include <mach-o/rld.h>
-#else
-#include <mach-o/dyld.h>
-#ifndef NSLINKMODULE_OPTION_BINDNOW
-#define NSLINKMODULE_OPTION_BINDNOW 1
-#endif
-#endif
-#else
-#ifdef __APPLE__
-#include <mach-o/dyld.h>
-#endif
-#endif
-
-#if defined _WIN32 && !defined __CYGWIN__
-#include <windows.h>
-#endif
-
-#ifdef _WIN32_WCE
-#undef FormatMessage
-#define FormatMessage FormatMessageA
-#undef LoadLibrary
-#define LoadLibrary LoadLibraryA
-#undef GetProcAddress
-#define GetProcAddress GetProcAddressA
-#endif
-
-static const char *
-dln_strerror()
-{
-#ifdef USE_DLN_A_OUT
- char *strerror();
-
- switch (dln_errno) {
- case DLN_ECONFL:
- return "Symbol name conflict";
- case DLN_ENOINIT:
- return "No initializer given";
- case DLN_EUNDEF:
- return "Unresolved symbols";
- case DLN_ENOTLIB:
- return "Not a library file";
- case DLN_EBADLIB:
- return "Malformed library file";
- case DLN_EINIT:
- return "Not initialized";
- default:
- return strerror(dln_errno);
- }
-#endif
-
-#ifdef USE_DLN_DLOPEN
- return (char*)dlerror();
-#endif
-
-#if defined _WIN32 && !defined __CYGWIN__
- static char message[1024];
- int error = GetLastError();
- char *p = message;
- p += sprintf(message, "%d: ", error);
- FormatMessage(
- FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- error,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- p,
- sizeof message - strlen(message),
- NULL);
-
- for (p = message; *p; p++) {
- if (*p == '\n' || *p == '\r')
- *p = ' ';
- }
- return message;
-#endif
-}
-
-
-#if defined(_AIX) && ! defined(_IA64)
-static void
-aix_loaderror(const char *pathname)
-{
- char *message[8], errbuf[1024];
- int i,j;
-
- struct errtab {
- int errnum;
- char *errstr;
- } load_errtab[] = {
- {L_ERROR_TOOMANY, "too many errors, rest skipped."},
- {L_ERROR_NOLIB, "can't load library:"},
- {L_ERROR_UNDEF, "can't find symbol in library:"},
- {L_ERROR_RLDBAD,
- "RLD index out of range or bad relocation type:"},
- {L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
- {L_ERROR_MEMBER,
- "file not an archive or does not contain requested member:"},
- {L_ERROR_TYPE, "symbol table mismatch:"},
- {L_ERROR_ALIGN, "text alignment in file is wrong."},
- {L_ERROR_SYSTEM, "System error:"},
- {L_ERROR_ERRNO, NULL}
- };
-
-#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
-#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
-
- snprintf(errbuf, 1024, "load failed - %s ", pathname);
-
- if (!loadquery(1, &message[0], sizeof(message)))
- ERRBUF_APPEND(strerror(errno));
- for(i = 0; message[i] && *message[i]; i++) {
- int nerr = atoi(message[i]);
- for (j=0; j<LOAD_ERRTAB_LEN; j++) {
- if (nerr == load_errtab[i].errnum && load_errtab[i].errstr)
- ERRBUF_APPEND(load_errtab[i].errstr);
- }
- while (isdigit(*message[i])) message[i]++;
- ERRBUF_APPEND(message[i]);
- ERRBUF_APPEND("\n");
- }
- errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
- rb_loaderror(errbuf);
- return;
-}
-#endif
-
-#endif /* NO_DLN_LOAD */
-
-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: matz $
- $Date: 2004/10/30 06:56:17 $
- 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: eban $
- $Date: 2005/03/18 03:17:27 $
- 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: nobu $
- $Date: 2005/05/01 00:15:25 $
- 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: nobu $
- $Date: 2005/04/18 15:01:19 $
- 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;
-}
-
-/*
- * call-seq:
- * stat.blockdev? => true or false
- *
- * Returns <code>true</code> if the file is a block device,
- * <code>false</code> if it isn't or if the operating system doesn't
- * support this feature.
- *
- * File.stat("testfile").blockdev? #=> false
- * File.stat("/dev/hda1").blockdev? #=> true
- *
- */
-
-static VALUE
-rb_stat_b(obj)
- VALUE obj;
-{
-#ifdef S_ISBLK
- if (S_ISBLK(get_stat(obj)->st_mode)) return Qtrue;
-
-#endif
- return Qfalse;
-}
-
-/*
- * call-seq:
- * stat.chardev? => true or false
- *
- * Returns <code>true</code> if the file is a character device,
- * <code>false</code> if it isn't or if the operating system doesn't
- * support this feature.
- *
- * File.stat("/dev/tty").chardev? #=> true
- *
- */
-
-static VALUE
-rb_stat_c(obj)
- VALUE obj;
-{
- if (S_ISCHR(get_stat(obj)->st_mode)) return Qtrue;
-
- return Qfalse;
-}
-
-/*
- * call-seq:
- * stat.owned? => true or false
- *
- * Returns <code>true</code> if the effective user id of the process is
- * the same as the owner of <i>stat</i>.
- *
- * File.stat("testfile").owned? #=> true
- * File.stat("/etc/passwd").owned? #=> false
- *
- */
-
-static VALUE
-rb_stat_owned(obj)
- VALUE obj;
-{
- if (get_stat(obj)->st_uid == geteuid()) return Qtrue;
- return Qfalse;
-}
-
-static VALUE
-rb_stat_rowned(obj)
- VALUE obj;
-{
- if (get_stat(obj)->st_uid == getuid()) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * stat.grpowned? => true or false
- *
- * Returns true if the effective group id of the process is the same as
- * the group id of <i>stat</i>. On Windows NT, returns <code>false</code>.
- *
- * File.stat("testfile").grpowned? #=> true
- * File.stat("/etc/passwd").grpowned? #=> false
- *
- */
-
-static VALUE
-rb_stat_grpowned(obj)
- VALUE obj;
-{
-#ifndef _WIN32
- if (get_stat(obj)->st_gid == getegid()) return Qtrue;
-#endif
- return Qfalse;
-}
-
-/*
- * call-seq:
- * stat.readable? => true or false
- *
- * Returns <code>true</code> if <i>stat</i> is readable by the
- * effective user id of this process.
- *
- * File.stat("testfile").readable? #=> true
- *
- */
-
-static VALUE
-rb_stat_r(obj)
- VALUE obj;
-{
- struct stat *st = get_stat(obj);
-
-#ifdef S_IRUSR
- if (rb_stat_owned(obj))
- return st->st_mode & S_IRUSR ? Qtrue : Qfalse;
-#endif
-#ifdef S_IRGRP
- if (rb_stat_grpowned(obj))
- return st->st_mode & S_IRGRP ? Qtrue : Qfalse;
-#endif
-#ifdef S_IROTH
- if (!(st->st_mode & S_IROTH)) return Qfalse;
-#endif
- return Qtrue;
-}
-
-
-
-/*
- * call-seq:
- * stat.readable_real? -> true or false
- *
- * Returns <code>true</code> if <i>stat</i> is readable by the real
- * user id of this process.
- *
- * File.stat("testfile").readable_real? #=> true
- *
- */
-
-static VALUE
-rb_stat_R(obj)
- VALUE obj;
-{
- struct stat *st = get_stat(obj);
-
-#ifdef S_IRUSR
- if (rb_stat_rowned(obj))
- return st->st_mode & S_IRUSR ? Qtrue : Qfalse;
-#endif
-#ifdef S_IRGRP
- if (group_member(get_stat(obj)->st_gid))
- return st->st_mode & S_IRGRP ? Qtrue : Qfalse;
-#endif
-#ifdef S_IROTH
- if (!(st->st_mode & S_IROTH)) return Qfalse;
-#endif
- return Qtrue;
-}
-
-/*
- * call-seq:
- * stat.world_readable? => fixnum or nil
- *
- * If <i>stat</i> is readable by others, returns an integer
- * representing the file permission bits of <i>stat</i>. Returns
- * <code>nil</code> otherwise. The meaning of the bits is platform
- * dependent; on Unix systems, see <code>stat(2)</code>.
- *
- * m = File.stat("/etc/passwd").world_readable? # => 420
- * sprintf("%o", m) # => "644"
- */
-
-static VALUE
-rb_stat_wr(obj)
- VALUE obj;
-{
-#ifdef S_IROTH
- if ((get_stat(obj)->st_mode & (S_IROTH)) == S_IROTH) {
- return UINT2NUM(get_stat(obj)->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
- }
- else {
- return Qnil;
- }
-#endif
-}
-
-/*
- * call-seq:
- * stat.writable? -> true or false
- *
- * Returns <code>true</code> if <i>stat</i> is writable by the
- * effective user id of this process.
- *
- * File.stat("testfile").writable? #=> true
- *
- */
-
-static VALUE
-rb_stat_w(obj)
- VALUE obj;
-{
- struct stat *st = get_stat(obj);
-
-#ifdef S_IWUSR
- if (rb_stat_owned(obj))
- return st->st_mode & S_IWUSR ? Qtrue : Qfalse;
-#endif
-#ifdef S_IWGRP
- if (rb_stat_grpowned(obj))
- return st->st_mode & S_IWGRP ? Qtrue : Qfalse;
-#endif
-#ifdef S_IWOTH
- if (!(st->st_mode & S_IWOTH)) return Qfalse;
-#endif
- return Qtrue;
-}
-
-/*
- * call-seq:
- * stat.writable_real? -> true or false
- *
- * Returns <code>true</code> if <i>stat</i> is writable by the real
- * user id of this process.
- *
- * File.stat("testfile").writable_real? #=> true
- *
- */
-
-static VALUE
-rb_stat_W(obj)
- VALUE obj;
-{
- struct stat *st = get_stat(obj);
-
-#ifdef S_IWUSR
- if (rb_stat_rowned(obj))
- return st->st_mode & S_IWUSR ? Qtrue : Qfalse;
-#endif
-#ifdef S_IWGRP
- if (group_member(get_stat(obj)->st_gid))
- return st->st_mode & S_IWGRP ? Qtrue : Qfalse;
-#endif
-#ifdef S_IWOTH
- if (!(st->st_mode & S_IWOTH)) return Qfalse;
-#endif
- return Qtrue;
-}
-
-/*
- * call-seq:
- * stat.world_writable? => fixnum or nil
- *
- * If <i>stat</i> is writable by others, returns an integer
- * representing the file permission bits of <i>stat</i>. Returns
- * <code>nil</code> otherwise. The meaning of the bits is platform
- * dependent; on Unix systems, see <code>stat(2)</code>.
- *
- * m = File.stat("/tmp").world_writable? # => 511
- * sprintf("%o", m) # => "777"
- */
-
-static VALUE
-rb_stat_ww(obj)
- VALUE obj;
-{
-#ifdef S_IROTH
- if ((get_stat(obj)->st_mode & (S_IWOTH)) == S_IWOTH) {
- return UINT2NUM(get_stat(obj)->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
- }
- else {
- return Qnil;
- }
-#endif
-}
-
-/*
- * call-seq:
- * stat.executable? => true or false
- *
- * Returns <code>true</code> if <i>stat</i> is executable or if the
- * operating system doesn't distinguish executable files from
- * nonexecutable files. The tests are made using the effective owner of
- * the process.
- *
- * File.stat("testfile").executable? #=> false
- *
- */
-
-static VALUE
-rb_stat_x(obj)
- VALUE obj;
-{
- struct stat *st = get_stat(obj);
-
-#ifdef S_IXUSR
- if (rb_stat_owned(obj))
- return st->st_mode & S_IXUSR ? Qtrue : Qfalse;
-#endif
-#ifdef S_IXGRP
- if (rb_stat_grpowned(obj))
- return st->st_mode & S_IXGRP ? Qtrue : Qfalse;
-#endif
-#ifdef S_IXOTH
- if (!(st->st_mode & S_IXOTH)) return Qfalse;
-#endif
- return Qtrue;
-}
-
-/*
- * call-seq:
- * stat.executable_real? => true or false
- *
- * Same as <code>executable?</code>, but tests using the real owner of
- * the process.
- */
-
-
-static VALUE
-rb_stat_X(obj)
- VALUE obj;
-{
- struct stat *st = get_stat(obj);
-
-#ifdef S_IXUSR
- if (rb_stat_rowned(obj))
- return st->st_mode & S_IXUSR ? Qtrue : Qfalse;
-#endif
-#ifdef S_IXGRP
- if (group_member(get_stat(obj)->st_gid))
- return st->st_mode & S_IXGRP ? Qtrue : Qfalse;
-#endif
-#ifdef S_IXOTH
- if (!(st->st_mode & S_IXOTH)) return Qfalse;
-#endif
- return Qtrue;
-}
-
-/*
- * call-seq:
- * stat.file? => true or false
- *
- * Returns <code>true</code> if <i>stat</i> is a regular file (not
- * a device file, pipe, socket, etc.).
- *
- * File.stat("testfile").file? #=> true
- *
- */
-
-static VALUE
-rb_stat_f(obj)
- VALUE obj;
-{
- if (S_ISREG(get_stat(obj)->st_mode)) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * stat.zero? => true or false
- *
- * Returns <code>true</code> if <i>stat</i> is a zero-length file;
- * <code>false</code> otherwise.
- *
- * File.stat("testfile").zero? #=> false
- *
- */
-
-static VALUE
-rb_stat_z(obj)
- VALUE obj;
-{
- if (get_stat(obj)->st_size == 0) return Qtrue;
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * state.size => integer
- *
- * Returns the size of <i>stat</i> in bytes.
- *
- * File.stat("testfile").size #=> 66
- *
- */
-
-static VALUE
-rb_stat_s(obj)
- VALUE obj;
-{
- off_t size = get_stat(obj)->st_size;
-
- if (size == 0) return Qnil;
- return OFFT2NUM(size);
-}
-
-/*
- * call-seq:
- * stat.setuid? => true or false
- *
- * Returns <code>true</code> if <i>stat</i> has the set-user-id
- * permission bit set, <code>false</code> if it doesn't or if the
- * operating system doesn't support this feature.
- *
- * File.stat("/bin/su").setuid? #=> true
- */
-
-static VALUE
-rb_stat_suid(obj)
- VALUE obj;
-{
-#ifdef S_ISUID
- if (get_stat(obj)->st_mode & S_ISUID) return Qtrue;
-#endif
- return Qfalse;
-}
-
-/*
- * call-seq:
- * stat.setgid? => true or false
- *
- * Returns <code>true</code> if <i>stat</i> has the set-group-id
- * permission bit set, <code>false</code> if it doesn't or if the
- * operating system doesn't support this feature.
- *
- * File.stat("/usr/sbin/lpc").setgid? #=> true
- *
- */
-
-static VALUE
-rb_stat_sgid(obj)
- VALUE obj;
-{
-#ifdef S_ISGID
- if (get_stat(obj)->st_mode & S_ISGID) return Qtrue;
-#endif
- return Qfalse;
-}
-
-/*
- * call-seq:
- * stat.sticky? => true or false
- *
- * Returns <code>true</code> if <i>stat</i> has its sticky bit set,
- * <code>false</code> if it doesn't or if the operating system doesn't
- * support this feature.
- *
- * File.stat("testfile").sticky? #=> false
- *
- */
-
-static VALUE
-rb_stat_sticky(obj)
- VALUE obj;
-{
-#ifdef S_ISVTX
- if (get_stat(obj)->st_mode & S_ISVTX) return Qtrue;
-#endif
- return Qfalse;
-}
-
-static VALUE rb_mFConst;
-
-void
-rb_file_const(name, value)
- const char *name;
- VALUE value;
-{
- rb_define_const(rb_mFConst, name, value);
-}
-
-static int
-is_absolute_path(path)
- const char *path;
-{
-#ifdef DOSISH_DRIVE_LETTER
- if (has_drive_letter(path) && isdirsep(path[2])) return 1;
-#endif
-#ifdef DOSISH_UNC
- if (isdirsep(path[0]) && isdirsep(path[1])) return 1;
-#endif
-#ifndef DOSISH
- if (path[0] == '/') return 1;
-#endif
- return 0;
-}
-
-#ifndef DOSISH
-static int
-path_check_1(path)
- VALUE path;
-{
- struct stat st;
- char *p0 = StringValueCStr(path);
- char *p = 0, *s;
-
- if (!is_absolute_path(p0)) {
- char *buf = my_getcwd();
- VALUE newpath;
-
- newpath = rb_str_new2(buf);
- free(buf);
-
- rb_str_cat2(newpath, "/");
- rb_str_cat2(newpath, p0);
- return path_check_1(newpath);
- }
- for (;;) {
-#ifndef S_IWOTH
-# define S_IWOTH 002
-#endif
- if (stat(p0, &st) == 0 && S_ISDIR(st.st_mode) && (st.st_mode & S_IWOTH)
-#ifdef S_ISVTX
- && !(st.st_mode & S_ISVTX)
-#endif
- && !access(p0, W_OK)) {
- rb_warn("Insecure world writable dir %s, mode 0%o", p0, st.st_mode);
- if (p) *p = '/';
- return 0;
- }
- s = strrdirsep(p0);
- if (p) *p = '/';
- if (!s || s == p0) return 1;
- p = s;
- *p = '\0';
- }
-}
-#endif
-
-int
-rb_path_check(path)
- char *path;
-{
-#ifndef DOSISH
- char *p0, *p, *pend;
- const char sep = PATH_SEP_CHAR;
-
- if (!path) return 1;
-
- pend = path + strlen(path);
- p0 = path;
- p = strchr(path, sep);
- if (!p) p = pend;
-
- for (;;) {
- if (!path_check_1(rb_str_new(p0, p - p0))) {
- return 0; /* not safe */
- }
- p0 = p + 1;
- if (p0 > pend) break;
- p = strchr(p0, sep);
- if (!p) p = pend;
- }
-#endif
- return 1;
-}
-
-#if defined(__MACOS__) || defined(riscos)
-static int
-is_macos_native_path(path)
- const char *path;
-{
- if (strchr(path, ':')) return 1;
- return 0;
-}
-#endif
-
-static int
-file_load_ok(file)
- char *file;
-{
- FILE *f;
-
- if (!file) return 0;
- f = fopen(file, "r");
- if (f == NULL) return 0;
- fclose(f);
- return 1;
-}
-
-extern VALUE rb_load_path;
-
-int
-rb_find_file_ext(filep, ext)
- VALUE *filep;
- const char * const *ext;
-{
- char *path, *found;
- char *f = RSTRING(*filep)->ptr;
- VALUE fname;
- long i, j;
-
- if (f[0] == '~') {
- fname = rb_file_expand_path(*filep, Qnil);
- if (rb_safe_level() >= 2 && OBJ_TAINTED(fname)) {
- rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
- }
- OBJ_FREEZE(fname);
- f = StringValueCStr(fname);
- *filep = fname;
- }
-
- if (is_absolute_path(f)) {
- for (i=0; ext[i]; i++) {
- fname = rb_str_dup(*filep);
- rb_str_cat2(fname, ext[i]);
- OBJ_FREEZE(fname);
- if (file_load_ok(StringValueCStr(fname))) {
- *filep = fname;
- return i+1;
- }
- }
- return 0;
- }
-
- if (!rb_load_path) return 0;
-
- Check_Type(rb_load_path, T_ARRAY);
- for (i=0;i<RARRAY(rb_load_path)->len;i++) {
- VALUE str = RARRAY(rb_load_path)->ptr[i];
-
- FilePathValue(str);
- if (RSTRING(str)->len == 0) continue;
- path = RSTRING(str)->ptr;
- for (j=0; ext[j]; j++) {
- fname = rb_str_dup(*filep);
- rb_str_cat2(fname, ext[j]);
- OBJ_FREEZE(fname);
- found = dln_find_file(StringValueCStr(fname), path);
- if (found && file_load_ok(found)) {
- *filep = rb_str_new2(found);
- return j+1;
- }
- }
- }
- return 0;
-}
-
-VALUE
-rb_find_file(path)
- VALUE path;
-{
- VALUE tmp;
- char *f = StringValueCStr(path);
- char *lpath;
-
- if (f[0] == '~') {
- path = rb_file_expand_path(path, Qnil);
- if (rb_safe_level() >= 1 && OBJ_TAINTED(path)) {
- rb_raise(rb_eSecurityError, "loading from unsafe path %s", f);
- }
- OBJ_FREEZE(path);
- f = StringValueCStr(path);
- }
-
-#if defined(__MACOS__) || defined(riscos)
- if (is_macos_native_path(f)) {
- if (rb_safe_level() >= 1 && !rb_path_check(f)) {
- rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
- }
- if (file_load_ok(f)) return path;
- }
-#endif
-
- if (is_absolute_path(f)) {
- if (rb_safe_level() >= 1 && !rb_path_check(f)) {
- rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
- }
- if (file_load_ok(f)) return path;
- }
-
- if (rb_safe_level() >= 4) {
- rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f);
- }
-
- if (rb_load_path) {
- long i;
-
- Check_Type(rb_load_path, T_ARRAY);
- tmp = rb_ary_new();
- for (i=0;i<RARRAY(rb_load_path)->len;i++) {
- VALUE str = RARRAY(rb_load_path)->ptr[i];
- FilePathValue(str);
- if (RSTRING(str)->len > 0) {
- rb_ary_push(tmp, str);
- }
- }
- tmp = rb_ary_join(tmp, rb_str_new2(PATH_SEP));
- if (RSTRING(tmp)->len == 0) {
- lpath = 0;
- }
- else {
- lpath = RSTRING(tmp)->ptr;
- if (rb_safe_level() >= 1 && !rb_path_check(lpath)) {
- rb_raise(rb_eSecurityError, "loading from unsafe path %s", lpath);
- }
- }
- }
- else {
- lpath = 0;
- }
-
- if (!lpath) {
- return 0; /* no path, no load */
- }
- f = dln_find_file(f, lpath);
- if (rb_safe_level() >= 1 && !rb_path_check(f)) {
- rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
- }
- if (file_load_ok(f)) {
- tmp = rb_str_new2(f);
- OBJ_FREEZE(tmp);
- return tmp;
- }
- return 0;
-}
-
-static void
-define_filetest_function(name, func, argc)
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_define_module_function(rb_mFileTest, name, func, argc);
- rb_define_singleton_method(rb_cFile, name, func, argc);
-}
-
-
-/*
- * A <code>File</code> is an abstraction of any file object accessible
- * by the program and is closely associated with class <code>IO</code>
- * <code>File</code> includes the methods of module
- * <code>FileTest</code> as class methods, allowing you to write (for
- * example) <code>File.exist?("foo")</code>.
- *
- * In the description of File methods,
- * <em>permission bits</em> are a platform-specific
- * set of bits that indicate permissions of a file. On Unix-based
- * systems, permissions are viewed as a set of three octets, for the
- * owner, the group, and the rest of the world. For each of these
- * entities, permissions may be set to read, write, or execute the
- * file:
- *
- * The permission bits <code>0644</code> (in octal) would thus be
- * interpreted as read/write for owner, and read-only for group and
- * other. Higher-order bits may also be used to indicate the type of
- * file (plain, directory, pipe, socket, and so on) and various other
- * special features. If the permissions are for a directory, the
- * meaning of the execute bit changes; when set the directory can be
- * searched.
- *
- * On non-Posix operating systems, there may be only the ability to
- * make a file read-only or read-write. In this case, the remaining
- * permission bits will be synthesized to resemble typical values. For
- * instance, on Windows NT the default permission bits are
- * <code>0644</code>, which means read/write for owner, read-only for
- * all others. The only change that can be made is to make the file
- * read-only, which is reported as <code>0444</code>.
- */
-
-void
-Init_File()
-{
- rb_mFileTest = rb_define_module("FileTest");
- rb_cFile = rb_define_class("File", rb_cIO);
-
- define_filetest_function("directory?", test_d, 1);
- define_filetest_function("exist?", test_e, 1);
- define_filetest_function("exists?", test_e, 1); /* temporary */
- define_filetest_function("readable?", test_r, 1);
- define_filetest_function("readable_real?", test_R, 1);
- define_filetest_function("world_readable?", test_wr, 1);
- define_filetest_function("writable?", test_w, 1);
- define_filetest_function("writable_real?", test_W, 1);
- define_filetest_function("world_writable?", test_ww, 1);
- define_filetest_function("executable?", test_x, 1);
- define_filetest_function("executable_real?", test_X, 1);
- define_filetest_function("file?", test_f, 1);
- define_filetest_function("zero?", test_z, 1);
- define_filetest_function("size?", test_s, 1);
- define_filetest_function("size", rb_file_s_size, 1);
- define_filetest_function("owned?", test_owned, 1);
- define_filetest_function("grpowned?", test_grpowned, 1);
-
- define_filetest_function("pipe?", test_p, 1);
- define_filetest_function("symlink?", test_l, 1);
- define_filetest_function("socket?", test_S, 1);
-
- define_filetest_function("blockdev?", test_b, 1);
- define_filetest_function("chardev?", test_c, 1);
-
- define_filetest_function("setuid?", test_suid, 1);
- define_filetest_function("setgid?", test_sgid, 1);
- define_filetest_function("sticky?", test_sticky, 1);
-
- rb_define_singleton_method(rb_cFile, "stat", rb_file_s_stat, 1);
- rb_define_singleton_method(rb_cFile, "lstat", rb_file_s_lstat, 1);
- rb_define_singleton_method(rb_cFile, "ftype", rb_file_s_ftype, 1);
-
- rb_define_singleton_method(rb_cFile, "atime", rb_file_s_atime, 1);
- rb_define_singleton_method(rb_cFile, "mtime", rb_file_s_mtime, 1);
- rb_define_singleton_method(rb_cFile, "ctime", rb_file_s_ctime, 1);
-
- rb_define_singleton_method(rb_cFile, "utime", rb_file_s_utime, -1);
- rb_define_singleton_method(rb_cFile, "chmod", rb_file_s_chmod, -1);
- rb_define_singleton_method(rb_cFile, "chown", rb_file_s_chown, -1);
- rb_define_singleton_method(rb_cFile, "lchmod", rb_file_s_lchmod, -1);
- rb_define_singleton_method(rb_cFile, "lchown", rb_file_s_lchown, -1);
-
- rb_define_singleton_method(rb_cFile, "link", rb_file_s_link, 2);
- rb_define_singleton_method(rb_cFile, "symlink", rb_file_s_symlink, 2);
- rb_define_singleton_method(rb_cFile, "readlink", rb_file_s_readlink, 1);
-
- rb_define_singleton_method(rb_cFile, "unlink", rb_file_s_unlink, -2);
- rb_define_singleton_method(rb_cFile, "delete", rb_file_s_unlink, -2);
- rb_define_singleton_method(rb_cFile, "rename", rb_file_s_rename, 2);
- rb_define_singleton_method(rb_cFile, "umask", rb_file_s_umask, -1);
- rb_define_singleton_method(rb_cFile, "truncate", rb_file_s_truncate, 2);
- rb_define_singleton_method(rb_cFile, "expand_path", rb_file_s_expand_path, -1);
- rb_define_singleton_method(rb_cFile, "basename", rb_file_s_basename, -1);
- rb_define_singleton_method(rb_cFile, "dirname", rb_file_s_dirname, 1);
- rb_define_singleton_method(rb_cFile, "extname", rb_file_s_extname, 1);
- rb_define_singleton_method(rb_cFile, "path", rb_file_s_path, 1);
-
- separator = rb_obj_freeze(rb_str_new2("/"));
- rb_define_const(rb_cFile, "Separator", separator);
- rb_define_const(rb_cFile, "SEPARATOR", separator);
- rb_define_singleton_method(rb_cFile, "split", rb_file_s_split, 1);
- rb_define_singleton_method(rb_cFile, "join", rb_file_s_join, -2);
-
-#ifdef DOSISH
- rb_define_const(rb_cFile, "ALT_SEPARATOR", rb_obj_freeze(rb_str_new2("\\")));
-#else
- rb_define_const(rb_cFile, "ALT_SEPARATOR", Qnil);
-#endif
- rb_define_const(rb_cFile, "PATH_SEPARATOR", rb_obj_freeze(rb_str_new2(PATH_SEP)));
-
- rb_define_method(rb_cIO, "stat", rb_io_stat, 0); /* this is IO's method */
- rb_define_method(rb_cFile, "lstat", rb_file_lstat, 0);
-
- rb_define_method(rb_cFile, "atime", rb_file_atime, 0);
- rb_define_method(rb_cFile, "mtime", rb_file_mtime, 0);
- rb_define_method(rb_cFile, "ctime", rb_file_ctime, 0);
-
- rb_define_method(rb_cFile, "chmod", rb_file_chmod, 1);
- rb_define_method(rb_cFile, "chown", rb_file_chown, 2);
- rb_define_method(rb_cFile, "truncate", rb_file_truncate, 1);
-
- rb_define_method(rb_cFile, "flock", rb_file_flock, 1);
-
- rb_mFConst = rb_define_module_under(rb_cFile, "Constants");
- rb_include_module(rb_cIO, rb_mFConst);
- rb_file_const("LOCK_SH", INT2FIX(LOCK_SH));
- rb_file_const("LOCK_EX", INT2FIX(LOCK_EX));
- rb_file_const("LOCK_UN", INT2FIX(LOCK_UN));
- rb_file_const("LOCK_NB", INT2FIX(LOCK_NB));
-
- rb_define_method(rb_cFile, "path", rb_file_path, 0);
- rb_define_global_function("test", rb_f_test, -1);
-
- rb_cStat = rb_define_class_under(rb_cFile, "Stat", rb_cObject);
- rb_define_alloc_func(rb_cStat, rb_stat_s_alloc);
- rb_define_method(rb_cStat, "initialize", rb_stat_init, 1);
- rb_define_method(rb_cStat, "initialize_copy", rb_stat_init_copy, 1);
-
- rb_include_module(rb_cStat, rb_mComparable);
-
- rb_define_method(rb_cStat, "<=>", rb_stat_cmp, 1);
-
- rb_define_method(rb_cStat, "dev", rb_stat_dev, 0);
- rb_define_method(rb_cStat, "dev_major", rb_stat_dev_major, 0);
- rb_define_method(rb_cStat, "dev_minor", rb_stat_dev_minor, 0);
- rb_define_method(rb_cStat, "ino", rb_stat_ino, 0);
- rb_define_method(rb_cStat, "mode", rb_stat_mode, 0);
- rb_define_method(rb_cStat, "nlink", rb_stat_nlink, 0);
- rb_define_method(rb_cStat, "uid", rb_stat_uid, 0);
- rb_define_method(rb_cStat, "gid", rb_stat_gid, 0);
- rb_define_method(rb_cStat, "rdev", rb_stat_rdev, 0);
- rb_define_method(rb_cStat, "rdev_major", rb_stat_rdev_major, 0);
- rb_define_method(rb_cStat, "rdev_minor", rb_stat_rdev_minor, 0);
- rb_define_method(rb_cStat, "size", rb_stat_size, 0);
- rb_define_method(rb_cStat, "blksize", rb_stat_blksize, 0);
- rb_define_method(rb_cStat, "blocks", rb_stat_blocks, 0);
- rb_define_method(rb_cStat, "atime", rb_stat_atime, 0);
- rb_define_method(rb_cStat, "mtime", rb_stat_mtime, 0);
- rb_define_method(rb_cStat, "ctime", rb_stat_ctime, 0);
-
- rb_define_method(rb_cStat, "inspect", rb_stat_inspect, 0);
-
- rb_define_method(rb_cStat, "ftype", rb_stat_ftype, 0);
-
- rb_define_method(rb_cStat, "directory?", rb_stat_d, 0);
- rb_define_method(rb_cStat, "readable?", rb_stat_r, 0);
- rb_define_method(rb_cStat, "readable_real?", rb_stat_R, 0);
- rb_define_method(rb_cStat, "world_readable?", rb_stat_wr, 0);
- rb_define_method(rb_cStat, "writable?", rb_stat_w, 0);
- rb_define_method(rb_cStat, "writable_real?", rb_stat_W, 0);
- rb_define_method(rb_cStat, "world_writable?", rb_stat_ww, 0);
- rb_define_method(rb_cStat, "executable?", rb_stat_x, 0);
- rb_define_method(rb_cStat, "executable_real?", rb_stat_X, 0);
- rb_define_method(rb_cStat, "file?", rb_stat_f, 0);
- rb_define_method(rb_cStat, "zero?", rb_stat_z, 0);
- rb_define_method(rb_cStat, "size?", rb_stat_s, 0);
- rb_define_method(rb_cStat, "owned?", rb_stat_owned, 0);
- rb_define_method(rb_cStat, "grpowned?", rb_stat_grpowned, 0);
-
- rb_define_method(rb_cStat, "pipe?", rb_stat_p, 0);
- rb_define_method(rb_cStat, "symlink?", rb_stat_l, 0);
- rb_define_method(rb_cStat, "socket?", rb_stat_S, 0);
-
- rb_define_method(rb_cStat, "blockdev?", rb_stat_b, 0);
- rb_define_method(rb_cStat, "chardev?", rb_stat_c, 0);
-
- rb_define_method(rb_cStat, "setuid?", rb_stat_suid, 0);
- rb_define_method(rb_cStat, "setgid?", rb_stat_sgid, 0);
- rb_define_method(rb_cStat, "sticky?", rb_stat_sticky, 0);
-}
-/**********************************************************************
-
- gc.c -
-
- $Author: nobu $
- $Date: 2005/04/30 02:59:41 $
- created at: Tue Oct 5 09:44:46 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 "rubysig.h"
-#include "st.h"
-#include "node.h"
-#include "env.h"
-#include "re.h"
-#include <stdio.h>
-#include <setjmp.h>
-#include <sys/types.h>
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-
-#ifdef __ia64__
-#include <ucontext.h>
-#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
-
-#if defined _WIN32 || defined __CYGWIN__
-#include <windows.h>
-#endif
-
-int rb_io_fptr_finalize _((struct OpenFile*));
-
-#if !defined(setjmp) && defined(HAVE__SETJMP)
-#define setjmp(env) _setjmp(env)
-#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__ */
-
-#ifndef GC_MALLOC_LIMIT
-#if defined(MSDOS) || defined(__human68k__)
-#define GC_MALLOC_LIMIT 200000
-#else
-#define GC_MALLOC_LIMIT 8000000
-#endif
-#endif
-
-static unsigned long malloc_increase = 0;
-static unsigned long malloc_limit = GC_MALLOC_LIMIT;
-static void run_final();
-static VALUE nomem_error;
-static void garbage_collect();
-
-void
-rb_memerror()
-{
- static int recurse = 0;
-
- if (recurse > 0 && rb_safe_level() < 4) {
- fprintf(stderr, "[FATAL] failed to allocate memory\n");
- exit(1);
- }
- recurse++;
- rb_exc_raise(nomem_error);
-}
-
-void *
-ruby_xmalloc(size)
- long size;
-{
- void *mem;
-
- if (size < 0) {
- rb_raise(rb_eNoMemError, "negative allocation size (or too big)");
- }
- if (size == 0) size = 1;
- malloc_increase += size;
-
- if (malloc_increase > malloc_limit) {
- garbage_collect();
- }
- RUBY_CRITICAL(mem = malloc(size));
- if (!mem) {
- garbage_collect();
- RUBY_CRITICAL(mem = malloc(size));
- if (!mem) {
- rb_memerror();
- }
- }
-
- return mem;
-}
-
-void *
-ruby_xcalloc(n, size)
- long n, size;
-{
- void *mem;
-
- mem = xmalloc(n * size);
- memset(mem, 0, n * size);
-
- return mem;
-}
-
-void *
-ruby_xrealloc(ptr, size)
- void *ptr;
- long size;
-{
- void *mem;
-
- if (size < 0) {
- rb_raise(rb_eArgError, "negative re-allocation size");
- }
- if (!ptr) return xmalloc(size);
- if (size == 0) size = 1;
- malloc_increase += size;
- RUBY_CRITICAL(mem = realloc(ptr, size));
- if (!mem) {
- garbage_collect();
- RUBY_CRITICAL(mem = realloc(ptr, size));
- if (!mem) {
- rb_memerror();
- }
- }
-
- return mem;
-}
-
-void
-ruby_xfree(x)
- void *x;
-{
- if (x)
- RUBY_CRITICAL(free(x));
-}
-
-static int dont_gc;
-static int during_gc;
-static int need_call_final = 0;
-static st_table *finalizer_table = 0;
-
-
-/*
- * call-seq:
- * GC.enable => true or false
- *
- * Enables garbage collection, returning <code>true</code> if garbage
- * collection was previously disabled.
- *
- * GC.disable #=> false
- * GC.enable #=> true
- * GC.enable #=> false
- *
- */
-
-VALUE
-rb_gc_enable()
-{
- int old = dont_gc;
-
- dont_gc = Qfalse;
- return old;
-}
-
-/*
- * call-seq:
- * GC.disable => true or false
- *
- * Disables garbage collection, returning <code>true</code> if garbage
- * collection was already disabled.
- *
- * GC.disable #=> false
- * GC.disable #=> true
- *
- */
-
-VALUE
-rb_gc_disable()
-{
- int old = dont_gc;
-
- dont_gc = Qtrue;
- return old;
-}
-
-VALUE rb_mGC;
-
-static struct gc_list {
- VALUE *varptr;
- struct gc_list *next;
-} *global_List = 0;
-
-void
-rb_gc_register_address(addr)
- VALUE *addr;
-{
- struct gc_list *tmp;
-
- tmp = ALLOC(struct gc_list);
- tmp->next = global_List;
- tmp->varptr = addr;
- global_List = tmp;
-}
-
-void
-rb_gc_unregister_address(addr)
- VALUE *addr;
-{
- struct gc_list *tmp = global_List;
-
- if (tmp->varptr == addr) {
- global_List = tmp->next;
- RUBY_CRITICAL(free(tmp));
- return;
- }
- while (tmp->next) {
- if (tmp->next->varptr == addr) {
- struct gc_list *t = tmp->next;
-
- tmp->next = tmp->next->next;
- RUBY_CRITICAL(free(t));
- break;
- }
- tmp = tmp->next;
- }
-}
-
-#undef GC_DEBUG
-
-void
-rb_global_variable(var)
- VALUE *var;
-{
- rb_gc_register_address(var);
-}
-
-typedef struct RVALUE {
- union {
- struct {
- unsigned long flags; /* always 0 for freed obj */
- struct RVALUE *next;
- } free;
- struct RBasic basic;
- struct RObject object;
- struct RClass klass;
- struct RFloat flonum;
- struct RString string;
- struct RArray array;
- struct RRegexp regexp;
- struct RHash hash;
- struct RData data;
- struct RStruct rstruct;
- struct RBignum bignum;
- struct RFile file;
- struct RNode node;
- struct RMatch match;
- struct RVarmap varmap;
- struct SCOPE scope;
- } as;
-#ifdef GC_DEBUG
- char *file;
- int line;
-#endif
-} RVALUE;
-
-static RVALUE *freelist = 0;
-static RVALUE *deferred_final_list = 0;
-
-#define HEAPS_INCREMENT 10
-static struct heaps_slot {
- RVALUE *slot;
- int limit;
-} *heaps;
-static int heaps_length = 0;
-static int heaps_used = 0;
-
-#define HEAP_MIN_SLOTS 10000
-static int heap_slots = HEAP_MIN_SLOTS;
-
-#define FREE_MIN 4096
-
-static RVALUE *himem, *lomem;
-
-static void
-add_heap()
-{
- RVALUE *p, *pend;
-
- if (heaps_used == heaps_length) {
- /* Realloc heaps */
- struct heaps_slot *p;
- int length;
-
- heaps_length += HEAPS_INCREMENT;
- length = heaps_length*sizeof(struct heaps_slot);
- RUBY_CRITICAL(
- if (heaps_used > 0) {
- p = (struct heaps_slot *)realloc(heaps, length);
- if (p) heaps = p;
- }
- else {
- p = heaps = (struct heaps_slot *)malloc(length);
- });
- if (p == 0) rb_memerror();
- }
-
- for (;;) {
- RUBY_CRITICAL(p = heaps[heaps_used].slot = (RVALUE*)malloc(sizeof(RVALUE)*heap_slots));
- heaps[heaps_used].limit = heap_slots;
- if (p == 0) {
- if (heap_slots == HEAP_MIN_SLOTS) {
- rb_memerror();
- }
- heap_slots = HEAP_MIN_SLOTS;
- continue;
- }
- break;
- }
- pend = p + heap_slots;
- if (lomem == 0 || lomem > p) lomem = p;
- if (himem < pend) himem = pend;
- heaps_used++;
- heap_slots *= 1.8;
-
- while (p < pend) {
- p->as.free.flags = 0;
- p->as.free.next = freelist;
- freelist = p;
- p++;
- }
-}
-#define RANY(o) ((RVALUE*)(o))
-
-VALUE
-rb_newobj()
-{
- VALUE obj;
-
- if (!freelist) garbage_collect();
-
- obj = (VALUE)freelist;
- freelist = freelist->as.free.next;
- MEMZERO((void*)obj, RVALUE, 1);
-#ifdef GC_DEBUG
- RANY(obj)->file = ruby_sourcefile;
- RANY(obj)->line = ruby_sourceline;
-#endif
- return obj;
-}
-
-VALUE
-rb_data_object_alloc(klass, datap, dmark, dfree)
- VALUE klass;
- void *datap;
- RUBY_DATA_FUNC dmark;
- RUBY_DATA_FUNC dfree;
-{
- NEWOBJ(data, struct RData);
- if (klass) Check_Type(klass, T_CLASS);
- OBJSETUP(data, klass, T_DATA);
- data->data = datap;
- data->dfree = dfree;
- data->dmark = dmark;
-
- return (VALUE)data;
-}
-
-extern st_table *rb_class_tbl;
-VALUE *rb_gc_stack_start = 0;
-
-#ifdef DJGPP
-/* set stack size (http://www.delorie.com/djgpp/v2faq/faq15_9.html) */
-unsigned int _stklen = 0x180000; /* 1.5 kB */
-#endif
-
-#if defined(DJGPP) || defined(_WIN32_WCE)
-static unsigned int STACK_LEVEL_MAX = 65535;
-#elif defined(__human68k__)
-unsigned int _stacksize = 262144;
-# define STACK_LEVEL_MAX (_stacksize - 4096)
-# undef HAVE_GETRLIMIT
-#elif defined(HAVE_GETRLIMIT)
-static unsigned int STACK_LEVEL_MAX = 655300;
-#else
-# define STACK_LEVEL_MAX 655300
-#endif
-
-NOINLINE(static void set_stack_end _((VALUE **stack_end_p)));
-
-static void
-set_stack_end(VALUE **stack_end_p)
-{
- VALUE stack_end;
- *stack_end_p = &stack_end;
-}
-#define SET_STACK_END VALUE *stack_end; set_stack_end(&stack_end)
-#define STACK_END (stack_end)
-
-#if defined(sparc) || defined(__sparc__)
-# define STACK_LENGTH (rb_gc_stack_start - STACK_END + 0x80)
-#elif STACK_GROW_DIRECTION < 0
-# define STACK_LENGTH (rb_gc_stack_start - STACK_END)
-#elif STACK_GROW_DIRECTION > 0
-# define STACK_LENGTH (STACK_END - rb_gc_stack_start + 1)
-#else
-# define STACK_LENGTH ((STACK_END < rb_gc_stack_start) ? rb_gc_stack_start - STACK_END\
- : STACK_END - rb_gc_stack_start + 1)
-#endif
-#if STACK_GROW_DIRECTION > 0
-# define STACK_UPPER(x, a, b) a
-#elif STACK_GROW_DIRECTION < 0
-# define STACK_UPPER(x, a, b) b
-#else
-static int grow_direction;
-static int
-stack_grow_direction(addr)
- VALUE *addr;
-{
- SET_STACK_END;
-
- if (STACK_END > addr) return grow_direction = 1;
- return grow_direction = -1;
-}
-# define stack_growup_p(x) ((grow_direction ? grow_direction : stack_grow_direction(x)) > 0)
-# define STACK_UPPER(x, a, b) (stack_growup_p(x) ? a : b)
-#endif
-
-#define GC_WATER_MARK 512
-
-#define CHECK_STACK(ret) do {\
- SET_STACK_END;\
- (ret) = (STACK_LENGTH > STACK_LEVEL_MAX + GC_WATER_MARK);\
-} while (0)
-
-int
-ruby_stack_length(p)
- VALUE **p;
-{
- SET_STACK_END;
- if (p) *p = STACK_UPPER(STACK_END, rb_gc_stack_start, STACK_END);
- return STACK_LENGTH;
-}
-
-int
-ruby_stack_check()
-{
- int ret;
-
- CHECK_STACK(ret);
- return ret;
-}
-
-#define MARK_STACK_MAX 1024
-static VALUE mark_stack[MARK_STACK_MAX];
-static VALUE *mark_stack_ptr;
-static int mark_stack_overflow;
-
-static void
-init_mark_stack()
-{
- mark_stack_overflow = 0;
- mark_stack_ptr = mark_stack;
-}
-
-#define MARK_STACK_EMPTY (mark_stack_ptr == mark_stack)
-
-static st_table *source_filenames;
-
-char *
-rb_source_filename(f)
- const char *f;
-{
- char *name;
-
- if (!st_lookup(source_filenames, (st_data_t)f, (st_data_t *)&name)) {
- long len = strlen(f) + 1;
- char *ptr = name = ALLOC_N(char, len + 1);
- *ptr++ = 0;
- MEMCPY(ptr, f, char, len);
- st_add_direct(source_filenames, (st_data_t)ptr, (st_data_t)name);
- return ptr;
- }
- return name + 1;
-}
-
-static void
-mark_source_filename(f)
- char *f;
-{
- if (f) {
- f[-1] = 1;
- }
-}
-
-static int
-sweep_source_filename(key, value)
- char *key, *value;
-{
- if (*value) {
- *value = 0;
- return ST_CONTINUE;
- }
- else {
- free(value);
- return ST_DELETE;
- }
-}
-
-static void gc_mark _((VALUE ptr, int lev));
-static void gc_mark_children _((VALUE ptr, int lev));
-
-static void
-gc_mark_all()
-{
- RVALUE *p, *pend;
- int i;
-
- init_mark_stack();
- for (i = 0; i < heaps_used; i++) {
- p = heaps[i].slot; pend = p + heaps[i].limit;
- while (p < pend) {
- if ((p->as.basic.flags & FL_MARK) &&
- (p->as.basic.flags != FL_MARK)) {
- gc_mark_children((VALUE)p, 0);
- }
- p++;
- }
- }
-}
-
-static void
-gc_mark_rest()
-{
- VALUE tmp_arry[MARK_STACK_MAX];
- VALUE *p;
-
- p = (mark_stack_ptr - mark_stack) + tmp_arry;
- MEMCPY(tmp_arry, mark_stack, VALUE, MARK_STACK_MAX);
-
- init_mark_stack();
- while(p != tmp_arry){
- p--;
- gc_mark_children(*p, 0);
- }
-}
-
-static inline int
-is_pointer_to_heap(ptr)
- void *ptr;
-{
- register RVALUE *p = RANY(ptr);
- register RVALUE *heap_org;
- register long i;
-
- if (p < lomem || p > himem) return Qfalse;
-
- /* check if p looks like a pointer */
- for (i=0; i < heaps_used; i++) {
- heap_org = heaps[i].slot;
- if (heap_org <= p && p < heap_org + heaps[i].limit &&
- ((((char*)p)-((char*)heap_org))%sizeof(RVALUE)) == 0)
- return Qtrue;
- }
- return Qfalse;
-}
-
-static void
-mark_locations_array(x, n)
- register VALUE *x;
- register long n;
-{
- VALUE v;
- while (n--) {
- v = *x;
- if (is_pointer_to_heap((void *)v)) {
- gc_mark(v, 0);
- }
- x++;
- }
-}
-
-void
-rb_gc_mark_locations(start, end)
- VALUE *start, *end;
-{
- long n;
-
- n = end - start;
- mark_locations_array(start,n);
-}
-
-static int
-mark_entry(key, value, lev)
- ID key;
- VALUE value;
- int lev;
-{
- gc_mark(value, lev);
- return ST_CONTINUE;
-}
-
-void
-mark_tbl(tbl, lev)
- st_table *tbl;
- int lev;
-{
- if (!tbl) return;
- st_foreach(tbl, mark_entry, lev);
-}
-
-void
-rb_mark_tbl(tbl)
- st_table *tbl;
-{
- mark_tbl(tbl, 0);
-}
-
-static int
-mark_keyvalue(key, value, lev)
- VALUE key;
- VALUE value;
- int lev;
-{
- gc_mark(key, lev);
- gc_mark(value, lev);
- return ST_CONTINUE;
-}
-
-void
-mark_hash(tbl, lev)
- st_table *tbl;
- int lev;
-{
- if (!tbl) return;
- st_foreach(tbl, mark_keyvalue, lev);
-}
-
-void
-rb_mark_hash(tbl)
- st_table *tbl;
-{
- mark_hash(tbl, 0);
-}
-
-void
-rb_gc_mark_maybe(obj)
- VALUE obj;
-{
- if (is_pointer_to_heap((void *)obj)) {
- gc_mark(obj, 0);
- }
-}
-
-#define GC_LEVEL_MAX 250
-
-void
-gc_mark(ptr, lev)
- VALUE ptr;
- int lev;
-{
- register RVALUE *obj;
-
- obj = RANY(ptr);
- if (rb_special_const_p(ptr)) return; /* special const not marked */
- if (obj->as.basic.flags == 0) return; /* free cell */
- if (obj->as.basic.flags & FL_MARK) return; /* already marked */
- obj->as.basic.flags |= FL_MARK;
-
- if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) {
- if (!mark_stack_overflow) {
- if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) {
- *mark_stack_ptr = ptr;
- mark_stack_ptr++;
- }
- else {
- mark_stack_overflow = 1;
- }
- }
- return;
- }
- gc_mark_children(ptr, lev+1);
-}
-
-void
-rb_gc_mark(ptr)
- VALUE ptr;
-{
- gc_mark(ptr, 0);
-}
-
-static void
-gc_mark_children(ptr, lev)
- VALUE ptr;
- int lev;
-{
- register RVALUE *obj = RANY(ptr);
-
- goto marking; /* skip */
-
- again:
- obj = RANY(ptr);
- if (rb_special_const_p(ptr)) return; /* special const not marked */
- if (obj->as.basic.flags == 0) return; /* free cell */
- if (obj->as.basic.flags & FL_MARK) return; /* already marked */
- obj->as.basic.flags |= FL_MARK;
-
- marking:
- if (FL_TEST(obj, FL_EXIVAR)) {
- rb_mark_generic_ivar(ptr);
- }
-
- switch (obj->as.basic.flags & T_MASK) {
- case T_NIL:
- case T_FIXNUM:
- rb_bug("rb_gc_mark() called for broken object");
- break;
-
- case T_NODE:
- mark_source_filename(obj->as.node.nd_file);
- switch (nd_type(obj)) {
- case NODE_IF: /* 1,2,3 */
- case NODE_FOR:
- case NODE_ITER:
- case NODE_CREF:
- case NODE_WHEN:
- case NODE_MASGN:
- case NODE_RESCUE:
- case NODE_RESBODY:
- case NODE_CLASS:
- gc_mark((VALUE)obj->as.node.u2.node, lev);
- /* fall through */
- case NODE_BLOCK: /* 1,3 */
- case NODE_ARRAY:
- case NODE_DSTR:
- case NODE_DXSTR:
- case NODE_DREGX:
- case NODE_DREGX_ONCE:
- case NODE_FBODY:
- case NODE_ENSURE:
- case NODE_CALL:
- case NODE_DEFS:
- case NODE_OP_ASGN1:
- gc_mark((VALUE)obj->as.node.u1.node, lev);
- /* fall through */
- case NODE_SUPER: /* 3 */
- case NODE_FCALL:
- case NODE_DEFN:
- ptr = (VALUE)obj->as.node.u3.node;
- goto again;
-
- case NODE_WHILE: /* 1,2 */
- case NODE_UNTIL:
- case NODE_AND:
- case NODE_OR:
- case NODE_CASE:
- case NODE_SCLASS:
- case NODE_DOT2:
- case NODE_DOT3:
- case NODE_FLIP2:
- case NODE_FLIP3:
- case NODE_MATCH2:
- case NODE_MATCH3:
- case NODE_OP_ASGN_OR:
- case NODE_OP_ASGN_AND:
- case NODE_MODULE:
- case NODE_ALIAS:
- case NODE_VALIAS:
- gc_mark((VALUE)obj->as.node.u1.node, lev);
- /* fall through */
- case NODE_METHOD: /* 2 */
- case NODE_NOT:
- case NODE_GASGN:
- case NODE_LASGN:
- case NODE_DASGN:
- case NODE_DASGN_CURR:
- case NODE_IASGN:
- case NODE_CVDECL:
- case NODE_CVASGN:
- case NODE_COLON3:
- case NODE_OPT_N:
- case NODE_EVSTR:
- case NODE_UNDEF:
- ptr = (VALUE)obj->as.node.u2.node;
- goto again;
-
- case NODE_HASH: /* 1 */
- case NODE_LIT:
- case NODE_STR:
- case NODE_XSTR:
- case NODE_DEFINED:
- case NODE_MATCH:
- case NODE_RETURN:
- case NODE_BREAK:
- case NODE_NEXT:
- case NODE_YIELD:
- case NODE_COLON2:
- case NODE_ARGS:
- case NODE_SPLAT:
- case NODE_TO_ARY:
- case NODE_SVALUE:
- ptr = (VALUE)obj->as.node.u1.node;
- goto again;
-
- case NODE_SCOPE: /* 2,3 */
- case NODE_BLOCK_PASS:
- case NODE_CDECL:
- gc_mark((VALUE)obj->as.node.u3.node, lev);
- ptr = (VALUE)obj->as.node.u2.node;
- goto again;
-
- case NODE_ZARRAY: /* - */
- case NODE_ZSUPER:
- case NODE_CFUNC:
- case NODE_VCALL:
- case NODE_GVAR:
- case NODE_LVAR:
- case NODE_DVAR:
- case NODE_IVAR:
- case NODE_CVAR:
- case NODE_NTH_REF:
- case NODE_BACK_REF:
- case NODE_REDO:
- case NODE_RETRY:
- case NODE_SELF:
- case NODE_NIL:
- case NODE_TRUE:
- case NODE_FALSE:
- case NODE_ERRINFO:
- case NODE_ATTRSET:
- case NODE_BLOCK_ARG:
- case NODE_POSTEXE:
- break;
-#ifdef C_ALLOCA
- case NODE_ALLOCA:
- mark_locations_array((VALUE*)obj->as.node.u1.value,
- obj->as.node.u3.cnt);
- ptr = (VALUE)obj->as.node.u2.node;
- goto again;
-#endif
-
- default: /* unlisted NODE */
- if (is_pointer_to_heap(obj->as.node.u1.node)) {
- gc_mark((VALUE)obj->as.node.u1.node, lev);
- }
- if (is_pointer_to_heap(obj->as.node.u2.node)) {
- gc_mark((VALUE)obj->as.node.u2.node, lev);
- }
- if (is_pointer_to_heap(obj->as.node.u3.node)) {
- gc_mark((VALUE)obj->as.node.u3.node, lev);
- }
- }
- return; /* no need to mark class. */
- }
-
- gc_mark(obj->as.basic.klass, lev);
- switch (obj->as.basic.flags & T_MASK) {
- case T_ICLASS:
- case T_CLASS:
- case T_MODULE:
- mark_tbl(obj->as.klass.m_tbl, lev);
- mark_tbl(obj->as.klass.iv_tbl, lev);
- ptr = obj->as.klass.super;
- goto again;
-
- case T_ARRAY:
- if (FL_TEST(obj, ELTS_SHARED)) {
- ptr = obj->as.array.aux.shared;
- goto again;
- }
- else {
- long i, len = obj->as.array.len;
- VALUE *ptr = obj->as.array.ptr;
-
- for (i=0; i < len; i++) {
- gc_mark(*ptr++, lev);
- }
- }
- break;
-
- case T_HASH:
- mark_hash(obj->as.hash.tbl, lev);
- ptr = obj->as.hash.ifnone;
- goto again;
-
- case T_STRING:
-#define STR_ASSOC FL_USER3 /* copied from string.c */
- if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) {
- ptr = obj->as.string.aux.shared;
- goto again;
- }
- break;
-
- case T_DATA:
- if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj));
- break;
-
- case T_OBJECT:
- mark_tbl(obj->as.object.iv_tbl, lev);
- break;
-
- case T_FILE:
- case T_REGEXP:
- case T_FLOAT:
- case T_BIGNUM:
- case T_BLOCK:
- break;
-
- case T_MATCH:
- if (obj->as.match.str) {
- ptr = obj->as.match.str;
- goto again;
- }
- break;
-
- case T_VARMAP:
- gc_mark(obj->as.varmap.val, lev);
- ptr = (VALUE)obj->as.varmap.next;
- goto again;
-
- case T_SCOPE:
- if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) {
- int n = obj->as.scope.local_tbl[0]+1;
- VALUE *vars = &obj->as.scope.local_vars[-1];
-
- while (n--) {
- gc_mark(*vars++, lev);
- }
- }
- break;
-
- case T_STRUCT:
- {
- long len = obj->as.rstruct.len;
- VALUE *ptr = obj->as.rstruct.ptr;
-
- while (len--) {
- gc_mark(*ptr++, lev);
- }
- }
- break;
-
- default:
- rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s",
- obj->as.basic.flags & T_MASK, obj,
- is_pointer_to_heap(obj) ? "corrupted object" : "non object");
- }
-}
-
-static void obj_free _((VALUE));
-
-static void
-finalize_list(p)
- RVALUE *p;
-{
- while (p) {
- RVALUE *tmp = p->as.free.next;
- run_final((VALUE)p);
- if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
- p->as.free.flags = 0;
- p->as.free.next = freelist;
- freelist = p;
- }
- p = tmp;
- }
-}
-
-static void
-free_unused_heaps()
-{
- int i, j;
-
- for (i = j = 1; j < heaps_used; i++) {
- if (heaps[i].limit == 0) {
- free(heaps[i].slot);
- heaps_used--;
- }
- else {
- if (i != j) {
- heaps[j] = heaps[i];
- }
- j++;
- }
- }
-}
-
-static void
-gc_sweep()
-{
- RVALUE *p, *pend, *final_list;
- int freed = 0;
- int i;
- unsigned long live = 0;
-
- mark_source_filename(ruby_sourcefile);
- st_foreach(source_filenames, sweep_source_filename, 0);
-
- freelist = 0;
- final_list = deferred_final_list;
- deferred_final_list = 0;
- for (i = 0; i < heaps_used; i++) {
- int n = 0;
- RVALUE *free = freelist;
- RVALUE *final = final_list;
-
- p = heaps[i].slot; pend = p + heaps[i].limit;
- while (p < pend) {
- if (!(p->as.basic.flags & FL_MARK)) {
- if (p->as.basic.flags) {
- obj_free((VALUE)p);
- }
- if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
- p->as.free.flags = FL_MARK; /* remain marked */
- p->as.free.next = final_list;
- final_list = p;
- }
- else {
- p->as.free.flags = 0;
- p->as.free.next = freelist;
- freelist = p;
- }
- n++;
- }
- else if (RBASIC(p)->flags == FL_MARK) {
- /* objects to be finalized */
- /* do notning remain marked */
- }
- else {
- RBASIC(p)->flags &= ~FL_MARK;
- live++;
- }
- p++;
- }
- if (n == heaps[i].limit && freed > FREE_MIN) {
- RVALUE *pp;
-
- heaps[i].limit = 0;
- for (pp = final_list; pp != final; pp = pp->as.free.next) {
- p->as.free.flags |= FL_SINGLETON; /* freeing page mark */
- }
- freelist = free; /* cancel this page from freelist */
- }
- else {
- freed += n;
- }
- }
- if (malloc_increase > malloc_limit) {
- malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);
- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
- }
- malloc_increase = 0;
- if (freed < FREE_MIN) {
- add_heap();
- }
- during_gc = 0;
-
- /* clear finalization list */
- if (final_list) {
- deferred_final_list = final_list;
- return;
- }
- free_unused_heaps();
-}
-
-void
-rb_gc_force_recycle(p)
- VALUE p;
-{
- RANY(p)->as.free.flags = 0;
- RANY(p)->as.free.next = freelist;
- freelist = RANY(p);
-}
-
-static void
-obj_free(obj)
- VALUE obj;
-{
- switch (RANY(obj)->as.basic.flags & T_MASK) {
- case T_NIL:
- case T_FIXNUM:
- case T_TRUE:
- case T_FALSE:
- rb_bug("obj_free() called for broken object");
- break;
- }
-
- if (FL_TEST(obj, FL_EXIVAR)) {
- rb_free_generic_ivar((VALUE)obj);
- }
-
- switch (RANY(obj)->as.basic.flags & T_MASK) {
- case T_OBJECT:
- if (RANY(obj)->as.object.iv_tbl) {
- st_free_table(RANY(obj)->as.object.iv_tbl);
- }
- break;
- case T_MODULE:
- case T_CLASS:
- rb_clear_cache_by_class((VALUE)obj);
- st_free_table(RANY(obj)->as.klass.m_tbl);
- if (RANY(obj)->as.object.iv_tbl) {
- st_free_table(RANY(obj)->as.object.iv_tbl);
- }
- break;
- case T_STRING:
- if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) {
- RUBY_CRITICAL(free(RANY(obj)->as.string.ptr));
- }
- break;
- case T_ARRAY:
- if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) {
- RUBY_CRITICAL(free(RANY(obj)->as.array.ptr));
- }
- break;
- case T_HASH:
- if (RANY(obj)->as.hash.tbl) {
- st_free_table(RANY(obj)->as.hash.tbl);
- }
- break;
- case T_REGEXP:
- if (RANY(obj)->as.regexp.ptr) {
- onig_free(RANY(obj)->as.regexp.ptr);
- }
- if (RANY(obj)->as.regexp.str) {
- RUBY_CRITICAL(free(RANY(obj)->as.regexp.str));
- }
- break;
- case T_DATA:
- if (DATA_PTR(obj)) {
- if ((long)RANY(obj)->as.data.dfree == -1) {
- RUBY_CRITICAL(free(DATA_PTR(obj)));
- }
- else if (RANY(obj)->as.data.dfree) {
- (*RANY(obj)->as.data.dfree)(DATA_PTR(obj));
- }
- }
- break;
- case T_MATCH:
- if (RANY(obj)->as.match.regs) {
- onig_region_free(RANY(obj)->as.match.regs, 0);
- RUBY_CRITICAL(free(RANY(obj)->as.match.regs));
- }
- break;
- case T_FILE:
- if (RANY(obj)->as.file.fptr) {
- rb_io_fptr_finalize(RANY(obj)->as.file.fptr);
- }
- break;
- case T_ICLASS:
- /* iClass shares table with the module */
- break;
-
- case T_FLOAT:
- case T_VARMAP:
- case T_BLOCK:
- break;
-
- case T_BIGNUM:
- if (RANY(obj)->as.bignum.digits) {
- RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits));
- }
- break;
- case T_NODE:
- switch (nd_type(obj)) {
- case NODE_SCOPE:
- if (RANY(obj)->as.node.u1.tbl) {
- RUBY_CRITICAL(free(RANY(obj)->as.node.u1.tbl));
- }
- break;
-#ifdef C_ALLOCA
- case NODE_ALLOCA:
- RUBY_CRITICAL(free(RANY(obj)->as.node.u1.node));
- break;
-#endif
- }
- return; /* no need to free iv_tbl */
-
- case T_SCOPE:
- if (RANY(obj)->as.scope.local_vars &&
- RANY(obj)->as.scope.flags != SCOPE_ALLOCA) {
- VALUE *vars = RANY(obj)->as.scope.local_vars-1;
- if (vars[0] == 0)
- RUBY_CRITICAL(free(RANY(obj)->as.scope.local_tbl));
- if (RANY(obj)->as.scope.flags & SCOPE_MALLOC)
- RUBY_CRITICAL(free(vars));
- }
- break;
-
- case T_STRUCT:
- if (RANY(obj)->as.rstruct.ptr) {
- RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr));
- }
- break;
-
- default:
- rb_bug("gc_sweep(): unknown data type 0x%lx(%ld)", obj,
- RANY(obj)->as.basic.flags & T_MASK);
- }
-}
-
-void
-rb_gc_mark_frame(frame)
- struct FRAME *frame;
-{
- gc_mark((VALUE)frame->node, 0);
-}
-
-#ifdef __GNUC__
-#if defined(__human68k__) || defined(DJGPP)
-#if defined(__human68k__)
-typedef unsigned long rb_jmp_buf[8];
-__asm__ (".even\n\
-_rb_setjmp:\n\
- move.l 4(sp),a0\n\
- movem.l d3-d7/a3-a5,(a0)\n\
- moveq.l #0,d0\n\
- rts");
-#ifdef setjmp
-#undef setjmp
-#endif
-#else
-#if defined(DJGPP)
-typedef unsigned long rb_jmp_buf[6];
-__asm__ (".align 4\n\
-_rb_setjmp:\n\
- pushl %ebp\n\
- movl %esp,%ebp\n\
- movl 8(%ebp),%ebp\n\
- movl %eax,(%ebp)\n\
- movl %ebx,4(%ebp)\n\
- movl %ecx,8(%ebp)\n\
- movl %edx,12(%ebp)\n\
- movl %esi,16(%ebp)\n\
- movl %edi,20(%ebp)\n\
- popl %ebp\n\
- xorl %eax,%eax\n\
- ret");
-#endif
-#endif
-int rb_setjmp (rb_jmp_buf);
-#define jmp_buf rb_jmp_buf
-#define setjmp rb_setjmp
-#endif /* __human68k__ or DJGPP */
-#endif /* __GNUC__ */
-
-static void
-garbage_collect()
-{
- struct gc_list *list;
- struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */
- jmp_buf save_regs_gc_mark;
- SET_STACK_END;
-
-#ifdef HAVE_NATIVETHREAD
- if (!is_ruby_native_thread()) {
- rb_bug("cross-thread violation on rb_gc()");
- }
-#endif
- if (dont_gc || during_gc) {
- if (!freelist) {
- add_heap();
- }
- return;
- }
- if (during_gc) return;
- during_gc++;
-
- init_mark_stack();
-
- /* mark frame stack */
- for (frame = ruby_frame; frame; frame = frame->prev) {
- rb_gc_mark_frame(frame);
- if (frame->tmp) {
- struct FRAME *tmp = frame->tmp;
- while (tmp) {
- rb_gc_mark_frame(tmp);
- tmp = tmp->prev;
- }
- }
- }
- gc_mark((VALUE)ruby_scope, 0);
- gc_mark((VALUE)ruby_dyna_vars, 0);
- if (finalizer_table) {
- mark_tbl(finalizer_table, 0);
- }
-
- FLUSH_REGISTER_WINDOWS;
- /* This assumes that all registers are saved into the jmp_buf (and stack) */
- setjmp(save_regs_gc_mark);
- mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *));
-#if STACK_GROW_DIRECTION < 0
- rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start);
-#elif STACK_GROW_DIRECTION > 0
- rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1);
-#else
- if ((VALUE*)STACK_END < rb_gc_stack_start)
- rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start);
- else
- rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1);
-#endif
-#ifdef __ia64__
- /* mark backing store (flushed register window on the stack) */
- /* the basic idea from guile GC code */
- {
- ucontext_t ctx;
- VALUE *top, *bot;
-#ifdef HAVE_UNWIND_H
- _Unwind_Context *unwctx = _UNW_createContextForSelf();
-#endif
-
- getcontext(&ctx);
- mark_locations_array((VALUE*)&ctx.uc_mcontext,
- ((size_t)(sizeof(VALUE)-1 + sizeof ctx.uc_mcontext)/sizeof(VALUE)));
-#ifdef HAVE_UNWIND_H
- _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
- bot = (VALUE*)__libc_ia64_register_backing_store_base;
- top = (VALUE*)ctx.uc_mcontext.IA64_BSPSTORE;
-#endif
- rb_gc_mark_locations(bot, top);
- }
-#endif
-#if defined(__human68k__) || defined(__mc68000__)
- rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2),
- (VALUE*)((char*)rb_gc_stack_start + 2));
-#endif
- rb_gc_mark_threads();
-
- /* mark protected global variables */
- for (list = global_List; list; list = list->next) {
- rb_gc_mark_maybe(*list->varptr);
- }
- rb_mark_end_proc();
- rb_gc_mark_global_tbl();
-
- rb_mark_tbl(rb_class_tbl);
- rb_gc_mark_trap_list();
-
- /* mark generic instance variables for special constants */
- rb_mark_generic_ivar_tbl();
-
- rb_gc_mark_parser();
-
- /* gc_mark objects whose marking are not completed*/
- while (!MARK_STACK_EMPTY){
- if (mark_stack_overflow){
- gc_mark_all();
- }
- else {
- gc_mark_rest();
- }
- }
- gc_sweep();
-}
-
-void
-rb_gc()
-{
- garbage_collect();
- rb_gc_finalize_deferred();
-}
-
-/*
- * call-seq:
- * GC.start => nil
- * gc.garbage_collect => nil
- * ObjectSpace.garbage_collect => nil
- *
- * Initiates garbage collection, unless manually disabled.
- *
- */
-
-VALUE
-rb_gc_start()
-{
- rb_gc();
- return Qnil;
-}
-
-void
-ruby_set_stack_size(size)
- size_t size;
-{
-#ifndef STACK_LEVEL_MAX
- STACK_LEVEL_MAX = size/sizeof(VALUE);
-#endif
-}
-
-void
-Init_stack(addr)
- VALUE *addr;
-{
-#if defined(_WIN32) || defined(__CYGWIN__)
- MEMORY_BASIC_INFORMATION m;
- memset(&m, 0, sizeof(m));
- VirtualQuery(&m, &m, sizeof(m));
- rb_gc_stack_start =
- STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress,
- (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1);
-#elif defined(STACK_END_ADDRESS)
- extern void *STACK_END_ADDRESS;
- rb_gc_stack_start = STACK_END_ADDRESS;
-#else
- if (!addr) addr = (VALUE *)&addr;
- STACK_UPPER(&addr, addr, ++addr);
- if (rb_gc_stack_start) {
- if (STACK_UPPER(&addr,
- rb_gc_stack_start > addr,
- rb_gc_stack_start < addr))
- rb_gc_stack_start = addr;
- return;
- }
- rb_gc_stack_start = addr;
-#endif
-#ifdef HAVE_GETRLIMIT
- {
- struct rlimit rlim;
-
- if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
- unsigned int space = rlim.rlim_cur/5;
-
- if (space > 1024*1024) space = 1024*1024;
- STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
- }
- }
-#if defined(__ia64__) && (!defined(__GNUC__) || __GNUC__ < 2 || defined(__OPTIMIZE__))
- /* ruby crashes on IA64 if compiled with optimizer on */
- /* when if STACK_LEVEL_MAX is greater than this magic number */
- /* I know this is a kludge. I suspect optimizer bug */
-#define IA64_MAGIC_STACK_LIMIT 49152
- if (STACK_LEVEL_MAX > IA64_MAGIC_STACK_LIMIT)
- STACK_LEVEL_MAX = IA64_MAGIC_STACK_LIMIT;
-#endif
-#endif
-}
-
-
-/*
- * Document-class: ObjectSpace
- *
- * The <code>ObjectSpace</code> module contains a number of routines
- * that interact with the garbage collection facility and allow you to
- * traverse all living objects with an iterator.
- *
- * <code>ObjectSpace</code> also provides support for object
- * finalizers, procs that will be called when a specific object is
- * about to be destroyed by garbage collection.
- *
- * include ObjectSpace
- *
- *
- * a = "A"
- * b = "B"
- * c = "C"
- *
- *
- * define_finalizer(a, proc {|id| puts "Finalizer one on #{id}" })
- * define_finalizer(a, proc {|id| puts "Finalizer two on #{id}" })
- * define_finalizer(b, proc {|id| puts "Finalizer three on #{id}" })
- *
- * <em>produces:</em>
- *
- * Finalizer three on 537763470
- * Finalizer one on 537763480
- * Finalizer two on 537763480
- *
- */
-
-void
-Init_heap()
-{
- if (!rb_gc_stack_start) {
- Init_stack(0);
- }
- add_heap();
-}
-
-static VALUE
-os_live_obj()
-{
- int i;
- int n = 0;
-
- for (i = 0; i < heaps_used; i++) {
- RVALUE *p, *pend;
-
- p = heaps[i].slot; pend = p + heaps[i].limit;
- for (;p < pend; p++) {
- if (p->as.basic.flags) {
- switch (TYPE(p)) {
- case T_ICLASS:
- case T_VARMAP:
- case T_SCOPE:
- case T_NODE:
- continue;
- case T_CLASS:
- if (FL_TEST(p, FL_SINGLETON)) continue;
- default:
- if (!p->as.basic.klass) continue;
- rb_yield((VALUE)p);
- n++;
- }
- }
- }
- }
-
- return INT2FIX(n);
-}
-
-static VALUE
-os_obj_of(of)
- VALUE of;
-{
- int i;
- int n = 0;
-
- for (i = 0; i < heaps_used; i++) {
- RVALUE *p, *pend;
-
- p = heaps[i].slot; pend = p + heaps[i].limit;
- for (;p < pend; p++) {
- if (p->as.basic.flags) {
- switch (TYPE(p)) {
- case T_ICLASS:
- case T_VARMAP:
- case T_SCOPE:
- case T_NODE:
- continue;
- case T_CLASS:
- if (FL_TEST(p, FL_SINGLETON)) continue;
- default:
- if (!p->as.basic.klass) continue;
- if (rb_obj_is_kind_of((VALUE)p, of)) {
- rb_yield((VALUE)p);
- n++;
- }
- }
- }
- }
- }
-
- return INT2FIX(n);
-}
-
-/*
- * call-seq:
- * ObjectSpace.each_object([module]) {|obj| ... } => fixnum
- *
- * Calls the block once for each living, nonimmediate object in this
- * Ruby process. If <i>module</i> is specified, calls the block
- * for only those classes or modules that match (or are a subclass of)
- * <i>module</i>. Returns the number of objects found. Immediate
- * objects (<code>Fixnum</code>s, <code>Symbol</code>s
- * <code>true</code>, <code>false</code>, and <code>nil</code>) are
- * never returned. In the example below, <code>each_object</code>
- * returns both the numbers we defined and several constants defined in
- * the <code>Math</code> module.
- *
- * a = 102.7
- * b = 95 # Won't be returned
- * c = 12345678987654321
- * count = ObjectSpace.each_object(Numeric) {|x| p x }
- * puts "Total count: #{count}"
- *
- * <em>produces:</em>
- *
- * 12345678987654321
- * 102.7
- * 2.71828182845905
- * 3.14159265358979
- * 2.22044604925031e-16
- * 1.7976931348623157e+308
- * 2.2250738585072e-308
- * Total count: 7
- *
- */
-
-static VALUE
-os_each_obj(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE of;
-
- rb_secure(4);
- if (rb_scan_args(argc, argv, "01", &of) == 0) {
- return os_live_obj();
- }
- else {
- return os_obj_of(of);
- }
-}
-
-static VALUE finalizers;
-
-/* deprecated
- */
-
-static VALUE
-add_final(os, block)
- VALUE os, block;
-{
- rb_warn("ObjectSpace::add_finalizer is deprecated; use define_finalizer");
- if (!rb_respond_to(block, rb_intern("call"))) {
- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
- rb_obj_classname(block));
- }
- rb_ary_push(finalizers, block);
- return block;
-}
-
-/*
- * deprecated
- */
-static VALUE
-rm_final(os, block)
- VALUE os, block;
-{
- rb_warn("ObjectSpace::remove_finalizer is deprecated; use undefine_finalizer");
- rb_ary_delete(finalizers, block);
- return block;
-}
-
-/*
- * deprecated
- */
-static VALUE
-finals()
-{
- rb_warn("ObjectSpace::finalizers is deprecated");
- return finalizers;
-}
-
-/*
- * deprecated
- */
-
-static VALUE
-call_final(os, obj)
- VALUE os, obj;
-{
- rb_warn("ObjectSpace::call_finalizer is deprecated; use define_finalizer");
- need_call_final = 1;
- FL_SET(obj, FL_FINALIZE);
- return obj;
-}
-
-/*
- * call-seq:
- * ObjectSpace.undefine_finalizer(obj)
- *
- * Removes all finalizers for <i>obj</i>.
- *
- */
-
-static VALUE
-undefine_final(os, obj)
- VALUE os, obj;
-{
- if (finalizer_table) {
- st_delete(finalizer_table, (st_data_t*)&obj, 0);
- }
- return obj;
-}
-
-/*
- * call-seq:
- * ObjectSpace.define_finalizer(obj, aProc=proc())
- *
- * Adds <i>aProc</i> as a finalizer, to be called when <i>obj</i>
- * is about to be destroyed.
- *
- */
-
-static VALUE
-define_final(argc, argv, os)
- int argc;
- VALUE *argv;
- VALUE os;
-{
- VALUE obj, block, table;
-
- rb_scan_args(argc, argv, "11", &obj, &block);
- if (argc == 1) {
- block = rb_block_proc();
- }
- else if (!rb_respond_to(block, rb_intern("call"))) {
- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
- rb_obj_classname(block));
- }
- need_call_final = 1;
- FL_SET(obj, FL_FINALIZE);
-
- block = rb_ary_new3(2, INT2FIX(ruby_safe_level), block);
-
- if (!finalizer_table) {
- finalizer_table = st_init_numtable();
- }
- if (st_lookup(finalizer_table, obj, &table)) {
- rb_ary_push(table, block);
- }
- else {
- st_add_direct(finalizer_table, obj, rb_ary_new3(1, block));
- }
- return block;
-}
-
-void
-rb_gc_copy_finalizer(dest, obj)
- VALUE dest, obj;
-{
- VALUE table;
-
- if (!finalizer_table) return;
- if (!FL_TEST(obj, FL_FINALIZE)) return;
- if (st_lookup(finalizer_table, obj, &table)) {
- st_insert(finalizer_table, dest, table);
- }
- FL_SET(dest, FL_FINALIZE);
-}
-
-static VALUE
-run_single_final(args)
- VALUE *args;
-{
- rb_eval_cmd(args[0], args[1], (int)args[2]);
- return Qnil;
-}
-
-static void
-run_final(obj)
- VALUE obj;
-{
- long i;
- int status, critical_save = rb_thread_critical;
- VALUE args[3], table;
-
- rb_thread_critical = Qtrue;
- args[1] = rb_ary_new3(1, rb_obj_id(obj)); /* make obj into id */
- args[2] = (VALUE)ruby_safe_level;
- for (i=0; i<RARRAY(finalizers)->len; i++) {
- args[0] = RARRAY(finalizers)->ptr[i];
- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status);
- }
- if (finalizer_table && st_delete(finalizer_table, (st_data_t*)&obj, &table)) {
- for (i=0; i<RARRAY(table)->len; i++) {
- VALUE final = RARRAY(table)->ptr[i];
- args[0] = RARRAY(final)->ptr[1];
- args[2] = FIX2INT(RARRAY(final)->ptr[0]);
- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status);
- }
- }
- rb_thread_critical = critical_save;
-}
-
-void
-rb_gc_finalize_deferred()
-{
- RVALUE *p = deferred_final_list;
-
- deferred_final_list = 0;
- if (p) {
- finalize_list(p);
- free_unused_heaps();
- }
-}
-
-void
-rb_gc_call_finalizer_at_exit()
-{
- RVALUE *p, *pend;
- int i;
-
- /* run finalizers */
- if (need_call_final) {
- finalize_list(deferred_final_list);
- for (i = 0; i < heaps_used; i++) {
- p = heaps[i].slot; pend = p + heaps[i].limit;
- while (p < pend) {
- if (FL_TEST(p, FL_FINALIZE)) {
- FL_UNSET(p, FL_FINALIZE);
- p->as.basic.klass = 0;
- run_final((VALUE)p);
- }
- p++;
- }
- }
- }
- /* run data object's finalizers */
- for (i = 0; i < heaps_used; i++) {
- p = heaps[i].slot; pend = p + heaps[i].limit;
- while (p < pend) {
- if (BUILTIN_TYPE(p) == T_DATA &&
- DATA_PTR(p) && RANY(p)->as.data.dfree &&
- RANY(p)->as.basic.klass != rb_cThread) {
- p->as.free.flags = 0;
- if ((long)RANY(p)->as.data.dfree == -1) {
- RUBY_CRITICAL(free(DATA_PTR(p)));
- }
- else if (RANY(p)->as.data.dfree) {
- (*RANY(p)->as.data.dfree)(DATA_PTR(p));
- }
- }
- else if (BUILTIN_TYPE(p) == T_FILE) {
- if (rb_io_fptr_finalize(RANY(p)->as.file.fptr)) {
- p->as.free.flags = 0;
- }
- }
- p++;
- }
- }
-}
-
-/*
- * call-seq:
- * ObjectSpace._id2ref(object_id) -> an_object
- *
- * Converts an object id to a reference to the object. May not be
- * called on an object id passed as a parameter to a finalizer.
- *
- * s = "I am a string" #=> "I am a string"
- * r = ObjectSpace._id2ref(s.object_id) #=> "I am a string"
- * r == s #=> true
- *
- */
-
-static VALUE
-id2ref(obj, id)
- VALUE obj, id;
-{
- unsigned long ptr, p0;
-
- rb_secure(4);
- p0 = ptr = NUM2ULONG(id);
- if (ptr == Qtrue) return Qtrue;
- if (ptr == Qfalse) return Qfalse;
- if (ptr == Qnil) return Qnil;
- if (FIXNUM_P(ptr)) return (VALUE)ptr;
- if (SYMBOL_P(ptr) && rb_id2name(SYM2ID((VALUE)ptr)) != 0) {
- return (VALUE)ptr;
- }
-
- ptr = id ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */
- if (!is_pointer_to_heap((void *)ptr)|| BUILTIN_TYPE(ptr) >= T_BLOCK) {
- rb_raise(rb_eRangeError, "0x%lx is not id value", p0);
- }
- if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) {
- rb_raise(rb_eRangeError, "0x%lx is recycled object", p0);
- }
- return (VALUE)ptr;
-}
-
-/*
- * The <code>GC</code> module provides an interface to Ruby's mark and
- * sweep garbage collection mechanism. Some of the underlying methods
- * are also available via the <code>ObjectSpace</code> module.
- */
-
-void
-Init_GC()
-{
- VALUE rb_mObSpace;
-
- rb_mGC = rb_define_module("GC");
- rb_define_singleton_method(rb_mGC, "start", rb_gc_start, 0);
- rb_define_singleton_method(rb_mGC, "enable", rb_gc_enable, 0);
- rb_define_singleton_method(rb_mGC, "disable", rb_gc_disable, 0);
- rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0);
-
- rb_mObSpace = rb_define_module("ObjectSpace");
- rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1);
- rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0);
- rb_define_module_function(rb_mObSpace, "add_finalizer", add_final, 1);
- rb_define_module_function(rb_mObSpace, "remove_finalizer", rm_final, 1);
- rb_define_module_function(rb_mObSpace, "finalizers", finals, 0);
- rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1);
-
- rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1);
- rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1);
-
- rb_define_module_function(rb_mObSpace, "_id2ref", id2ref, 1);
-
- rb_gc_register_address(&rb_mObSpace);
- rb_global_variable(&finalizers);
- rb_gc_unregister_address(&rb_mObSpace);
- finalizers = rb_ary_new();
-
- source_filenames = st_init_strtable();
-
- nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory");
- rb_global_variable(&nomem_error);
-}
-/**********************************************************************
-
- hash.c -
-
- $Author: ocean $
- $Date: 2005/05/08 12:23:51 $
- created at: Mon Nov 22 18:51:18 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 "st.h"
-#include "util.h"
-#include "rubysig.h"
-
-#ifdef __APPLE__
-#include <crt_externs.h>
-#endif
-
-#define HASH_DELETED FL_USER1
-#define HASH_PROC_DEFAULT FL_USER2
-
-VALUE
-rb_hash_freeze(hash)
- VALUE hash;
-{
- return rb_obj_freeze(hash);
-}
-
-VALUE rb_cHash;
-
-static VALUE envtbl;
-static ID id_hash, id_call, id_default;
-
-static VALUE
-eql(args)
- VALUE *args;
-{
- return (VALUE)rb_eql(args[0], args[1]);
-}
-
-static int
-rb_any_cmp(a, b)
- VALUE a, b;
-{
- VALUE args[2];
-
- if (a == b) return 0;
- if (FIXNUM_P(a) && FIXNUM_P(b)) {
- return a != b;
- }
- if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString &&
- TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) {
- return rb_str_cmp(a, b);
- }
- if (a == Qundef || b == Qundef) return -1;
- if (SYMBOL_P(a) && SYMBOL_P(b)) {
- return a != b;
- }
-
- args[0] = a;
- args[1] = b;
- return !rb_with_disable_interrupt(eql, (VALUE)args);
-}
-
-VALUE
-rb_hash(obj)
- VALUE obj;
-{
- return rb_funcall(obj, id_hash, 0);
-}
-
-static int
-rb_any_hash(a)
- VALUE a;
-{
- VALUE hval;
-
- switch (TYPE(a)) {
- case T_FIXNUM:
- case T_SYMBOL:
- return (int)a;
- break;
-
- case T_STRING:
- return rb_str_hash(a);
- break;
-
- default:
- hval = rb_funcall(a, id_hash, 0);
- if (!FIXNUM_P(hval)) {
- hval = rb_funcall(hval, '%', 1, INT2FIX(536870923));
- }
- return (int)FIX2LONG(hval);
- }
-}
-
-static struct st_hash_type objhash = {
- rb_any_cmp,
- rb_any_hash,
-};
-
-struct foreach_safe_arg {
- st_table *tbl;
- int (*func)();
- st_data_t arg;
-};
-
-static int
-foreach_safe_i(key, value, arg)
- st_data_t key, value;
- struct foreach_safe_arg *arg;
-{
- int status;
-
- if (key == Qundef) return ST_CONTINUE;
- status = (*arg->func)(key, value, arg->arg);
- if (status == ST_CONTINUE) {
- return ST_CHECK;
- }
- return status;
-}
-
-void
-st_foreach_safe(table, func, a)
- st_table *table;
- int (*func)();
- st_data_t a;
-{
- struct foreach_safe_arg arg;
-
- arg.tbl = table;
- arg.func = func;
- arg.arg = a;
- if (st_foreach(table, foreach_safe_i, (st_data_t)&arg)) {
- rb_raise(rb_eRuntimeError, "hash modified during iteration");
- }
-}
-
-struct hash_foreach_arg {
- VALUE hash;
- int (*func)();
- VALUE arg;
-};
-
-static int
-hash_foreach_iter(key, value, arg)
- VALUE key, value;
- struct hash_foreach_arg *arg;
-{
- int status;
- st_table *tbl;
-
- tbl = RHASH(arg->hash)->tbl;
- if (key == Qundef) return ST_CONTINUE;
- status = (*arg->func)(key, value, arg->arg);
- if (RHASH(arg->hash)->tbl != tbl) {
- rb_raise(rb_eRuntimeError, "rehash occurred during iteration");
- }
- switch (status) {
- case ST_DELETE:
- st_delete_safe(tbl, (st_data_t*)&key, 0, Qundef);
- FL_SET(arg->hash, HASH_DELETED);
- case ST_CONTINUE:
- break;
- case ST_STOP:
- return ST_STOP;
- }
- return ST_CHECK;
-}
-
-static VALUE
-hash_foreach_ensure(hash)
- VALUE hash;
-{
- RHASH(hash)->iter_lev--;
-
- if (RHASH(hash)->iter_lev == 0) {
- if (FL_TEST(hash, HASH_DELETED)) {
- st_cleanup_safe(RHASH(hash)->tbl, Qundef);
- FL_UNSET(hash, HASH_DELETED);
- }
- }
- return 0;
-}
-
-static VALUE
-hash_foreach_call(arg)
- struct hash_foreach_arg *arg;
-{
- if (st_foreach(RHASH(arg->hash)->tbl, hash_foreach_iter, (st_data_t)arg)) {
- rb_raise(rb_eRuntimeError, "hash modified during iteration");
- }
- return Qnil;
-}
-
-void
-rb_hash_foreach(hash, func, farg)
- VALUE hash;
- int (*func)();
- VALUE farg;
-{
- struct hash_foreach_arg arg;
-
- RHASH(hash)->iter_lev++;
- arg.hash = hash;
- arg.func = func;
- arg.arg = farg;
- rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
-}
-
-static VALUE hash_alloc _((VALUE));
-
-static VALUE
-hash_alloc(klass)
- VALUE klass;
-{
- NEWOBJ(hash, struct RHash);
- OBJSETUP(hash, klass, T_HASH);
-
- hash->ifnone = Qnil;
- hash->tbl = st_init_table(&objhash);
-
- return (VALUE)hash;
-}
-
-VALUE
-rb_hash_new()
-{
- return hash_alloc(rb_cHash);
-}
-
-static void
-rb_hash_modify(hash)
- VALUE hash;
-{
- if (!RHASH(hash)->tbl) rb_raise(rb_eTypeError, "uninitialized Hash");
- if (OBJ_FROZEN(hash)) rb_error_frozen("hash");
- if (!OBJ_TAINTED(hash) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
-}
-
-/*
- * call-seq:
- * Hash.new => hash
- * Hash.new(obj) => aHash
- * Hash.new {|hash, key| block } => aHash
- *
- * Returns a new, empty hash. If this hash is subsequently accessed by
- * a key that doesn't correspond to a hash entry, the value returned
- * depends on the style of <code>new</code> used to create the hash. In
- * the first form, the access returns <code>nil</code>. If
- * <i>obj</i> is specified, this single object will be used for
- * all <em>default values</em>. If a block is specified, it will be
- * called with the hash object and the key, and should return the
- * default value. It is the block's responsibility to store the value
- * in the hash if required.
- *
- * h = Hash.new("Go Fish")
- * h["a"] = 100
- * h["b"] = 200
- * h["a"] #=> 100
- * h["c"] #=> "Go Fish"
- * # The following alters the single default object
- * h["c"].upcase! #=> "GO FISH"
- * h["d"] #=> "GO FISH"
- * h.keys #=> ["a", "b"]
- *
- * # While this creates a new default object each time
- * h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
- * h["c"] #=> "Go Fish: c"
- * h["c"].upcase! #=> "GO FISH: C"
- * h["d"] #=> "Go Fish: d"
- * h.keys #=> ["c", "d"]
- *
- */
-
-static VALUE
-rb_hash_initialize(argc, argv, hash)
- int argc;
- VALUE *argv;
- VALUE hash;
-{
- VALUE ifnone;
-
- rb_hash_modify(hash);
- if (rb_block_given_p()) {
- if (argc > 0) {
- rb_raise(rb_eArgError, "wrong number of arguments");
- }
- RHASH(hash)->ifnone = rb_block_proc();
- FL_SET(hash, HASH_PROC_DEFAULT);
- }
- else {
- rb_scan_args(argc, argv, "01", &ifnone);
- RHASH(hash)->ifnone = ifnone;
- }
-
- return hash;
-}
-
-/*
- * call-seq:
- * Hash[ [key =>|, value]* ] => hash
- *
- * Creates a new hash populated with the given objects. Equivalent to
- * the literal <code>{ <i>key</i>, <i>value</i>, ... }</code>. Keys and
- * values occur in pairs, so there must be an even number of arguments.
- *
- * Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}
- * Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}
- * { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200}
- */
-
-static VALUE
-rb_hash_s_create(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE hash;
- int i;
-
- if (argc == 1 && TYPE(argv[0]) == T_HASH) {
- hash = hash_alloc(klass);
-
- RHASH(hash)->ifnone = Qnil;
- RHASH(hash)->tbl = st_copy(RHASH(argv[0])->tbl);
-
- return hash;
- }
-
- if (argc % 2 != 0) {
- rb_raise(rb_eArgError, "odd number of arguments for Hash");
- }
-
- hash = hash_alloc(klass);
- for (i=0; i<argc; i+=2) {
- rb_hash_aset(hash, argv[i], argv[i + 1]);
- }
-
- return hash;
-}
-
-static VALUE
-to_hash(hash)
- VALUE hash;
-{
- return rb_convert_type(hash, T_HASH, "Hash", "to_hash");
-}
-
-static int
-rb_hash_rehash_i(key, value, tbl)
- VALUE key, value;
- st_table *tbl;
-{
- if (key != Qundef) st_insert(tbl, key, value);
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.rehash -> hsh
- *
- * Rebuilds the hash based on the current hash values for each key. If
- * values of key objects have changed since they were inserted, this
- * method will reindex <i>hsh</i>. If <code>Hash#rehash</code> is
- * called while an iterator is traversing the hash, an
- * <code>RuntimeError</code> will be raised in the iterator.
- *
- * a = [ "a", "b" ]
- * c = [ "c", "d" ]
- * h = { a => 100, c => 300 }
- * h[a] #=> 100
- * a[0] = "z"
- * h[a] #=> nil
- * h.rehash #=> {["z", "b"]=>100, ["c", "d"]=>300}
- * h[a] #=> 100
- */
-
-static VALUE
-rb_hash_rehash(hash)
- VALUE hash;
-{
- st_table *tbl;
-
- if (RHASH(hash)->iter_lev > 0) {
- rb_raise(rb_eRuntimeError, "rehash during iteration");
- }
- rb_hash_modify(hash);
- tbl = st_init_table_with_size(&objhash, RHASH(hash)->tbl->num_entries);
- rb_hash_foreach(hash, rb_hash_rehash_i, (st_data_t)tbl);
- st_free_table(RHASH(hash)->tbl);
- RHASH(hash)->tbl = tbl;
-
- return hash;
-}
-
-/*
- * call-seq:
- * hsh[key] => value
- *
- * Element Reference---Retrieves the <i>value</i> object corresponding
- * to the <i>key</i> object. If not found, returns the a default value (see
- * <code>Hash::new</code> for details).
- *
- * h = { "a" => 100, "b" => 200 }
- * h["a"] #=> 100
- * h["c"] #=> nil
- *
- */
-
-VALUE
-rb_hash_aref(hash, key)
- VALUE hash, key;
-{
- VALUE val;
-
- if (!st_lookup(RHASH(hash)->tbl, key, &val)) {
- return rb_funcall(hash, id_default, 1, key);
- }
- return val;
-}
-
-/*
- * call-seq:
- * hsh.fetch(key [, default] ) => obj
- * hsh.fetch(key) {| key | block } => obj
- *
- * Returns a value from the hash for the given key. If the key can't be
- * found, there are several options: With no other arguments, it will
- * raise an <code>KeyError</code> exception; if <i>default</i> is
- * given, then that will be returned; if the optional code block is
- * specified, then that will be run and its result returned.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.fetch("a") #=> 100
- * h.fetch("z", "go fish") #=> "go fish"
- * h.fetch("z") { |el| "go fish, #{el}"} #=> "go fish, z"
- *
- * The following example shows that an exception is raised if the key
- * is not found and a default value is not supplied.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.fetch("z")
- *
- * <em>produces:</em>
- *
- * prog.rb:2:in `fetch': key not found (KeyError)
- * from prog.rb:2
- *
- */
-
-static VALUE
-rb_hash_fetch(argc, argv, hash)
- int argc;
- VALUE *argv;
- VALUE hash;
-{
- VALUE key, if_none;
- VALUE val;
- long block_given;
-
- rb_scan_args(argc, argv, "11", &key, &if_none);
-
- block_given = rb_block_given_p();
- if (block_given && argc == 2) {
- rb_warn("block supersedes default value argument");
- }
- if (!st_lookup(RHASH(hash)->tbl, key, &val)) {
- if (block_given) return rb_yield(key);
- if (argc == 1) {
- rb_raise(rb_eKeyError, "key not found");
- }
- return if_none;
- }
- return val;
-}
-
-/*
- * call-seq:
- * hsh.default(key=nil) => obj
- *
- * Returns the default value, the value that would be returned by
- * <i>hsh</i>[<i>key</i>] if <i>key</i> did not exist in <i>hsh</i>.
- * See also <code>Hash::new</code> and <code>Hash#default=</code>.
- *
- * h = Hash.new #=> {}
- * h.default #=> nil
- * h.default(2) #=> nil
- *
- * h = Hash.new("cat") #=> {}
- * h.default #=> "cat"
- * h.default(2) #=> "cat"
- *
- * h = Hash.new {|h,k| h[k] = k.to_i*10} #=> {}
- * h.default #=> 0
- * h.default(2) #=> 20
- */
-
-static VALUE
-rb_hash_default(argc, argv, hash)
- int argc;
- VALUE *argv;
- VALUE hash;
-{
- VALUE key;
-
- rb_scan_args(argc, argv, "01", &key);
- if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
- return rb_funcall(RHASH(hash)->ifnone, id_call, 2, hash, key);
- }
- return RHASH(hash)->ifnone;
-}
-
-/*
- * call-seq:
- * hsh.default = obj => hsh
- *
- * Sets the default value, the value returned for a key that does not
- * exist in the hash. It is not possible to set the a default to a
- * <code>Proc</code> that will be executed on each key lookup.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.default = "Go fish"
- * h["a"] #=> 100
- * h["z"] #=> "Go fish"
- * # This doesn't do what you might hope...
- * h.default = proc do |hash, key|
- * hash[key] = key + key
- * end
- * h[2] #=> #<Proc:0x401b3948@-:6>
- * h["cat"] #=> #<Proc:0x401b3948@-:6>
- */
-
-static VALUE
-rb_hash_set_default(hash, ifnone)
- VALUE hash, ifnone;
-{
- rb_hash_modify(hash);
- RHASH(hash)->ifnone = ifnone;
- FL_UNSET(hash, HASH_PROC_DEFAULT);
- return ifnone;
-}
-
-/*
- * call-seq:
- * hsh.default_proc -> anObject
- *
- * If <code>Hash::new</code> was invoked with a block, return that
- * block, otherwise return <code>nil</code>.
- *
- * h = Hash.new {|h,k| h[k] = k*k } #=> {}
- * p = h.default_proc #=> #<Proc:0x401b3d08@-:1>
- * a = [] #=> []
- * p.call(a, 2)
- * a #=> [nil, nil, 4]
- */
-
-
-static VALUE
-rb_hash_default_proc(hash)
- VALUE hash;
-{
- if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
- return RHASH(hash)->ifnone;
- }
- return Qnil;
-}
-
-static int
-key_i(key, value, args)
- VALUE key, value;
- VALUE *args;
-{
- if (rb_equal(value, args[0])) {
- args[1] = key;
- return ST_STOP;
- }
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.key(value) => key
- *
- * Returns the key for a given value. If not found, returns <code>nil</code>.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.key(200) #=> "b"
- * h.key(999) #=> nil
- *
- */
-
-static VALUE
-rb_hash_key(hash, value)
- VALUE hash, value;
-{
- VALUE args[2];
-
- args[0] = value;
- args[1] = Qnil;
-
- rb_hash_foreach(hash, key_i, (st_data_t)args);
-
- return args[1];
-}
-
-/* :nodoc: */
-static VALUE
-rb_hash_index(hash, value)
- VALUE hash, value;
-{
- rb_warn("Hash#index is deprecated; use Hash#key");
- return rb_hash_key(hash, value);
-}
-
-/*
- * call-seq:
- * hsh.delete(key) => value
- * hsh.delete(key) {| key | block } => value
- *
- * Deletes and returns a key-value pair from <i>hsh</i> whose key is
- * equal to <i>key</i>. If the key is not found, returns the
- * <em>default value</em>. If the optional code block is given and the
- * key is not found, pass in the key and return the result of
- * <i>block</i>.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.delete("a") #=> 100
- * h.delete("z") #=> nil
- * h.delete("z") { |el| "#{el} not found" } #=> "z not found"
- *
- */
-
-VALUE
-rb_hash_delete(hash, key)
- VALUE hash, key;
-{
- VALUE val;
-
- rb_hash_modify(hash);
- if (RHASH(hash)->iter_lev > 0) {
- if (st_delete_safe(RHASH(hash)->tbl, (st_data_t*)&key, &val, Qundef)) {
- FL_SET(hash, HASH_DELETED);
- return val;
- }
- }
- else if (st_delete(RHASH(hash)->tbl, (st_data_t*)&key, &val))
- return val;
- if (rb_block_given_p()) {
- return rb_yield(key);
- }
- return Qnil;
-}
-
-struct shift_var {
- int stop;
- VALUE key;
- VALUE val;
-};
-
-static int
-shift_i(key, value, var)
- VALUE key, value;
- struct shift_var *var;
-{
- if (key == Qundef) return ST_CONTINUE;
- if (var->stop) return ST_STOP;
- var->stop = 1;
- var->key = key;
- var->val = value;
- return ST_DELETE;
-}
-
-/*
- * call-seq:
- * hsh.shift -> anArray or obj
- *
- * Removes a key-value pair from <i>hsh</i> and returns it as the
- * two-item array <code>[</code> <i>key, value</i> <code>]</code>, or
- * the hash's default value if the hash is empty.
- *
- * h = { 1 => "a", 2 => "b", 3 => "c" }
- * h.shift #=> [1, "a"]
- * h #=> {2=>"b", 3=>"c"}
- */
-
-static VALUE
-rb_hash_shift(hash)
- VALUE hash;
-{
- struct shift_var var;
-
- rb_hash_modify(hash);
- var.stop = 0;
- rb_hash_foreach(hash, shift_i, (st_data_t)&var);
-
- if (var.stop) {
- return rb_assoc_new(var.key, var.val);
- }
- else if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
- return rb_funcall(RHASH(hash)->ifnone, id_call, 2, hash, Qnil);
- }
- else {
- return RHASH(hash)->ifnone;
- }
-}
-
-static int
-delete_if_i(key, value, hash)
- VALUE key, value, hash;
-{
- if (key == Qundef) return ST_CONTINUE;
- if (RTEST(rb_yield_values(2, key, value))) {
- rb_hash_delete(hash, key);
- }
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.delete_if {| key, value | block } -> hsh
- *
- * Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
- * evaluates to <code>true</code>.
- *
- * h = { "a" => 100, "b" => 200, "c" => 300 }
- * h.delete_if {|key, value| key >= "b" } #=> {"a"=>100}
- *
- */
-
-VALUE
-rb_hash_delete_if(hash)
- VALUE hash;
-{
- rb_hash_modify(hash);
- rb_hash_foreach(hash, delete_if_i, hash);
- return hash;
-}
-
-/*
- * call-seq:
- * hsh.reject! {| key, value | block } -> hsh or nil
- *
- * Equivalent to <code>Hash#delete_if</code>, but returns
- * <code>nil</code> if no changes were made.
- */
-
-VALUE
-rb_hash_reject_bang(hash)
- VALUE hash;
-{
- int n = RHASH(hash)->tbl->num_entries;
- rb_hash_delete_if(hash);
- if (n == RHASH(hash)->tbl->num_entries) return Qnil;
- return hash;
-}
-
-/*
- * call-seq:
- * hsh.reject {| key, value | block } -> a_hash
- *
- * Same as <code>Hash#delete_if</code>, but works on (and returns) a
- * copy of the <i>hsh</i>. Equivalent to
- * <code><i>hsh</i>.dup.delete_if</code>.
- *
- */
-
-static VALUE
-rb_hash_reject(hash)
- VALUE hash;
-{
- return rb_hash_delete_if(rb_obj_dup(hash));
-}
-
-static int
-select_i(key, value, result)
- VALUE key, value, result;
-{
- if (key == Qundef) return ST_CONTINUE;
- if (RTEST(rb_yield_values(2, key, value)))
- rb_ary_push(result, rb_assoc_new(key, value));
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.values_at(key, ...) => array
- *
- * Return an array containing the values associated with the given keys.
- * Also see <code>Hash.select</code>.
- *
- * h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
- * h.values_at("cow", "cat") #=> ["bovine", "feline"]
-*/
-
-VALUE
-rb_hash_values_at(argc, argv, hash)
- int argc;
- VALUE *argv;
- VALUE hash;
-{
- VALUE result = rb_ary_new2(argc);
- long i;
-
- for (i=0; i<argc; i++) {
- rb_ary_push(result, rb_hash_aref(hash, argv[i]));
- }
- return result;
-}
-
-/*
- * call-seq:
- * hsh.select {|key, value| block} => array
- *
- * Returns a new array consisting of <code>[key,value]</code>
- * pairs for which the block returns true.
- * Also see <code>Hash.values_at</code>.
- *
- * h = { "a" => 100, "b" => 200, "c" => 300 }
- * h.select {|k,v| k > "a"} #=> [["b", 200], ["c", 300]]
- * h.select {|k,v| v < 200} #=> [["a", 100]]
- */
-
-VALUE
-rb_hash_select(hash)
- VALUE hash;
-{
- VALUE result;
-
- result = rb_ary_new();
- rb_hash_foreach(hash, select_i, result);
- return result;
-}
-
-static int
-clear_i(key, value, dummy)
- VALUE key, value, dummy;
-{
- return ST_DELETE;
-}
-
-/*
- * call-seq:
- * hsh.clear -> hsh
- *
- * Removes all key-value pairs from <i>hsh</i>.
- *
- * h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200}
- * h.clear #=> {}
- *
- */
-
-static VALUE
-rb_hash_clear(hash)
- VALUE hash;
-{
- rb_hash_modify(hash);
- if (RHASH(hash)->tbl->num_entries > 0) {
- rb_hash_foreach(hash, clear_i, 0);
- }
-
- return hash;
-}
-
-/*
- * call-seq:
- * hsh[key] = value => value
- * hsh.store(key, value) => value
- *
- * Element Assignment---Associates the value given by
- * <i>value</i> with the key given by <i>key</i>.
- * <i>key</i> should not have its value changed while it is in
- * use as a key (a <code>String</code> passed as a key will be
- * duplicated and frozen).
- *
- * h = { "a" => 100, "b" => 200 }
- * h["a"] = 9
- * h["c"] = 4
- * h #=> {"a"=>9, "b"=>200, "c"=>4}
- *
- */
-
-VALUE
-rb_hash_aset(hash, key, val)
- VALUE hash, key, val;
-{
- rb_hash_modify(hash);
- if (TYPE(key) != T_STRING || st_lookup(RHASH(hash)->tbl, key, 0)) {
- st_insert(RHASH(hash)->tbl, key, val);
- }
- else {
- st_add_direct(RHASH(hash)->tbl, rb_str_new4(key), val);
- }
- return val;
-}
-
-static int
-replace_i(key, val, hash)
- VALUE key, val, hash;
-{
- if (key != Qundef) {
- rb_hash_aset(hash, key, val);
- }
-
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.replace(other_hash) -> hsh
- *
- * Replaces the contents of <i>hsh</i> with the contents of
- * <i>other_hash</i>.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.replace({ "c" => 300, "d" => 400 }) #=> {"c"=>300, "d"=>400}
- *
- */
-
-static VALUE
-rb_hash_replace(hash, hash2)
- VALUE hash, hash2;
-{
- hash2 = to_hash(hash2);
- if (hash == hash2) return hash;
- rb_hash_clear(hash);
- rb_hash_foreach(hash2, replace_i, hash);
- RHASH(hash)->ifnone = RHASH(hash2)->ifnone;
- if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
- FL_SET(hash, HASH_PROC_DEFAULT);
- }
- else {
- FL_UNSET(hash, HASH_PROC_DEFAULT);
- }
-
- return hash;
-}
-
-/*
- * call-seq:
- * hsh.length => fixnum
- * hsh.size => fixnum
- *
- * Returns the number of key-value pairs in the hash.
- *
- * h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
- * h.length #=> 4
- * h.delete("a") #=> 200
- * h.length #=> 3
- */
-
-static VALUE
-rb_hash_size(hash)
- VALUE hash;
-{
- return INT2FIX(RHASH(hash)->tbl->num_entries);
-}
-
-
-/*
- * call-seq:
- * hsh.empty? => true or false
- *
- * Returns <code>true</code> if <i>hsh</i> contains no key-value pairs.
- *
- * {}.empty? #=> true
- *
- */
-
-static VALUE
-rb_hash_empty_p(hash)
- VALUE hash;
-{
- if (RHASH(hash)->tbl->num_entries == 0)
- return Qtrue;
- return Qfalse;
-}
-
-static int
-each_value_i(key, value)
- VALUE key, value;
-{
- if (key == Qundef) return ST_CONTINUE;
- rb_yield(value);
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.each_value {| value | block } -> hsh
- *
- * Calls <i>block</i> once for each key in <i>hsh</i>, passing the
- * value as a parameter.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.each_value {|value| puts value }
- *
- * <em>produces:</em>
- *
- * 100
- * 200
- */
-
-static VALUE
-rb_hash_each_value(hash)
- VALUE hash;
-{
- rb_hash_foreach(hash, each_value_i, 0);
- return hash;
-}
-
-static int
-each_key_i(key, value)
- VALUE key, value;
-{
- if (key == Qundef) return ST_CONTINUE;
- rb_yield(key);
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.each_key {| key | block } -> hsh
- *
- * Calls <i>block</i> once for each key in <i>hsh</i>, passing the key
- * as a parameter.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.each_key {|key| puts key }
- *
- * <em>produces:</em>
- *
- * a
- * b
- */
-static VALUE
-rb_hash_each_key(hash)
- VALUE hash;
-{
- rb_hash_foreach(hash, each_key_i, 0);
- return hash;
-}
-
-static int
-each_pair_i(key, value)
- VALUE key, value;
-{
- if (key == Qundef) return ST_CONTINUE;
- rb_yield_values(2, key, value);
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.each_pair {| key_value_array | block } -> hsh
- *
- * Calls <i>block</i> once for each key in <i>hsh</i>, passing the key
- * and value as parameters.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.each_pair {|key, value| puts "#{key} is #{value}" }
- *
- * <em>produces:</em>
- *
- * a is 100
- * b is 200
- *
- */
-
-static VALUE
-rb_hash_each_pair(hash)
- VALUE hash;
-{
- rb_hash_foreach(hash, each_pair_i, 0);
- return hash;
-}
-
-static int
-each_i(key, value)
- VALUE key, value;
-{
- if (key == Qundef) return ST_CONTINUE;
- rb_yield(rb_assoc_new(key, value));
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.each {| key, value | block } -> hsh
- *
- * Calls <i>block</i> once for each key in <i>hsh</i>, passing the key
- * and value to the block as a two-element array. Because of the assignment
- * semantics of block parameters, these elements will be split out if the
- * block has two formal parameters. Also see <code>Hash.each_pair</code>, which
- * will be marginally more efficient for blocks with two parameters.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.each {|key, value| puts "#{key} is #{value}" }
- *
- * <em>produces:</em>
- *
- * a is 100
- * b is 200
- *
- */
-
-static VALUE
-rb_hash_each(hash)
- VALUE hash;
-{
- rb_hash_foreach(hash, each_i, 0);
- return hash;
-}
-
-static int
-to_a_i(key, value, ary)
- VALUE key, value, ary;
-{
- if (key == Qundef) return ST_CONTINUE;
- rb_ary_push(ary, rb_assoc_new(key, value));
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.to_a -> array
- *
- * Converts <i>hsh</i> to a nested array of <code>[</code> <i>key,
- * value</i> <code>]</code> arrays.
- *
- * h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 }
- * h.to_a #=> [["a", 100], ["c", 300], ["d", 400]]
- */
-
-static VALUE
-rb_hash_to_a(hash)
- VALUE hash;
-{
- VALUE ary;
-
- ary = rb_ary_new();
- rb_hash_foreach(hash, to_a_i, ary);
- if (OBJ_TAINTED(hash)) OBJ_TAINT(ary);
-
- return ary;
-}
-
-/*
- * call-seq:
- * hsh.sort => array
- * hsh.sort {| a, b | block } => array
- *
- * Converts <i>hsh</i> to a nested array of <code>[</code> <i>key,
- * value</i> <code>]</code> arrays and sorts it, using
- * <code>Array#sort</code>.
- *
- * h = { "a" => 20, "b" => 30, "c" => 10 }
- * h.sort #=> [["a", 20], ["b", 30], ["c", 10]]
- * h.sort {|a,b| a[1]<=>b[1]} #=> [["c", 10], ["a", 20], ["b", 30]]
- *
- */
-
-static VALUE
-rb_hash_sort(hash)
- VALUE hash;
-{
- VALUE entries = rb_hash_to_a(hash);
- rb_ary_sort_bang(entries);
- return entries;
-}
-
-static int
-inspect_i(key, value, str)
- VALUE key, value, str;
-{
- VALUE str2;
-
- if (key == Qundef) return ST_CONTINUE;
- if (RSTRING(str)->len > 1) {
- rb_str_cat2(str, ", ");
- }
- str2 = rb_inspect(key);
- rb_str_buf_append(str, str2);
- OBJ_INFECT(str, str2);
- rb_str_buf_cat2(str, "=>");
- str2 = rb_inspect(value);
- rb_str_buf_append(str, str2);
- OBJ_INFECT(str, str2);
-
- return ST_CONTINUE;
-}
-
-static VALUE
-inspect_hash(hash, dummy, recur)
- VALUE hash, dummy;
- int recur;
-{
- VALUE str;
-
- if (recur) return rb_str_new2("{...}");
- str = rb_str_buf_new2("{");
- rb_hash_foreach(hash, inspect_i, str);
- rb_str_buf_cat2(str, "}");
- OBJ_INFECT(str, hash);
-
- return str;
-}
-
-/*
- * call-seq:
- * hsh.inspect => string
- *
- * Return the contents of this hash as a string.
- */
-
-static VALUE
-rb_hash_inspect(hash)
- VALUE hash;
-{
- if (RHASH(hash)->tbl == 0 || RHASH(hash)->tbl->num_entries == 0)
- return rb_str_new2("{}");
- return rb_exec_recursive(inspect_hash, hash, 0);
-}
-
-static VALUE
-to_s_hash(hash, dummy, recur)
- VALUE hash, dummy;
- int recur;
-{
- if (recur) return rb_str_new2("{...}");
- return rb_ary_to_s(rb_hash_to_a(hash));
-}
-
-/*
- * call-seq:
- * hsh.to_s => string
- *
- * Converts <i>hsh</i> to a string by converting the hash to an array
- * of <code>[</code> <i>key, value</i> <code>]</code> pairs and then
- * converting that array to a string using <code>Array#join</code> with
- * the default separator.
- *
- * h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 }
- * h.to_s #=> "a100c300d400"
- */
-
-static VALUE
-rb_hash_to_s(hash)
- VALUE hash;
-{
- return rb_exec_recursive(to_s_hash, hash, 0);
-}
-
-/*
- * call-seq:
- * hsh.to_hash => hsh
- *
- * Returns <i>self</i>.
- */
-
-static VALUE
-rb_hash_to_hash(hash)
- VALUE hash;
-{
- return hash;
-}
-
-static int
-keys_i(key, value, ary)
- VALUE key, value, ary;
-{
- if (key == Qundef) return ST_CONTINUE;
- rb_ary_push(ary, key);
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.keys => array
- *
- * Returns a new array populated with the keys from this hash. See also
- * <code>Hash#values</code>.
- *
- * h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
- * h.keys #=> ["a", "b", "c", "d"]
- *
- */
-
-static VALUE
-rb_hash_keys(hash)
- VALUE hash;
-{
- VALUE ary;
-
- ary = rb_ary_new();
- rb_hash_foreach(hash, keys_i, ary);
-
- return ary;
-}
-
-static int
-values_i(key, value, ary)
- VALUE key, value, ary;
-{
- if (key == Qundef) return ST_CONTINUE;
- rb_ary_push(ary, value);
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.values => array
- *
- * Returns a new array populated with the values from <i>hsh</i>. See
- * also <code>Hash#keys</code>.
- *
- * h = { "a" => 100, "b" => 200, "c" => 300 }
- * h.values #=> [100, 200, 300]
- *
- */
-
-static VALUE
-rb_hash_values(hash)
- VALUE hash;
-{
- VALUE ary;
-
- ary = rb_ary_new();
- rb_hash_foreach(hash, values_i, ary);
-
- return ary;
-}
-
-/*
- * call-seq:
- * hsh.has_key?(key) => true or false
- * hsh.include?(key) => true or false
- * hsh.key?(key) => true or false
- * hsh.member?(key) => true or false
- *
- * Returns <code>true</code> if the given key is present in <i>hsh</i>.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.has_key?("a") #=> true
- * h.has_key?("z") #=> false
- *
- */
-
-static VALUE
-rb_hash_has_key(hash, key)
- VALUE hash;
- VALUE key;
-{
- if (st_lookup(RHASH(hash)->tbl, key, 0)) {
- return Qtrue;
- }
- return Qfalse;
-}
-
-static int
-rb_hash_search_value(key, value, data)
- VALUE key, value, *data;
-{
- if (key == Qundef) return ST_CONTINUE;
- if (rb_equal(value, data[1])) {
- data[0] = Qtrue;
- return ST_STOP;
- }
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.has_value?(value) => true or false
- * hsh.value?(value) => true or false
- *
- * Returns <code>true</code> if the given value is present for some key
- * in <i>hsh</i>.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.has_value?(100) #=> true
- * h.has_value?(999) #=> false
- */
-
-static VALUE
-rb_hash_has_value(hash, val)
- VALUE hash;
- VALUE val;
-{
- VALUE data[2];
-
- data[0] = Qfalse;
- data[1] = val;
- rb_hash_foreach(hash, rb_hash_search_value, (st_data_t)data);
- return data[0];
-}
-
-struct equal_data {
- int result;
- st_table *tbl;
-};
-
-static int
-equal_i(key, val1, data)
- VALUE key, val1;
- struct equal_data *data;
-{
- VALUE val2;
-
- if (key == Qundef) return ST_CONTINUE;
- if (!st_lookup(data->tbl, key, &val2)) {
- data->result = Qfalse;
- return ST_STOP;
- }
- if (!rb_equal(val1, val2)) {
- data->result = Qfalse;
- return ST_STOP;
- }
- return ST_CONTINUE;
-}
-
-static VALUE
-hash_equal(hash1, hash2, eql)
- VALUE hash1, hash2;
- int eql; /* compare default value if true */
-{
- struct equal_data data;
-
- if (hash1 == hash2) return Qtrue;
- if (TYPE(hash2) != T_HASH) {
- if (!rb_respond_to(hash2, rb_intern("to_hash"))) {
- return Qfalse;
- }
- return rb_equal(hash2, hash1);
- }
- if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries)
- return Qfalse;
- if (eql) {
- if (!(rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone) &&
- FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT)))
- return Qfalse;
- }
-
- data.tbl = RHASH(hash2)->tbl;
- data.result = Qtrue;
- rb_hash_foreach(hash1, equal_i, (st_data_t)&data);
-
- return data.result;
-}
-
-/*
- * call-seq:
- * hsh == other_hash => true or false
- *
- * Equality---Two hashes are equal if they each contain the same number
- * of keys and if each key-value pair is equal to (according to
- * <code>Object#==</code>) the corresponding elements in the other
- * hash.
- *
- * h1 = { "a" => 1, "c" => 2 }
- * h2 = { 7 => 35, "c" => 2, "a" => 1 }
- * h3 = { "a" => 1, "c" => 2, 7 => 35 }
- * h4 = { "a" => 1, "d" => 2, "f" => 35 }
- * h1 == h2 #=> false
- * h2 == h3 #=> true
- * h3 == h4 #=> false
- *
- */
-
-static VALUE
-rb_hash_equal(hash1, hash2)
- VALUE hash1, hash2;
-{
- return hash_equal(hash1, hash2, Qfalse);
-}
-
-static int
-rb_hash_invert_i(key, value, hash)
- VALUE key, value;
- VALUE hash;
-{
- if (key == Qundef) return ST_CONTINUE;
- rb_hash_aset(hash, value, key);
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.invert -> aHash
- *
- * Returns a new hash created by using <i>hsh</i>'s values as keys, and
- * the keys as values.
- *
- * h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
- * h.invert #=> {0=>"a", 100=>"n", 200=>"d", 300=>"y"}
- *
- */
-
-static VALUE
-rb_hash_invert(hash)
- VALUE hash;
-{
- VALUE h = rb_hash_new();
-
- rb_hash_foreach(hash, rb_hash_invert_i, h);
- return h;
-}
-
-static int
-rb_hash_update_i(key, value, hash)
- VALUE key, value;
- VALUE hash;
-{
- if (key == Qundef) return ST_CONTINUE;
- rb_hash_aset(hash, key, value);
- return ST_CONTINUE;
-}
-
-static int
-rb_hash_update_block_i(key, value, hash)
- VALUE key, value;
- VALUE hash;
-{
- if (key == Qundef) return ST_CONTINUE;
- if (rb_hash_has_key(hash, key)) {
- value = rb_yield_values(3, key, rb_hash_aref(hash, key), value);
- }
- rb_hash_aset(hash, key, value);
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * hsh.merge!(other_hash) => hsh
- * hsh.update(other_hash) => hsh
- * hsh.merge!(other_hash){|key, oldval, newval| block} => hsh
- * hsh.update(other_hash){|key, oldval, newval| block} => hsh
- *
- * Adds the contents of <i>other_hash</i> to <i>hsh</i>. If no
- * block is specified entries with duplicate keys are overwritten
- * with the values from <i>other_hash</i>, otherwise the value
- * of each duplicate key is detemined by calling the block with
- * the key, its value in <i>hsh</i> and its value in <i>other_hash</i>.
- *
- * h1 = { "a" => 100, "b" => 200 }
- * h2 = { "b" => 254, "c" => 300 }
- * h1.merge!(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
- * h1.merge!(h2) { |key, v1, v2| v1 }
- * #=> {"a"=>100, "b"=>200, "c"=>300}
- */
-
-static VALUE
-rb_hash_update(hash1, hash2)
- VALUE hash1, hash2;
-{
- hash2 = to_hash(hash2);
- if (rb_block_given_p()) {
- rb_hash_foreach(hash2, rb_hash_update_block_i, hash1);
- }
- else {
- rb_hash_foreach(hash2, rb_hash_update_i, hash1);
- }
- return hash1;
-}
-
-/*
- * call-seq:
- * hsh.merge(other_hash) -> a_hash
- * hsh.merge(other_hash){|key, oldval, newval| block} -> a_hash
- *
- * Returns a new hash containing the contents of <i>other_hash</i> and
- * the contents of <i>hsh</i>, overwriting entries in <i>hsh</i> with
- * duplicate keys with those from <i>other_hash</i>.
- *
- * h1 = { "a" => 100, "b" => 200 }
- * h2 = { "b" => 254, "c" => 300 }
- * h1.merge(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
- * h1 #=> {"a"=>100, "b"=>200}
- *
- */
-
-static VALUE
-rb_hash_merge(hash1, hash2)
- VALUE hash1, hash2;
-{
- return rb_hash_update(rb_obj_dup(hash1), hash2);
-}
-
-static int path_tainted = -1;
-
-static char **origenviron;
-#ifdef _WIN32
-#define GET_ENVIRON(e) (e = rb_w32_get_environ())
-#define FREE_ENVIRON(e) rb_w32_free_environ(e)
-static char **my_environ;
-#undef environ
-#define environ my_environ
-#elif defined(__APPLE__)
-#undef environ
-#define environ (*_NSGetEnviron())
-#define GET_ENVIRON(e) (e)
-#define FREE_ENVIRON(e)
-#else
-extern char **environ;
-#define GET_ENVIRON(e) (e)
-#define FREE_ENVIRON(e)
-#endif
-
-static VALUE
-env_str_new(ptr, len)
- const char *ptr;
- long len;
-{
- VALUE str = rb_tainted_str_new(ptr, len);
-
- rb_obj_freeze(str);
- return str;
-}
-
-static VALUE
-env_str_new2(ptr)
- const char *ptr;
-{
- if (!ptr) return Qnil;
- return env_str_new(ptr, strlen(ptr));
-}
-
-static VALUE
-env_delete(obj, name)
- VALUE obj, name;
-{
- char *nam, *val;
-
- rb_secure(4);
- SafeStringValue(name);
- nam = RSTRING(name)->ptr;
- if (strlen(nam) != RSTRING(name)->len) {
- rb_raise(rb_eArgError, "bad environment variable name");
- }
- val = getenv(nam);
- if (val) {
- VALUE value = env_str_new2(val);
-
- ruby_setenv(nam, 0);
-#ifdef ENV_IGNORECASE
- if (strcasecmp(nam, PATH_ENV) == 0)
-#else
- if (strcmp(nam, PATH_ENV) == 0)
-#endif
- {
- path_tainted = 0;
- }
- return value;
- }
- return Qnil;
-}
-
-static VALUE
-env_delete_m(obj, name)
- VALUE obj, name;
-{
- VALUE val;
-
- val = env_delete(obj, name);
- if (NIL_P(val) && rb_block_given_p()) rb_yield(name);
- return val;
-}
-
-static VALUE
-rb_f_getenv(obj, name)
- VALUE obj, name;
-{
- char *nam, *env;
-
- rb_secure(4);
- SafeStringValue(name);
- nam = RSTRING(name)->ptr;
- if (strlen(nam) != RSTRING(name)->len) {
- rb_raise(rb_eArgError, "bad environment variable name");
- }
- env = getenv(nam);
- if (env) {
-#ifdef ENV_IGNORECASE
- if (strcasecmp(nam, PATH_ENV) == 0 && !rb_env_path_tainted())
-#else
- if (strcmp(nam, PATH_ENV) == 0 && !rb_env_path_tainted())
-#endif
- {
- VALUE str = rb_str_new2(env);
-
- rb_obj_freeze(str);
- return str;
- }
- return env_str_new2(env);
- }
- return Qnil;
-}
-
-static VALUE
-env_fetch(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE key, if_none;
- long block_given;
- char *nam, *env;
-
- rb_secure(4);
- rb_scan_args(argc, argv, "11", &key, &if_none);
- block_given = rb_block_given_p();
- if (block_given && argc == 2) {
- rb_warn("block supersedes default value argument");
- }
- SafeStringValue(key);
- nam = RSTRING(key)->ptr;
- if (strlen(nam) != RSTRING(key)->len) {
- rb_raise(rb_eArgError, "bad environment variable name");
- }
- env = getenv(nam);
- if (!env) {
- if (block_given) return rb_yield(key);
- if (argc == 1) {
- rb_raise(rb_eKeyError, "key not found");
- }
- return if_none;
- }
-#ifdef ENV_IGNORECASE
- if (strcasecmp(nam, PATH_ENV) == 0 && !rb_env_path_tainted())
-#else
- if (strcmp(nam, PATH_ENV) == 0 && !rb_env_path_tainted())
-#endif
- return rb_str_new2(env);
- return env_str_new2(env);
-}
-
-static void
-path_tainted_p(path)
- char *path;
-{
- path_tainted = rb_path_check(path)?0:1;
-}
-
-int
-rb_env_path_tainted()
-{
- if (path_tainted < 0) {
- path_tainted_p(getenv(PATH_ENV));
- }
- return path_tainted;
-}
-
-static int
-envix(nam)
- const char *nam;
-{
- register int i, len = strlen(nam);
- char **env;
-
- env = GET_ENVIRON(environ);
- for (i = 0; env[i]; i++) {
- if (
-#ifdef ENV_IGNORECASE
- strncasecmp(env[i],nam,len) == 0
-#else
- memcmp(env[i],nam,len) == 0
-#endif
- && env[i][len] == '=')
- break; /* memcmp must come first to avoid */
- } /* potential SEGV's */
- FREE_ENVIRON(environ);
- return i;
-}
-
-void
-ruby_setenv(name, value)
- const char *name;
- const char *value;
-{
-#if defined(_WIN32)
- /* The sane way to deal with the environment.
- * Has these advantages over putenv() & co.:
- * * enables us to store a truly empty value in the
- * environment (like in UNIX).
- * * we don't have to deal with RTL globals, bugs and leaks.
- * * Much faster.
- * Why you may want to enable USE_WIN32_RTL_ENV:
- * * environ[] and RTL functions will not reflect changes,
- * which might be an issue if extensions want to access
- * the env. via RTL. This cuts both ways, since RTL will
- * not see changes made by extensions that call the Win32
- * functions directly, either.
- * GSAR 97-06-07
- *
- * REMARK: USE_WIN32_RTL_ENV is already obsoleted since we don't use
- * RTL's environ global variable directly yet.
- */
- SetEnvironmentVariable(name,value);
-#elif defined __CYGWIN__
-#undef setenv
-#undef unsetenv
- if (value)
- setenv(name,value,1);
- else
- unsetenv(name);
-#else /* WIN32 */
-
- int i=envix(name); /* where does it go? */
-
- if (environ == origenviron) { /* need we copy environment? */
- int j;
- int max;
- char **tmpenv;
-
- for (max = i; environ[max]; max++) ;
- tmpenv = ALLOC_N(char*, max+2);
- for (j=0; j<max; j++) /* copy environment */
- tmpenv[j] = strdup(environ[j]);
- tmpenv[max] = 0;
- environ = tmpenv; /* tell exec where it is now */
- }
- if (!value) {
- if (environ != origenviron) {
- char **envp = origenviron;
- while (*envp && *envp != environ[i]) envp++;
- if (!*envp)
- free(environ[i]);
- }
- while (environ[i]) {
- environ[i] = environ[i+1];
- i++;
- }
- return;
- }
- if (!environ[i]) { /* does not exist yet */
- REALLOC_N(environ, char*, i+2); /* just expand it a bit */
- environ[i+1] = 0; /* make sure it's null terminated */
- }
- else {
- if (environ[i] != origenviron[i])
- free(environ[i]);
- }
- environ[i] = ALLOC_N(char, strlen(name) + strlen(value) + 2);
-#ifndef MSDOS
- sprintf(environ[i],"%s=%s",name,value); /* all that work just for this */
-#else
- /* MS-DOS requires environment variable names to be in uppercase */
- /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
- * some utilities and applications may break because they only look
- * for upper case strings. (Fixed strupr() bug here.)]
- */
- strcpy(environ[i],name); strupr(environ[i]);
- sprintf(environ[i] + strlen(name),"=%s", value);
-#endif /* MSDOS */
-
-#endif /* WIN32 */
-}
-
-void
-ruby_unsetenv(name)
- const char *name;
-{
- ruby_setenv(name, 0);
-}
-
-static VALUE
-env_aset(obj, nm, val)
- VALUE obj, nm, val;
-{
- char *name, *value;
-
- if (rb_safe_level() >= 4) {
- rb_raise(rb_eSecurityError, "can't change environment variable");
- }
-
- if (NIL_P(val)) {
- env_delete(obj, nm);
- return Qnil;
- }
-
- StringValue(nm);
- StringValue(val);
- name = RSTRING(nm)->ptr;
- value = RSTRING(val)->ptr;
- if (strlen(name) != RSTRING(nm)->len)
- rb_raise(rb_eArgError, "bad environment variable name");
- if (strlen(value) != RSTRING(val)->len)
- rb_raise(rb_eArgError, "bad environment variable value");
-
- ruby_setenv(name, value);
-#ifdef ENV_IGNORECASE
- if (strcasecmp(name, PATH_ENV) == 0) {
-#else
- if (strcmp(name, PATH_ENV) == 0) {
-#endif
- if (OBJ_TAINTED(val)) {
- /* already tainted, no check */
- path_tainted = 1;
- return val;
- }
- else {
- path_tainted_p(value);
- }
- }
- return val;
-}
-
-static VALUE
-env_keys()
-{
- char **env;
- VALUE ary;
-
- rb_secure(4);
- ary = rb_ary_new();
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- rb_ary_push(ary, env_str_new(*env, s-*env));
- }
- env++;
- }
- FREE_ENVIRON(environ);
- return ary;
-}
-
-static VALUE
-env_each_key(ehash)
- VALUE ehash;
-{
- VALUE keys;
- long i;
-
- rb_secure(4);
- keys = env_keys();
- for (i=0; i<RARRAY(keys)->len; i++) {
- rb_yield(RARRAY(keys)->ptr[i]);
- }
- return ehash;
-}
-
-static VALUE
-env_values()
-{
- VALUE ary;
- char **env;
-
- rb_secure(4);
- ary = rb_ary_new();
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- rb_ary_push(ary, env_str_new2(s+1));
- }
- env++;
- }
- FREE_ENVIRON(environ);
- return ary;
-}
-
-static VALUE
-env_each_value(ehash)
- VALUE ehash;
-{
- VALUE values = env_values();
- long i;
-
- rb_secure(4);
- values = env_values();
- for (i=0; i<RARRAY(values)->len; i++) {
- rb_yield(RARRAY(values)->ptr[i]);
- }
- return ehash;
-}
-
-static VALUE
-env_each_i(ehash, values)
- VALUE ehash;
- int values;
-{
- char **env;
- VALUE ary;
- long i;
-
- rb_secure(4);
- ary = rb_ary_new();
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- rb_ary_push(ary, env_str_new(*env, s-*env));
- rb_ary_push(ary, env_str_new2(s+1));
- }
- env++;
- }
- FREE_ENVIRON(environ);
-
- for (i=0; i<RARRAY(ary)->len; i+=2) {
- if (values) {
- rb_yield_values(2, RARRAY(ary)->ptr[i], RARRAY(ary)->ptr[i+1]);
- }
- else {
- rb_yield(rb_assoc_new(RARRAY(ary)->ptr[i], RARRAY(ary)->ptr[i+1]));
- }
- }
- return ehash;
-}
-
-static VALUE
-env_each(ehash)
- VALUE ehash;
-{
- return env_each_i(ehash, Qfalse);
-}
-
-static VALUE
-env_each_pair(ehash)
- VALUE ehash;
-{
- return env_each_i(ehash, Qtrue);
-}
-
-static VALUE
-env_reject_bang()
-{
- volatile VALUE keys;
- long i;
- int del = 0;
-
- rb_secure(4);
- keys = env_keys();
- for (i=0; i<RARRAY(keys)->len; i++) {
- VALUE val = rb_f_getenv(Qnil, RARRAY(keys)->ptr[i]);
- if (!NIL_P(val)) {
- if (RTEST(rb_yield_values(2, RARRAY(keys)->ptr[i], val))) {
- FL_UNSET(RARRAY(keys)->ptr[i], FL_TAINT);
- env_delete(Qnil, RARRAY(keys)->ptr[i]);
- del++;
- }
- }
- }
- if (del == 0) return Qnil;
- return envtbl;
-}
-
-static VALUE
-env_delete_if()
-{
- env_reject_bang();
- return envtbl;
-}
-
-static VALUE
-env_values_at(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE result;
- long i;
-
- rb_secure(4);
- result = rb_ary_new();
- for (i=0; i<argc; i++) {
- rb_ary_push(result, rb_f_getenv(Qnil, argv[i]));
- }
- return result;
-}
-
-static VALUE
-env_select()
-{
- VALUE result;
- char **env;
-
- rb_secure(4);
- result = rb_ary_new();
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- VALUE k = env_str_new(*env, s-*env);
- VALUE v = env_str_new2(s+1);
- if (RTEST(rb_yield_values(2, k, v))) {
- rb_ary_push(result, rb_assoc_new(k, v));
- }
- }
- env++;
- }
- FREE_ENVIRON(environ);
-
- return result;
-}
-
-static VALUE
-env_clear()
-{
- volatile VALUE keys;
- long i;
-
- rb_secure(4);
- keys = env_keys();
- for (i=0; i<RARRAY(keys)->len; i++) {
- VALUE val = rb_f_getenv(Qnil, RARRAY(keys)->ptr[i]);
- if (!NIL_P(val)) {
- env_delete(Qnil, RARRAY(keys)->ptr[i]);
- }
- }
- return envtbl;
-}
-
-static VALUE
-env_to_s()
-{
- return rb_str_new2("ENV");
-}
-
-static VALUE
-env_inspect()
-{
- char **env;
- VALUE str, i;
-
- rb_secure(4);
- str = rb_str_buf_new2("{");
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
-
- if (env != environ) {
- rb_str_buf_cat2(str, ", ");
- }
- if (s) {
- rb_str_buf_cat2(str, "\"");
- rb_str_buf_cat(str, *env, s-*env);
- rb_str_buf_cat2(str, "\"=>");
- i = rb_inspect(rb_str_new2(s+1));
- rb_str_buf_append(str, i);
- }
- env++;
- }
- FREE_ENVIRON(environ);
- rb_str_buf_cat2(str, "}");
- OBJ_TAINT(str);
-
- return str;
-}
-
-static VALUE
-env_to_a()
-{
- char **env;
- VALUE ary;
-
- rb_secure(4);
- ary = rb_ary_new();
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env),
- env_str_new2(s+1)));
- }
- env++;
- }
- FREE_ENVIRON(environ);
- return ary;
-}
-
-static VALUE
-env_none()
-{
- return Qnil;
-}
-
-static VALUE
-env_size()
-{
- int i;
- char **env;
-
- rb_secure(4);
- env = GET_ENVIRON(environ);
- for(i=0; env[i]; i++)
- ;
- FREE_ENVIRON(environ);
- return INT2FIX(i);
-}
-
-static VALUE
-env_empty_p()
-{
- char **env;
-
- rb_secure(4);
- env = GET_ENVIRON(environ);
- if (env[0] == 0) {
- FREE_ENVIRON(environ);
- return Qtrue;
- }
- FREE_ENVIRON(environ);
- return Qfalse;
-}
-
-static VALUE
-env_has_key(env, key)
- VALUE env, key;
-{
- char *s;
-
- rb_secure(4);
- s = StringValuePtr(key);
- if (strlen(s) != RSTRING(key)->len)
- rb_raise(rb_eArgError, "bad environment variable name");
- if (getenv(s)) return Qtrue;
- return Qfalse;
-}
-
-static VALUE
-env_has_value(dmy, value)
- VALUE dmy, value;
-{
- char **env;
-
- rb_secure(4);
- if (TYPE(value) != T_STRING) return Qfalse;
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s++) {
- long len = strlen(s);
- if (RSTRING(value)->len == len && strncmp(s, RSTRING(value)->ptr, len) == 0) {
- FREE_ENVIRON(environ);
- return Qtrue;
- }
- }
- env++;
- }
- FREE_ENVIRON(environ);
- return Qfalse;
-}
-
-static VALUE
-env_key(dmy, value)
- VALUE dmy, value;
-{
- char **env;
- VALUE str;
-
- rb_secure(4);
- StringValue(value);
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s++) {
- long len = strlen(s);
- if (RSTRING(value)->len == len && strncmp(s, RSTRING(value)->ptr, len) == 0) {
- str = env_str_new(*env, s-*env-1);
- FREE_ENVIRON(environ);
- return str;
- }
- }
- env++;
- }
- FREE_ENVIRON(environ);
- return Qnil;
-}
-
-static VALUE
-env_index(dmy, value)
- VALUE dmy, value;
-{
- rb_warn("ENV.index is deprecated; use ENV.key");
- return env_key(dmy, value);
-}
-
-static VALUE
-env_to_hash()
-{
- char **env;
- VALUE hash;
-
- rb_secure(4);
- hash = rb_hash_new();
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- rb_hash_aset(hash, env_str_new(*env, s-*env),
- env_str_new2(s+1));
- }
- env++;
- }
- FREE_ENVIRON(environ);
- return hash;
-}
-
-static VALUE
-env_reject()
-{
- return rb_hash_delete_if(env_to_hash());
-}
-
-static VALUE
-env_shift()
-{
- char **env;
-
- rb_secure(4);
- env = GET_ENVIRON(environ);
- if (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- VALUE key = env_str_new(*env, s-*env);
- VALUE val = env_str_new2(getenv(RSTRING(key)->ptr));
- env_delete(Qnil, key);
- return rb_assoc_new(key, val);
- }
- }
- FREE_ENVIRON(environ);
- return Qnil;
-}
-
-static VALUE
-env_invert()
-{
- return rb_hash_invert(env_to_hash());
-}
-
-static int
-env_replace_i(key, val, keys)
- VALUE key, val, keys;
-{
- if (key != Qundef) {
- env_aset(Qnil, key, val);
- if (rb_ary_includes(keys, key)) {
- rb_ary_delete(keys, key);
- }
- }
- return ST_CONTINUE;
-}
-
-static VALUE
-env_replace(env, hash)
- VALUE env, hash;
-{
- volatile VALUE keys;
- long i;
-
- rb_secure(4);
- keys = env_keys();
- if (env == hash) return env;
- hash = to_hash(hash);
- rb_hash_foreach(hash, env_replace_i, keys);
-
- for (i=0; i<RARRAY(keys)->len; i++) {
- env_delete(env, RARRAY(keys)->ptr[i]);
- }
- return env;
-}
-
-static int
-env_update_i(key, val)
- VALUE key, val;
-{
- if (key != Qundef) {
- if (rb_block_given_p()) {
- val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val);
- }
- env_aset(Qnil, key, val);
- }
- return ST_CONTINUE;
-}
-
-static VALUE
-env_update(env, hash)
- VALUE env, hash;
-{
- rb_secure(4);
- if (env == hash) return env;
- hash = to_hash(hash);
- rb_hash_foreach(hash, env_update_i, 0);
- return env;
-}
-
-/*
- * A <code>Hash</code> is a collection of key-value pairs. It is
- * similar to an <code>Array</code>, except that indexing is done via
- * arbitrary keys of any object type, not an integer index. The order
- * in which you traverse a hash by either key or value may seem
- * arbitrary, and will generally not be in the insertion order.
- *
- * Hashes have a <em>default value</em> that is returned when accessing
- * keys that do not exist in the hash. By default, that value is
- * <code>nil</code>.
- *
- */
-
-void
-Init_Hash()
-{
- id_hash = rb_intern("hash");
- id_call = rb_intern("call");
- id_default = rb_intern("default");
-
- rb_cHash = rb_define_class("Hash", rb_cObject);
-
- rb_include_module(rb_cHash, rb_mEnumerable);
-
- rb_define_alloc_func(rb_cHash, hash_alloc);
- rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
- rb_define_method(rb_cHash,"initialize", rb_hash_initialize, -1);
- rb_define_method(rb_cHash,"initialize_copy", rb_hash_replace, 1);
- rb_define_method(rb_cHash,"rehash", rb_hash_rehash, 0);
-
- rb_define_method(rb_cHash,"to_hash", rb_hash_to_hash, 0);
- rb_define_method(rb_cHash,"to_a", rb_hash_to_a, 0);
- rb_define_method(rb_cHash,"to_s", rb_hash_to_s, 0);
- rb_define_method(rb_cHash,"inspect", rb_hash_inspect, 0);
-
- rb_define_method(rb_cHash,"==", rb_hash_equal, 1);
- rb_define_method(rb_cHash,"[]", rb_hash_aref, 1);
- rb_define_method(rb_cHash,"fetch", rb_hash_fetch, -1);
- rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);
- rb_define_method(rb_cHash,"store", rb_hash_aset, 2);
- rb_define_method(rb_cHash,"default", rb_hash_default, -1);
- rb_define_method(rb_cHash,"default=", rb_hash_set_default, 1);
- rb_define_method(rb_cHash,"default_proc", rb_hash_default_proc, 0);
- rb_define_method(rb_cHash,"key", rb_hash_key, 1);
- rb_define_method(rb_cHash,"index", rb_hash_index, 1);
- rb_define_method(rb_cHash,"size", rb_hash_size, 0);
- rb_define_method(rb_cHash,"length", rb_hash_size, 0);
- rb_define_method(rb_cHash,"empty?", rb_hash_empty_p, 0);
-
- rb_define_method(rb_cHash,"each", rb_hash_each, 0);
- rb_define_method(rb_cHash,"each_value", rb_hash_each_value, 0);
- rb_define_method(rb_cHash,"each_key", rb_hash_each_key, 0);
- rb_define_method(rb_cHash,"each_pair", rb_hash_each_pair, 0);
- rb_define_method(rb_cHash,"sort", rb_hash_sort, 0);
-
- rb_define_method(rb_cHash,"keys", rb_hash_keys, 0);
- rb_define_method(rb_cHash,"values", rb_hash_values, 0);
- rb_define_method(rb_cHash,"values_at", rb_hash_values_at, -1);
-
- rb_define_method(rb_cHash,"shift", rb_hash_shift, 0);
- rb_define_method(rb_cHash,"delete", rb_hash_delete, 1);
- rb_define_method(rb_cHash,"delete_if", rb_hash_delete_if, 0);
- rb_define_method(rb_cHash,"select", rb_hash_select, 0);
- rb_define_method(rb_cHash,"reject", rb_hash_reject, 0);
- rb_define_method(rb_cHash,"reject!", rb_hash_reject_bang, 0);
- rb_define_method(rb_cHash,"clear", rb_hash_clear, 0);
- rb_define_method(rb_cHash,"invert", rb_hash_invert, 0);
- rb_define_method(rb_cHash,"update", rb_hash_update, 1);
- rb_define_method(rb_cHash,"replace", rb_hash_replace, 1);
- rb_define_method(rb_cHash,"merge!", rb_hash_update, 1);
- rb_define_method(rb_cHash,"merge", rb_hash_merge, 1);
-
- rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1);
- rb_define_method(rb_cHash,"member?", rb_hash_has_key, 1);
- rb_define_method(rb_cHash,"has_key?", rb_hash_has_key, 1);
- rb_define_method(rb_cHash,"has_value?", rb_hash_has_value, 1);
- rb_define_method(rb_cHash,"key?", rb_hash_has_key, 1);
- rb_define_method(rb_cHash,"value?", rb_hash_has_value, 1);
-
-#ifndef __MACOS__ /* environment variables nothing on MacOS. */
- origenviron = environ;
- envtbl = rb_obj_alloc(rb_cObject);
- rb_extend_object(envtbl, rb_mEnumerable);
-
- rb_define_singleton_method(envtbl,"[]", rb_f_getenv, 1);
- rb_define_singleton_method(envtbl,"fetch", env_fetch, -1);
- rb_define_singleton_method(envtbl,"[]=", env_aset, 2);
- rb_define_singleton_method(envtbl,"store", env_aset, 2);
- rb_define_singleton_method(envtbl,"each", env_each, 0);
- rb_define_singleton_method(envtbl,"each_pair", env_each_pair, 0);
- rb_define_singleton_method(envtbl,"each_key", env_each_key, 0);
- rb_define_singleton_method(envtbl,"each_value", env_each_value, 0);
- rb_define_singleton_method(envtbl,"delete", env_delete_m, 1);
- rb_define_singleton_method(envtbl,"delete_if", env_delete_if, 0);
- rb_define_singleton_method(envtbl,"clear", env_clear, 0);
- rb_define_singleton_method(envtbl,"reject", env_reject, 0);
- rb_define_singleton_method(envtbl,"reject!", env_reject_bang, 0);
- rb_define_singleton_method(envtbl,"select", env_select, 0);
- rb_define_singleton_method(envtbl,"shift", env_shift, 0);
- rb_define_singleton_method(envtbl,"invert", env_invert, 0);
- rb_define_singleton_method(envtbl,"replace", env_replace, 1);
- rb_define_singleton_method(envtbl,"update", env_update, 1);
- rb_define_singleton_method(envtbl,"inspect", env_inspect, 0);
- rb_define_singleton_method(envtbl,"rehash", env_none, 0);
- rb_define_singleton_method(envtbl,"to_a", env_to_a, 0);
- rb_define_singleton_method(envtbl,"to_s", env_to_s, 0);
- rb_define_singleton_method(envtbl,"key", env_key, 1);
- rb_define_singleton_method(envtbl,"index", env_index, 1);
- rb_define_singleton_method(envtbl,"size", env_size, 0);
- rb_define_singleton_method(envtbl,"length", env_size, 0);
- rb_define_singleton_method(envtbl,"empty?", env_empty_p, 0);
- rb_define_singleton_method(envtbl,"keys", env_keys, 0);
- rb_define_singleton_method(envtbl,"values", env_values, 0);
- rb_define_singleton_method(envtbl,"values_at", env_values_at, -1);
- rb_define_singleton_method(envtbl,"include?", env_has_key, 1);
- rb_define_singleton_method(envtbl,"member?", env_has_key, 1);
- rb_define_singleton_method(envtbl,"has_key?", env_has_key, 1);
- rb_define_singleton_method(envtbl,"has_value?", env_has_value, 1);
- rb_define_singleton_method(envtbl,"key?", env_has_key, 1);
- rb_define_singleton_method(envtbl,"value?", env_has_value, 1);
- rb_define_singleton_method(envtbl,"to_hash", env_to_hash, 0);
-
- rb_define_global_const("ENV", envtbl);
-#else /* __MACOS__ */
- envtbl = rb_hash_s_new(0, NULL, rb_cHash);
- rb_define_global_const("ENV", envtbl);
-#endif /* ifndef __MACOS__ environment variables nothing on MacOS. */
-}
-/**********************************************************************
-
- inits.c -
-
- $Author: dave $
- $Date: 2003/12/19 03:58:57 $
- created at: Tue Dec 28 16:01:58 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-
-void Init_Array _((void));
-void Init_Bignum _((void));
-void Init_Binding _((void));
-void Init_Comparable _((void));
-void Init_Dir _((void));
-void Init_Enumerable _((void));
-void Init_Exception _((void));
-void Init_syserr _((void));
-void Init_eval _((void));
-void Init_load _((void));
-void Init_Proc _((void));
-void Init_Thread _((void));
-void Init_File _((void));
-void Init_GC _((void));
-void Init_Hash _((void));
-void Init_IO _((void));
-void Init_Math _((void));
-void Init_marshal _((void));
-void Init_Numeric _((void));
-void Init_Object _((void));
-void Init_pack _((void));
-void Init_Precision _((void));
-void Init_sym _((void));
-void Init_process _((void));
-void Init_Random _((void));
-void Init_Range _((void));
-void Init_Regexp _((void));
-void Init_signal _((void));
-void Init_String _((void));
-void Init_Struct _((void));
-void Init_Time _((void));
-void Init_var_tables _((void));
-void Init_version _((void));
-
-void
-rb_call_inits()
-{
- Init_sym();
- Init_var_tables();
- Init_Object();
- Init_Comparable();
- Init_Enumerable();
- Init_Precision();
- Init_eval();
- Init_String();
- Init_Exception();
- Init_Thread();
- Init_Numeric();
- Init_Bignum();
- Init_syserr();
- Init_Array();
- Init_Hash();
- Init_Struct();
- Init_Regexp();
- Init_pack();
- Init_Range();
- Init_IO();
- Init_Dir();
- Init_Time();
- Init_Random();
- Init_signal();
- Init_process();
- Init_load();
- Init_Proc();
- Init_Binding();
- Init_Math();
- Init_GC();
- Init_marshal();
- Init_version();
-}
-/**********************************************************************
-
- io.c -
-
- $Author: matz $
- $Date: 2005/03/07 02:05:07 $
- created at: Fri Oct 15 18:08:59 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 "rubyio.h"
-#include "rubysig.h"
-#include <ctype.h>
-#include <errno.h>
-
-#include <sys/types.h>
-#if !defined(_WIN32) && !defined(__DJGPP__)
-# if defined(__BEOS__)
-# include <net/socket.h>
-# else
-# include <sys/socket.h>
-# endif
-#endif
-
-#if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32) || defined(__human68k__) || defined(__EMX__) || defined(__BEOS__)
-# define NO_SAFE_RENAME
-#endif
-
-#if defined(MSDOS) || defined(__CYGWIN__) || defined(_WIN32)
-# define NO_LONG_FNAME
-#endif
-
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(sun) || defined(_nec_ews)
-# define USE_SETVBUF
-#endif
-
-#ifdef __QNXNTO__
-#include "unix.h"
-#endif
-
-#include <sys/types.h>
-#if !defined(DJGPP) && !defined(_WIN32) && !defined(__human68k__)
-#include <sys/ioctl.h>
-#endif
-#if defined(HAVE_FCNTL_H) || defined(_WIN32)
-#include <fcntl.h>
-#elif defined(HAVE_SYS_FCNTL_H)
-#include <sys/fcntl.h>
-#endif
-
-#if !HAVE_OFF_T && !defined(off_t)
-# define off_t long
-#endif
-
-#include <sys/stat.h>
-
-/* EMX has sys/param.h, but.. */
-#if defined(HAVE_SYS_PARAM_H) && !(defined(__EMX__) || defined(__HIUX_MPP__))
-# include <sys/param.h>
-#endif
-
-#if !defined NOFILE
-# define NOFILE 64
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-extern void Init_File _((void));
-
-#ifdef __BEOS__
-# ifndef NOFILE
-# define NOFILE (OPEN_MAX)
-# endif
-#include <net/socket.h>
-#endif
-
-#include "util.h"
-
-#ifndef O_ACCMODE
-#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
-#endif
-
-#if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
-# error off_t is bigger than long, but you have no long long...
-#endif
-
-VALUE rb_cIO;
-VALUE rb_eEOFError;
-VALUE rb_eIOError;
-
-VALUE rb_stdin, rb_stdout, rb_stderr;
-VALUE rb_deferr; /* rescue VIM plugin */
-static VALUE orig_stdout, orig_stderr;
-
-VALUE rb_output_fs;
-VALUE rb_rs;
-VALUE rb_output_rs;
-VALUE rb_default_rs;
-
-static VALUE argf;
-
-static ID id_write, id_read, id_getc, id_flush;
-
-extern char *ruby_inplace_mode;
-
-struct timeval rb_time_interval _((VALUE));
-
-static VALUE filename, current_file;
-static int gets_lineno;
-static int init_p = 0, next_p = 0;
-static VALUE lineno = INT2FIX(0);
-
-#ifdef _STDIO_USES_IOSTREAM /* GNU libc */
-# ifdef _IO_fpos_t
-# define STDIO_READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end)
-# else
-# define STDIO_READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
-# endif
-#elif defined(FILE_COUNT)
-# define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
-#elif defined(FILE_READEND)
-# define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND)
-#elif defined(__BEOS__)
-# define STDIO_READ_DATA_PENDING(fp) (fp->_state._eof == 0)
-#elif defined(__VMS)
-# define STDIO_READ_DATA_PENDING(fp) (((unsigned int)(*(fp))->_cnt) > 0)
-#else
-# define STDIO_READ_DATA_PENDING(fp) (!feof(fp))
-#endif
-
-#if defined(__VMS)
-#define fopen(file_spec, mode) fopen(file_spec, mode, "rfm=stmlf")
-#define open(file_spec, flags, mode) open(file_spec, flags, mode, "rfm=stmlf")
-#endif
-
-#define READ_DATA_PENDING(fptr) ((fptr)->rbuf_len)
-#define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf_len)
-#define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf+(fptr)->rbuf_off)
-#define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
-
-#define READ_CHECK(fptr) do {\
- if (!READ_DATA_PENDING(fptr)) {\
- rb_thread_wait_fd((fptr)->fd);\
- rb_io_check_closed(fptr);\
- }\
-} while(0)
-
-#if defined(_WIN32)
-#define is_socket(fd, path) rb_w32_is_socket(fd)
-#elif defined(__DJGPP__)
-#define is_socket(fd, path) 0
-#define shutdown(a,b) 0
-#else
-static int
-is_socket(fd, path)
- int fd;
- const char *path;
-{
- struct stat sbuf;
- if (fstat(fd, &sbuf) < 0)
- rb_sys_fail(path);
- return S_ISSOCK(sbuf.st_mode);
-}
-#endif
-
-void
-rb_eof_error()
-{
- rb_raise(rb_eEOFError, "end of file reached");
-}
-
-VALUE
-rb_io_taint_check(io)
- VALUE io;
-{
- if (!OBJ_TAINTED(io) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
- rb_check_frozen(io);
- return io;
-}
-
-void
-rb_io_check_initialized(fptr)
- OpenFile *fptr;
-{
- if (!fptr) {
- rb_raise(rb_eIOError, "uninitialized stream");
- }
-}
-
-void
-rb_io_check_closed(fptr)
- OpenFile *fptr;
-{
- rb_io_check_initialized(fptr);
- if (fptr->fd < 0) {
- rb_raise(rb_eIOError, "closed stream");
- }
-}
-
-static int io_fflush _((OpenFile *));
-
-static VALUE
-rb_io_get_io(io)
- VALUE io;
-{
- return rb_convert_type(io, T_FILE, "IO", "to_io");
-}
-
-static VALUE
-rb_io_check_io(io)
- VALUE io;
-{
- return rb_check_convert_type(io, T_FILE, "IO", "to_io");
-}
-
-static void
-io_unread(OpenFile *fptr)
-{
- off_t r;
- rb_io_check_closed(fptr);
- if (fptr->rbuf_len == 0 || fptr->mode & FMODE_DUPLEX)
- return;
- /* xxx: target position may be negative if buffer is filled by ungetc */
- r = lseek(fptr->fd, -fptr->rbuf_len, SEEK_CUR);
- if (r < 0) {
- if (errno == ESPIPE)
- fptr->mode |= FMODE_DUPLEX;
- return;
- }
- fptr->rbuf_off = 0;
- fptr->rbuf_len = 0;
- return;
-}
-
-static int
-io_ungetc(int c, OpenFile *fptr)
-{
- if (fptr->rbuf == NULL) {
- fptr->rbuf_off = 0;
- fptr->rbuf_len = 0;
- fptr->rbuf_capa = 8192;
- fptr->rbuf = ALLOC_N(char, fptr->rbuf_capa);
- }
- if (c < 0 || fptr->rbuf_len == fptr->rbuf_capa) {
- return -1;
- }
- if (fptr->rbuf_off == 0) {
- if (fptr->rbuf_len)
- MEMMOVE(fptr->rbuf+1, fptr->rbuf, char, fptr->rbuf_len);
- fptr->rbuf_off = 1;
- }
- fptr->rbuf_off--;
- fptr->rbuf_len++;
- fptr->rbuf[fptr->rbuf_off] = c;
- return c;
-}
-
-static OpenFile *
-flush_before_seek(fptr)
- OpenFile *fptr;
-{
- io_fflush(fptr);
- io_unread(fptr);
- return fptr;
-}
-
-#define io_seek(fptr, ofs, whence) lseek(flush_before_seek(fptr)->fd, ofs, whence)
-#define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
-
-#ifndef SEEK_CUR
-# define SEEK_SET 0
-# define SEEK_CUR 1
-# define SEEK_END 2
-#endif
-
-#define FMODE_SYNCWRITE (FMODE_SYNC|FMODE_WRITABLE)
-
-void
-rb_io_check_readable(fptr)
- OpenFile *fptr;
-{
- rb_io_check_closed(fptr);
- if (!(fptr->mode & FMODE_READABLE)) {
- rb_raise(rb_eIOError, "not opened for reading");
- }
- if (fptr->wbuf_len) {
- io_fflush(fptr);
- }
-}
-
-void
-rb_io_check_writable(fptr)
- OpenFile *fptr;
-{
- rb_io_check_closed(fptr);
- if (!(fptr->mode & FMODE_WRITABLE)) {
- rb_raise(rb_eIOError, "not opened for writing");
- }
- if (fptr->rbuf_len) {
- io_unread(fptr);
- }
-}
-
-int
-rb_read_pending(fp)
- FILE *fp;
-{
- return STDIO_READ_DATA_PENDING(fp);
-}
-
-int
-rb_io_read_pending(OpenFile *fptr)
-{
- return READ_DATA_PENDING(fptr);
-}
-
-void
-rb_read_check(fp)
- FILE *fp;
-{
- if (!STDIO_READ_DATA_PENDING(fp)) {
- rb_thread_wait_fd(fileno(fp));
- }
-}
-
-void
-rb_io_read_check(OpenFile *fptr)
-{
- if (!READ_DATA_PENDING(fptr)) {
- rb_thread_wait_fd(fptr->fd);
- }
- return;
-}
-
-static int
-ruby_dup(orig)
- int orig;
-{
- int fd;
-
- fd = dup(orig);
- if (fd < 0) {
- if (errno == EMFILE || errno == ENFILE) {
- rb_gc();
- fd = dup(orig);
- }
- if (fd < 0) {
- rb_sys_fail(0);
- }
- }
- return fd;
-}
-
-static VALUE io_alloc _((VALUE));
-static VALUE
-io_alloc(klass)
- VALUE klass;
-{
- NEWOBJ(io, struct RFile);
- OBJSETUP(io, klass, T_FILE);
-
- io->fptr = 0;
-
- return (VALUE)io;
-}
-
-static int
-io_fflush(fptr)
- OpenFile *fptr;
-{
- int r;
- int wbuf_off, wbuf_len;
-
- rb_io_check_closed(fptr);
- if (fptr->wbuf_len == 0)
- return 0;
- if (!rb_thread_fd_writable(fptr->fd)) {
- rb_io_check_closed(fptr);
- }
- retry:
- if (fptr->wbuf_len == 0)
- return 0;
- wbuf_off = fptr->wbuf_off;
- wbuf_len = fptr->wbuf_len;
- TRAP_BEG;
- r = write(fptr->fd, fptr->wbuf+fptr->wbuf_off, fptr->wbuf_len);
- TRAP_END; /* xxx: signal handler may modify wbuf */
- if (r == fptr->wbuf_len) {
- fptr->wbuf_off = 0;
- fptr->wbuf_len = 0;
- return 0;
- }
- if (0 <= r) {
- fptr->wbuf_off = (wbuf_off += r);
- fptr->wbuf_len = (wbuf_len -= r);
- errno = EAGAIN;
- }
- if (rb_io_wait_writable(fptr->fd)) {
- rb_io_check_closed(fptr);
- goto retry;
- }
- return -1;
-}
-
-int
-rb_io_wait_readable(f)
- int f;
-{
- fd_set rfds;
-
- switch (errno) {
- case EINTR:
-#if defined(ERESTART)
- case ERESTART:
-#endif
- rb_thread_wait_fd(f);
- return Qtrue;
-
- case EAGAIN:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
-#endif
- FD_ZERO(&rfds);
- FD_SET(f, &rfds);
- rb_thread_select(f + 1, &rfds, NULL, NULL, NULL);
- return Qtrue;
-
- default:
- return Qfalse;
- }
-}
-
-int
-rb_io_wait_writable(f)
- int f;
-{
- fd_set wfds;
-
- switch (errno) {
- case EINTR:
-#if defined(ERESTART)
- case ERESTART:
-#endif
- rb_thread_fd_writable(f);
- return Qtrue;
-
- case EAGAIN:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
-#endif
- FD_ZERO(&wfds);
- FD_SET(f, &wfds);
- rb_thread_select(f + 1, NULL, &wfds, NULL, NULL);
- return Qtrue;
-
- default:
- return Qfalse;
- }
-}
-
-/* writing functions */
-static long
-io_fwrite(str, fptr)
- VALUE str;
- OpenFile *fptr;
-{
- long len, n, r, offset = 0;
-
- len = RSTRING(str)->len;
- if ((n = len) <= 0) return n;
- if (fptr->wbuf == NULL && !(fptr->mode & FMODE_SYNC)) {
- fptr->wbuf_off = 0;
- fptr->wbuf_len = 0;
- fptr->wbuf_capa = 8192;
- fptr->wbuf = ALLOC_N(char, fptr->wbuf_capa);
- }
- if ((fptr->mode & FMODE_SYNC) ||
- (fptr->wbuf && fptr->wbuf_capa <= fptr->wbuf_len + len) ||
- ((fptr->mode & FMODE_TTY) && memchr(RSTRING(str)->ptr+offset, '\n', len))) {
- /* xxx: use writev to avoid double write if available */
- if (fptr->wbuf_len && fptr->wbuf_len+len <= fptr->wbuf_capa) {
- if (fptr->wbuf_capa < fptr->wbuf_off+fptr->wbuf_len+len) {
- MEMMOVE(fptr->wbuf, fptr->wbuf+fptr->wbuf_off, char, fptr->wbuf_len);
- fptr->wbuf_off = 0;
- }
- MEMMOVE(fptr->wbuf+fptr->wbuf_off+fptr->wbuf_len, RSTRING(str)->ptr+offset, char, len);
- fptr->wbuf_len += len;
- n = 0;
- }
- if (io_fflush(fptr) < 0)
- return -1L;
- if (n == 0)
- return len;
- /* avoid context switch between "a" and "\n" in STDERR.puts "a".
- [ruby-dev:25080] */
- if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd)) {
- rb_io_check_closed(fptr);
- }
- retry:
- TRAP_BEG;
- r = write(fptr->fd, RSTRING(str)->ptr+offset, n);
- TRAP_END; /* xxx: signal handler may modify given string. */
- if (r == n) return len;
- if (0 <= r) {
- offset += r;
- n -= r;
- errno = EAGAIN;
- }
- if (rb_io_wait_writable(fptr->fd)) {
- rb_io_check_closed(fptr);
- if (offset < RSTRING(str)->len)
- goto retry;
- }
- return -1L;
- }
-
- if (fptr->wbuf_off) {
- if (fptr->wbuf_len)
- MEMMOVE(fptr->wbuf, fptr->wbuf+fptr->wbuf_off, char, fptr->wbuf_len);
- fptr->wbuf_off = 0;
- }
- MEMMOVE(fptr->wbuf+fptr->wbuf_off+fptr->wbuf_len, RSTRING(str)->ptr+offset, char, len);
- fptr->wbuf_len += len;
- return len;
-}
-
-long
-rb_io_fwrite(ptr, len, f)
- const char *ptr;
- long len;
- FILE *f;
-{
- OpenFile of;
-
- of.fd = fileno(f);
- of.stdio_file = f;
- of.mode = FMODE_WRITABLE;
- of.path = NULL;
- return io_fwrite(rb_str_new(ptr, len), &of);
-}
-
-/*
- * call-seq:
- * ios.write(string) => integer
- *
- * Writes the given string to <em>ios</em>. The stream must be opened
- * for writing. If the argument is not a string, it will be converted
- * to a string using <code>to_s</code>. Returns the number of bytes
- * written.
- *
- * count = $stdout.write( "This is a test\n" )
- * puts "That was #{count} bytes of data"
- *
- * <em>produces:</em>
- *
- * This is a test
- * That was 15 bytes of data
- */
-
-static VALUE
-io_write(io, str)
- VALUE io, str;
-{
- OpenFile *fptr;
- long n;
- VALUE tmp;
-
- rb_secure(4);
- str = rb_obj_as_string(str);
- tmp = rb_io_check_io(io);
- if (NIL_P(tmp)) {
- /* port is not IO, call write method for it. */
- return rb_funcall(io, id_write, 1, str);
- }
- io = tmp;
- if (RSTRING(str)->len == 0) return INT2FIX(0);
-
- GetOpenFile(io, fptr);
- rb_io_check_writable(fptr);
-
- n = io_fwrite(str, fptr);
- if (n == -1L) rb_sys_fail(fptr->path);
-
- return LONG2FIX(n);
-}
-
-VALUE
-rb_io_write(io, str)
- VALUE io, str;
-{
- return rb_funcall(io, id_write, 1, str);
-}
-
-/*
- * call-seq:
- * ios << obj => ios
- *
- * String Output---Writes <i>obj</i> to <em>ios</em>.
- * <i>obj</i> will be converted to a string using
- * <code>to_s</code>.
- *
- * $stdout << "Hello " << "world!\n"
- *
- * <em>produces:</em>
- *
- * Hello world!
- */
-
-
-VALUE
-rb_io_addstr(io, str)
- VALUE io, str;
-{
- rb_io_write(io, str);
- return io;
-}
-
-/*
- * call-seq:
- * ios.flush => ios
- *
- * Flushes any buffered data within <em>ios</em> to the underlying
- * operating system (note that this is Ruby internal buffering only;
- * the OS may buffer the data as well).
- *
- * $stdout.print "no newline"
- * $stdout.flush
- *
- * <em>produces:</em>
- *
- * no newline
- */
-
-VALUE
-rb_io_flush(io)
- VALUE io;
-{
- OpenFile *fptr;
-
- if (TYPE(io) != T_FILE) {
- return rb_funcall(io, id_flush, 0);
- }
-
- GetOpenFile(io, fptr);
-
- if (fptr->mode & FMODE_WRITABLE) {
- io_fflush(fptr);
- }
- if (fptr->mode & FMODE_READABLE) {
- io_unread(fptr);
- }
-
- return io;
-}
-
-/*
- * call-seq:
- * ios.pos => integer
- * ios.tell => integer
- *
- * Returns the current offset (in bytes) of <em>ios</em>.
- *
- * f = File.new("testfile")
- * f.pos #=> 0
- * f.gets #=> "This is line one\n"
- * f.pos #=> 17
- */
-
-static VALUE
-rb_io_tell(io)
- VALUE io;
-{
- OpenFile *fptr;
- off_t pos;
-
- GetOpenFile(io, fptr);
- pos = io_tell(fptr);
- if (pos < 0) rb_sys_fail(fptr->path);
- return OFFT2NUM(pos);
-}
-
-static VALUE
-rb_io_seek(io, offset, whence)
- VALUE io, offset;
- int whence;
-{
- OpenFile *fptr;
- off_t pos;
-
- pos = NUM2OFFT(offset);
- GetOpenFile(io, fptr);
- pos = io_seek(fptr, pos, whence);
- if (pos < 0) rb_sys_fail(fptr->path);
-
- return INT2FIX(0);
-}
-
-/*
- * call-seq:
- * ios.seek(amount, whence=SEEK_SET) -> 0
- *
- * Seeks to a given offset <i>anInteger</i> in the stream according to
- * the value of <i>whence</i>:
- *
- * IO::SEEK_CUR | Seeks to _amount_ plus current position
- * --------------+----------------------------------------------------
- * IO::SEEK_END | Seeks to _amount_ plus end of stream (you probably
- * | want a negative value for _amount_)
- * --------------+----------------------------------------------------
- * IO::SEEK_SET | Seeks to the absolute location given by _amount_
- *
- * Example:
- *
- * f = File.new("testfile")
- * f.seek(-13, IO::SEEK_END) #=> 0
- * f.readline #=> "And so on...\n"
- */
-
-static VALUE
-rb_io_seek_m(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE offset, ptrname;
- int whence = SEEK_SET;
-
- if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
- whence = NUM2INT(ptrname);
- }
-
- return rb_io_seek(io, offset, whence);
-}
-
-/*
- * call-seq:
- * ios.pos = integer => integer
- *
- * Seeks to the given position (in bytes) in <em>ios</em>.
- *
- * f = File.new("testfile")
- * f.pos = 17
- * f.gets #=> "This is line two\n"
- */
-
-static VALUE
-rb_io_set_pos(io, offset)
- VALUE io, offset;
-{
- OpenFile *fptr;
- off_t pos;
-
- pos = NUM2OFFT(offset);
- GetOpenFile(io, fptr);
- pos = io_seek(fptr, pos, SEEK_SET);
- if (pos < 0) rb_sys_fail(fptr->path);
-
- return OFFT2NUM(pos);
-}
-
-/*
- * call-seq:
- * ios.rewind => 0
- *
- * Positions <em>ios</em> to the beginning of input, resetting
- * <code>lineno</code> to zero.
- *
- * f = File.new("testfile")
- * f.readline #=> "This is line one\n"
- * f.rewind #=> 0
- * f.lineno #=> 0
- * f.readline #=> "This is line one\n"
- */
-
-static VALUE
-rb_io_rewind(io)
- VALUE io;
-{
- OpenFile *fptr;
-
- GetOpenFile(io, fptr);
- if (io_seek(fptr, 0L, 0) < 0) rb_sys_fail(fptr->path);
- if (io == current_file) {
- gets_lineno -= fptr->lineno;
- }
- fptr->lineno = 0;
-
- return INT2FIX(0);
-}
-
-static int
-io_getc(OpenFile *fptr)
-{
- int r;
- if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && TYPE(rb_stdout) == T_FILE) {
- OpenFile *ofp;
- GetOpenFile(rb_stdout, ofp);
- if (ofp->mode & FMODE_TTY) {
- rb_io_flush(rb_stdout);
- }
- }
- if (fptr->rbuf == NULL) {
- fptr->rbuf_off = 0;
- fptr->rbuf_len = 0;
- fptr->rbuf_capa = 8192;
- fptr->rbuf = ALLOC_N(char, fptr->rbuf_capa);
- }
- if (fptr->rbuf_len == 0) {
- retry:
- TRAP_BEG;
- r = read(fptr->fd, fptr->rbuf, fptr->rbuf_capa);
- TRAP_END; /* xxx: signal handler may modify rbuf */
- if (r < 0) {
- if (rb_io_wait_readable(fptr->fd))
- goto retry;
- rb_sys_fail(fptr->path);
- }
- fptr->rbuf_off = 0;
- fptr->rbuf_len = r;
- if (r == 0)
- return -1; /* EOF */
- }
- fptr->rbuf_off++;
- fptr->rbuf_len--;
- return (unsigned char)fptr->rbuf[fptr->rbuf_off-1];
-}
-
-/*
- * call-seq:
- * ios.eof => true or false
- * ios.eof? => true or false
- *
- * Returns true if <em>ios</em> is at end of file. The stream must be
- * opened for reading or an <code>IOError</code> will be raised.
- *
- * f = File.new("testfile")
- * dummy = f.readlines
- * f.eof #=> true
- */
-
-VALUE
-rb_io_eof(io)
- VALUE io;
-{
- OpenFile *fptr;
- int ch;
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
-
- if (READ_DATA_PENDING(fptr)) return Qfalse;
- READ_CHECK(fptr);
- ch = io_getc(fptr);
-
- if (ch != EOF) {
- io_ungetc(ch, fptr);
- return Qfalse;
- }
- return Qtrue;
-}
-
-/*
- * call-seq:
- * ios.sync => true or false
- *
- * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
- * true, all output is immediately flushed to the underlying operating
- * system and is not buffered by Ruby internally. See also
- * <code>IO#fsync</code>.
- *
- * f = File.new("testfile")
- * f.sync #=> false
- */
-
-static VALUE
-rb_io_sync(io)
- VALUE io;
-{
- OpenFile *fptr;
-
- GetOpenFile(io, fptr);
- return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- * ios.sync = boolean => boolean
- *
- * Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
- * When sync mode is true, all output is immediately flushed to the
- * underlying operating system and is not buffered internally. Returns
- * the new state. See also <code>IO#fsync</code>.
- *
- * f = File.new("testfile")
- * f.sync = true
- *
- * <em>(produces no output)</em>
- */
-
-static VALUE
-rb_io_set_sync(io, mode)
- VALUE io, mode;
-{
- OpenFile *fptr;
-
- GetOpenFile(io, fptr);
- if (RTEST(mode)) {
- fptr->mode |= FMODE_SYNC;
- }
- else {
- fptr->mode &= ~FMODE_SYNC;
- }
- return mode;
-}
-
-/*
- * call-seq:
- * ios.fsync => 0 or nil
- *
- * Immediately writes all buffered data in <em>ios</em> to disk.
- * Returns <code>nil</code> if the underlying operating system does not
- * support <em>fsync(2)</em>. Note that <code>fsync</code> differs from
- * using <code>IO#sync=</code>. The latter ensures that data is flushed
- * from Ruby's buffers, but doesn't not guarantee that the underlying
- * operating system actually writes it to disk.
- */
-
-static VALUE
-rb_io_fsync(io)
- VALUE io;
-{
-#ifdef HAVE_FSYNC
- OpenFile *fptr;
-
- GetOpenFile(io, fptr);
-
- io_fflush(fptr);
- if (fsync(fptr->fd) < 0)
- rb_sys_fail(fptr->path);
- return INT2FIX(0);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-/*
- * call-seq:
- * ios.fileno => fixnum
- * ios.to_i => fixnum
- *
- * Returns an integer representing the numeric file descriptor for
- * <em>ios</em>.
- *
- * $stdin.fileno #=> 0
- * $stdout.fileno #=> 1
- */
-
-static VALUE
-rb_io_fileno(io)
- VALUE io;
-{
- OpenFile *fptr;
- int fd;
-
- GetOpenFile(io, fptr);
- fd = fptr->fd;
- return INT2FIX(fd);
-}
-
-
-/*
- * call-seq:
- * ios.pid => fixnum
- *
- * Returns the process ID of a child process associated with
- * <em>ios</em>. This will be set by <code>IO::popen</code>.
- *
- * pipe = IO.popen("-")
- * if pipe
- * $stderr.puts "In parent, child pid is #{pipe.pid}"
- * else
- * $stderr.puts "In child, pid is #{$$}"
- * end
- *
- * <em>produces:</em>
- *
- * In child, pid is 26209
- * In parent, child pid is 26209
- */
-
-static VALUE
-rb_io_pid(io)
- VALUE io;
-{
- OpenFile *fptr;
-
- GetOpenFile(io, fptr);
- if (!fptr->pid)
- return Qnil;
- return INT2FIX(fptr->pid);
-}
-
-
-/*
- * call-seq:
- * ios.inspect => string
- *
- * Return a string describing this IO object.
- */
-
-static VALUE
-rb_io_inspect(obj)
- VALUE obj;
-{
- OpenFile *fptr;
- char *buf, *cname, *st = "";
- long len;
-
- fptr = RFILE(rb_io_taint_check(obj))->fptr;
- if (!fptr || !fptr->path) return rb_any_to_s(obj);
- cname = rb_obj_classname(obj);
- len = strlen(cname) + strlen(fptr->path) + 5;
- if (fptr->fd < 0) {
- st = " (closed)";
- len += 9;
- }
- buf = ALLOCA_N(char, len);
- sprintf(buf, "#<%s:%s%s>", cname, fptr->path, st);
- return rb_str_new2(buf);
-}
-
-/*
- * call-seq:
- * ios.to_io -> ios
- *
- * Returns <em>ios</em>.
- */
-
-static VALUE
-rb_io_to_io(io)
- VALUE io;
-{
- return io;
-}
-
-/* reading functions */
-static long
-read_buffered_data(char *ptr, long len, OpenFile *fptr)
-{
- long n;
-
- n = READ_DATA_PENDING_COUNT(fptr);
- if (n <= 0) return 0;
- if (n > len) n = len;
- MEMMOVE(ptr, fptr->rbuf+fptr->rbuf_off, char, n);
- fptr->rbuf_off += n;
- fptr->rbuf_len -= n;
- return n;
-}
-
-static long
-io_fread(str, offset, fptr)
- VALUE str;
- long offset;
- OpenFile *fptr;
-{
- long len = RSTRING(str)->len - offset;
- long n = len;
- int c;
-
- while (n > 0) {
- c = read_buffered_data(RSTRING(str)->ptr+offset, n, fptr);
- if (c > 0) {
- offset += c;
- if ((n -= c) <= 0) break;
- }
- rb_thread_wait_fd(fptr->fd);
- rb_io_check_closed(fptr);
- c = io_getc(fptr);
- if (c < 0) {
- break;
- }
- RSTRING(str)->ptr[offset++] = c;
- if (offset > RSTRING(str)->len) break;
- n--;
- }
- return len - n;
-}
-
-long
-rb_io_fread(ptr, len, f)
- char *ptr;
- long len;
- FILE *f;
-{
- OpenFile of;
- VALUE str;
- long n;
-
- of.fd = fileno(f);
- of.stdio_file = f;
- of.mode = FMODE_READABLE;
- str = rb_str_new(ptr, len);
- n = io_fread(str, 0, &of);
- MEMCPY(ptr, RSTRING(str)->ptr, char, n);
- return n;
-}
-
-#ifndef S_ISREG
-# define S_ISREG(m) ((m & S_IFMT) == S_IFREG)
-#endif
-
-#define SMALLBUF 100
-
-static long
-remain_size(fptr)
- OpenFile *fptr;
-{
- struct stat st;
- off_t siz = READ_DATA_PENDING_COUNT(fptr);
- off_t pos;
-
- if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
-#ifdef __BEOS__
- && (st.st_dev > 3)
-#endif
- )
- {
- io_fflush(fptr);
- pos = lseek(fptr->fd, 0, SEEK_CUR);
- if (st.st_size >= pos && pos >= 0) {
- siz += st.st_size - pos + 1;
- if (siz > LONG_MAX) {
- rb_raise(rb_eIOError, "file too big for single read");
- }
- }
- }
- else {
- siz += BUFSIZ;
- }
- return (long)siz;
-}
-
-static VALUE
-read_all(fptr, siz, str)
- OpenFile *fptr;
- long siz;
- VALUE str;
-{
- long bytes = 0;
- long n;
-
- if (siz == 0) siz = BUFSIZ;
- if (NIL_P(str)) {
- str = rb_str_new(0, siz);
- }
- else {
- rb_str_resize(str, siz);
- }
- for (;;) {
- READ_CHECK(fptr);
- n = io_fread(str, bytes, fptr);
- if (n == 0 && bytes == 0) {
- break;
- }
- bytes += n;
- if (bytes < siz) break;
- siz += BUFSIZ;
- rb_str_resize(str, siz);
- }
- if (bytes != siz) rb_str_resize(str, bytes);
- OBJ_TAINT(str);
-
- return str;
-}
-
-static VALUE
-io_getpartial(int argc, VALUE *argv, VALUE io)
-{
- OpenFile *fptr;
- VALUE length, str;
- long n, len;
-
- rb_scan_args(argc, argv, "11", &length, &str);
-
- if ((len = NUM2LONG(length)) < 0) {
- rb_raise(rb_eArgError, "negative length %ld given", len);
- }
-
- if (NIL_P(str)) {
- str = rb_str_new(0, len);
- }
- else {
- StringValue(str);
- rb_str_modify(str);
- rb_str_resize(str, len);
- }
- OBJ_TAINT(str);
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
-
- if (len == 0)
- return str;
-
- READ_CHECK(fptr);
- if (RSTRING(str)->len != len) {
- modified:
- rb_raise(rb_eRuntimeError, "buffer string modified");
- }
- n = read_buffered_data(RSTRING(str)->ptr, len, fptr);
- if (n <= 0) {
- again:
- if (RSTRING(str)->len != len) goto modified;
- TRAP_BEG;
- n = read(fptr->fd, RSTRING(str)->ptr, len);
- TRAP_END;
- if (n < 0) {
- if (rb_io_wait_readable(fptr->fd))
- goto again;
- rb_sys_fail(fptr->path);
- }
- }
- rb_str_resize(str, n);
-
- if (n == 0)
- return Qnil;
- else
- return str;
-}
-
-/*
- * call-seq:
- * ios.readpartial(maxlen[, outbuf]) => string, outbuf
- *
- * Reads at most <i>maxlen</i> bytes from the I/O stream but
- * it blocks only if <em>ios</em> has no data immediately available.
- * If the optional <i>outbuf</i> argument is present,
- * it must reference a String, which will receive the data.
- * It raises <code>EOFError</code> on end of file.
- *
- * readpartial is designed for streams such as pipe, socket, tty, etc.
- * It blocks only when no data immediately available.
- * This means that it blocks only when following all conditions hold.
- * * the buffer in the IO object is empty.
- * * the content of the stream is empty.
- * * the stream is not reached to EOF.
- *
- * When readpartial blocks, it waits data or EOF on the stream.
- * If some data is reached, readpartial returns with the data.
- * If EOF is reached, readpartial raises EOFError.
- *
- * When readpartial doesn't blocks, it returns or raises immediately.
- * If the buffer is not empty, it returns the data in the buffer.
- * Otherwise if the stream has some content,
- * it returns the data in the stream.
- * Otherwise if the stream is reached to EOF, it raises EOFError.
- *
- * r, w = IO.pipe # buffer pipe content
- * w << "abc" # "" "abc".
- * r.readpartial(4096) #=> "abc" "" ""
- * r.readpartial(4096) # blocks because buffer and pipe is empty.
- *
- * r, w = IO.pipe # buffer pipe content
- * w << "abc" # "" "abc"
- * w.close # "" "abc" EOF
- * r.readpartial(4096) #=> "abc" "" EOF
- * r.readpartial(4096) # raises EOFError
- *
- * r, w = IO.pipe # buffer pipe content
- * w << "abc\ndef\n" # "" "abc\ndef\n"
- * r.gets #=> "abc\n" "def\n" ""
- * w << "ghi\n" # "def\n" "ghi\n"
- * r.readpartial(4096) #=> "def\n" "" "ghi\n"
- * r.readpartial(4096) #=> "ghi\n" "" ""
- *
- * Note that readpartial is nonblocking-flag insensitive.
- * It blocks even if the nonblocking-flag is set.
- *
- * Also note that readpartial behaves similar to sysread in blocking mode.
- * The behavior is identical when the buffer is empty.
- *
- */
-
-static VALUE
-io_readpartial(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE ret;
-
- ret = io_getpartial(argc, argv, io);
- if (NIL_P(ret))
- rb_eof_error();
- else
- return ret;
-}
-
-/*
- * call-seq:
- * ios.read([length [, buffer]]) => string, buffer, or nil
- *
- * Reads at most <i>length</i> bytes from the I/O stream, or to the
- * end of file if <i>length</i> is omitted or is <code>nil</code>.
- * <i>length</i> must be a non-negative integer or nil.
- * If the optional <i>buffer</i> argument is present, it must reference
- * a String, which will receive the data.
- *
- * At end of file, it returns <code>nil</code> or <code>""</code>
- * depend on <i>length</i>.
- * <code><i>ios</i>.read()</code> and
- * <code><i>ios</i>.read(nil)</code> returns <code>""</code>.
- * <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns nil.
- *
- * <code><i>ios</i>.read(0)</code> returns <code>""</code>.
- *
- * f = File.new("testfile")
- * f.read(16) #=> "This is line one"
- */
-
-static VALUE
-io_read(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- OpenFile *fptr;
- long n, len;
- VALUE length, str;
-
- rb_scan_args(argc, argv, "02", &length, &str);
-
- if (NIL_P(length)) {
- if (!NIL_P(str)) StringValue(str);
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
- return read_all(fptr, remain_size(fptr), str);
- }
- len = NUM2LONG(length);
- if (len < 0) {
- rb_raise(rb_eArgError, "negative length %ld given", len);
- }
-
- if (NIL_P(str)) {
- str = rb_tainted_str_new(0, len);
- }
- else {
- StringValue(str);
- rb_str_modify(str);
- rb_str_resize(str,len);
- }
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
- if (len == 0) return str;
-
- READ_CHECK(fptr);
- if (RSTRING(str)->len != len) {
- rb_raise(rb_eRuntimeError, "buffer string modified");
- }
- n = io_fread(str, 0, fptr);
- if (n == 0) {
- if (fptr->fd < 0) return Qnil;
- rb_str_resize(str, 0);
- return Qnil;
- }
- rb_str_resize(str, n);
- RSTRING(str)->len = n;
- RSTRING(str)->ptr[n] = '\0';
- OBJ_TAINT(str);
-
- return str;
-}
-
-static int
-appendline(fptr, delim, strp)
- OpenFile *fptr;
- int delim;
- VALUE *strp;
-{
- VALUE str = *strp;
- int c = EOF;
-
- do {
- long pending = READ_DATA_PENDING_COUNT(fptr);
- if (pending > 0) {
- const char *p = READ_DATA_PENDING_PTR(fptr);
- const char *e = memchr(p, delim, pending);
- long last = 0, len = (c != EOF);
- if (e) pending = e - p + 1;
- len += pending;
- if (!NIL_P(str)) {
- last = RSTRING(str)->len;
- rb_str_resize(str, last + len);
- }
- else {
- *strp = str = rb_str_buf_new(len);
- RSTRING(str)->len = len;
- RSTRING(str)->ptr[len] = '\0';
- }
- if (c != EOF) {
- RSTRING(str)->ptr[last++] = c;
- }
- read_buffered_data(RSTRING(str)->ptr + last, pending, fptr); /* must not fail */
- if (e) return delim;
- }
- else if (c != EOF) {
- if (!NIL_P(str)) {
- char ch = c;
- rb_str_buf_cat(str, &ch, 1);
- }
- else {
- *strp = str = rb_str_buf_new(1);
- RSTRING(str)->ptr[RSTRING(str)->len++] = c;
- }
- }
- rb_thread_wait_fd(fptr->fd);
- rb_io_check_closed(fptr);
- c = io_getc(fptr);
- if (c < 0) {
- return c;
- }
- } while (c != delim);
-
- {
- char ch = c;
- if (!NIL_P(str)) {
- rb_str_cat(str, &ch, 1);
- }
- else {
- *strp = str = rb_str_new(&ch, 1);
- }
- }
-
- return c;
-}
-
-static inline int
-swallow(fptr, term)
- OpenFile *fptr;
- int term;
-{
- int c;
-
- do {
- long cnt;
- while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
- char buf[1024];
- const char *p = READ_DATA_PENDING_PTR(fptr);
- int i;
- if (cnt > sizeof buf) cnt = sizeof buf;
- if (*p != term) return Qtrue;
- i = cnt;
- while (--i && *++p == term);
- if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
- rb_sys_fail(fptr->path);
- }
- rb_thread_wait_fd(fptr->fd);
- rb_io_check_closed(fptr);
- c = io_getc(fptr);
- if (c != term) {
- io_ungetc(c, fptr);
- return Qtrue;
- }
- } while (c != EOF);
- return Qfalse;
-}
-
-static VALUE
-rb_io_getline_fast(fptr, delim)
- OpenFile *fptr;
- unsigned char delim;
-{
- VALUE str = Qnil;
- int c;
-
- while ((c = appendline(fptr, delim, &str)) != EOF && c != delim);
-
- if (!NIL_P(str)) {
- fptr->lineno++;
- lineno = INT2FIX(fptr->lineno);
- OBJ_TAINT(str);
- }
-
- return str;
-}
-
-static int
-rscheck(rsptr, rslen, rs)
- char *rsptr;
- long rslen;
- VALUE rs;
-{
- if (RSTRING(rs)->ptr != rsptr && RSTRING(rs)->len != rslen)
- rb_raise(rb_eRuntimeError, "rs modified");
- return 0;
-}
-
-static VALUE
-rb_io_getline(rs, io)
- VALUE rs, io;
-{
- VALUE str = Qnil;
- OpenFile *fptr;
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
- if (NIL_P(rs)) {
- str = read_all(fptr, 0, Qnil);
- if (RSTRING(str)->len == 0) return Qnil;
- }
- else if (rs == rb_default_rs) {
- return rb_io_getline_fast(fptr, '\n');
- }
- else {
- int c, newline;
- char *rsptr;
- long rslen;
- int rspara = 0;
-
- rslen = RSTRING(rs)->len;
- if (rslen == 0) {
- rsptr = "\n\n";
- rslen = 2;
- rspara = 1;
- swallow(fptr, '\n');
- }
- else if (rslen == 1) {
- return rb_io_getline_fast(fptr, (unsigned char)RSTRING(rs)->ptr[0]);
- }
- else {
- rsptr = RSTRING(rs)->ptr;
- }
- newline = rsptr[rslen - 1];
-
- while ((c = appendline(fptr, newline, &str)) != EOF) {
- if (c == newline) {
- if (RSTRING(str)->len < rslen) continue;
- if (!rspara) rscheck(rsptr, rslen, rs);
- if (memcmp(RSTRING(str)->ptr + RSTRING(str)->len - rslen,
- rsptr, rslen) == 0) break;
- }
- }
-
- if (rspara) {
- if (c != EOF) {
- swallow(fptr, '\n');
- }
- }
- }
-
- if (!NIL_P(str)) {
- fptr->lineno++;
- lineno = INT2FIX(fptr->lineno);
- OBJ_TAINT(str);
- }
-
- return str;
-}
-
-VALUE
-rb_io_gets(io)
- VALUE io;
-{
- OpenFile *fptr;
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
- return rb_io_getline_fast(fptr, '\n');
-}
-
-/*
- * call-seq:
- * ios.gets(sep_string=$/) => string or nil
- *
- * Reads the next ``line'' from the I/O stream; lines are separated by
- * <i>sep_string</i>. A separator of <code>nil</code> reads the entire
- * contents, and a zero-length separator reads the input a paragraph at
- * a time (two successive newlines in the input separate paragraphs).
- * The stream must be opened for reading or an <code>IOError</code>
- * will be raised. The line read in will be returned and also assigned
- * to <code>$_</code>. Returns <code>nil</code> if called at end of
- * file.
- *
- * File.new("testfile").gets #=> "This is line one\n"
- * $_ #=> "This is line one\n"
- */
-
-static VALUE
-rb_io_gets_m(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE rs, str;
-
- if (argc == 0) {
- rs = rb_rs;
- }
- else {
- rb_scan_args(argc, argv, "1", &rs);
- if (!NIL_P(rs)) StringValue(rs);
- }
- str = rb_io_getline(rs, io);
- rb_lastline_set(str);
-
- return str;
-}
-
-/*
- * call-seq:
- * ios.lineno => integer
- *
- * Returns the current line number in <em>ios</em>. The stream must be
- * opened for reading. <code>lineno</code> counts the number of times
- * <code>gets</code> is called, rather than the number of newlines
- * encountered. The two values will differ if <code>gets</code> is
- * called with a separator other than newline. See also the
- * <code>$.</code> variable.
- *
- * f = File.new("testfile")
- * f.lineno #=> 0
- * f.gets #=> "This is line one\n"
- * f.lineno #=> 1
- * f.gets #=> "This is line two\n"
- * f.lineno #=> 2
- */
-
-static VALUE
-rb_io_lineno(io)
- VALUE io;
-{
- OpenFile *fptr;
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
- return INT2NUM(fptr->lineno);
-}
-
-/*
- * call-seq:
- * ios.lineno = integer => integer
- *
- * Manually sets the current line number to the given value.
- * <code>$.</code> is updated only on the next read.
- *
- * f = File.new("testfile")
- * f.gets #=> "This is line one\n"
- * $. #=> 1
- * f.lineno = 1000
- * f.lineno #=> 1000
- * $. # lineno of last read #=> 1
- * f.gets #=> "This is line two\n"
- * $. # lineno of last read #=> 1001
- */
-
-static VALUE
-rb_io_set_lineno(io, lineno)
- VALUE io, lineno;
-{
- OpenFile *fptr;
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
- fptr->lineno = NUM2INT(lineno);
- return lineno;
-}
-
-static void
-lineno_setter(val, id, var)
- VALUE val;
- ID id;
- VALUE *var;
-{
- gets_lineno = NUM2INT(val);
- *var = INT2FIX(gets_lineno);
-}
-
-static VALUE
-argf_set_lineno(argf, val)
- VALUE argf, val;
-{
- gets_lineno = NUM2INT(val);
- lineno = INT2FIX(gets_lineno);
- return Qnil;
-}
-
-static VALUE
-argf_lineno()
-{
- return lineno;
-}
-
-/*
- * call-seq:
- * ios.readline(sep_string=$/) => string
- *
- * Reads a line as with <code>IO#gets</code>, but raises an
- * <code>EOFError</code> on end of file.
- */
-
-static VALUE
-rb_io_readline(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE line = rb_io_gets_m(argc, argv, io);
-
- if (NIL_P(line)) {
- rb_eof_error();
- }
- return line;
-}
-
-/*
- * call-seq:
- * ios.readlines(sep_string=$/) => array
- *
- * Reads all of the lines in <em>ios</em>, and returns them in
- * <i>anArray</i>. Lines are separated by the optional
- * <i>sep_string</i>. If <i>sep_string</i> is <code>nil</code>, the
- * rest of the stream is returned as a single record.
- * The stream must be opened for reading or an
- * <code>IOError</code> will be raised.
- *
- * f = File.new("testfile")
- * f.readlines[0] #=> "This is line one\n"
- */
-
-static VALUE
-rb_io_readlines(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE line, ary;
- VALUE rs;
-
- if (argc == 0) {
- rs = rb_rs;
- }
- else {
- rb_scan_args(argc, argv, "1", &rs);
- if (!NIL_P(rs)) StringValue(rs);
- }
- ary = rb_ary_new();
- while (!NIL_P(line = rb_io_getline(rs, io))) {
- rb_ary_push(ary, line);
- }
- return ary;
-}
-
-/*
- * call-seq:
- * ios.each(sep_string=$/) {|line| block } => ios
- * ios.each_line(sep_string=$/) {|line| block } => ios
- *
- * Executes the block for every line in <em>ios</em>, where lines are
- * separated by <i>sep_string</i>. <em>ios</em> must be opened for
- * reading or an <code>IOError</code> will be raised.
- *
- * f = File.new("testfile")
- * f.each {|line| puts "#{f.lineno}: #{line}" }
- *
- * <em>produces:</em>
- *
- * 1: This is line one
- * 2: This is line two
- * 3: This is line three
- * 4: And so on...
- */
-
-static VALUE
-rb_io_each_line(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE str;
- VALUE rs;
-
- if (argc == 0) {
- rs = rb_rs;
- }
- else {
- rb_scan_args(argc, argv, "1", &rs);
- if (!NIL_P(rs)) StringValue(rs);
- }
- while (!NIL_P(str = rb_io_getline(rs, io))) {
- rb_yield(str);
- }
- return io;
-}
-
-/*
- * call-seq:
- * ios.each_byte {|byte| block } => ios
- *
- * Calls the given block once for each byte (0..255) in <em>ios</em>,
- * passing the byte as an argument. The stream must be opened for
- * reading or an <code>IOError</code> will be raised.
- *
- * f = File.new("testfile")
- * checksum = 0
- * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
- * checksum #=> 12
- */
-
-static VALUE
-rb_io_each_byte(io)
- VALUE io;
-{
- OpenFile *fptr;
- int c;
-
- GetOpenFile(io, fptr);
-
- for (;;) {
- rb_io_check_readable(fptr);
- READ_CHECK(fptr);
- c = io_getc(fptr);
- if (c < 0) {
- break;
- }
- rb_yield(INT2FIX(c & 0xff));
- }
- return io;
-}
-
-/*
- * call-seq:
- * ios.getc => fixnum or nil
- *
- * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
- * <code>nil</code> if called at end of file.
- *
- * f = File.new("testfile")
- * f.getc #=> 84
- * f.getc #=> 104
- */
-
-VALUE
-rb_io_getc(io)
- VALUE io;
-{
- OpenFile *fptr;
- int c;
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
-
- READ_CHECK(fptr);
- c = io_getc(fptr);
-
- if (c < 0) {
- return Qnil;
- }
- return INT2FIX(c & 0xff);
-}
-
-int
-rb_getc(f)
- FILE *f;
-{
- int c;
-
- if (!STDIO_READ_DATA_PENDING(f)) {
- rb_thread_wait_fd(fileno(f));
- }
- TRAP_BEG;
- c = getc(f);
- TRAP_END;
-
- return c;
-}
-
-/*
- * call-seq:
- * ios.readchar => fixnum
- *
- * Reads a character as with <code>IO#getc</code>, but raises an
- * <code>EOFError</code> on end of file.
- */
-
-static VALUE
-rb_io_readchar(io)
- VALUE io;
-{
- VALUE c = rb_io_getc(io);
-
- if (NIL_P(c)) {
- rb_eof_error();
- }
- return c;
-}
-
-/*
- * call-seq:
- * ios.ungetc(integer) => nil
- *
- * Pushes back one character (passed as a parameter) onto <em>ios</em>,
- * such that a subsequent buffered read will return it. Only one character
- * may be pushed back before a subsequent read operation (that is,
- * you will be able to read only the last of several characters that have been pushed
- * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
- *
- * f = File.new("testfile") #=> #<File:testfile>
- * c = f.getc #=> 84
- * f.ungetc(c) #=> nil
- * f.getc #=> 84
- */
-
-VALUE
-rb_io_ungetc(io, c)
- VALUE io, c;
-{
- OpenFile *fptr;
- int cc = NUM2INT(c);
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
-
- if (io_ungetc(cc, fptr) == EOF && cc != EOF) {
- rb_raise(rb_eIOError, "ungetc failed");
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * ios.isatty => true or false
- * ios.tty? => true or false
- *
- * Returns <code>true</code> if <em>ios</em> is associated with a
- * terminal device (tty), <code>false</code> otherwise.
- *
- * File.new("testfile").isatty #=> false
- * File.new("/dev/tty").isatty #=> true
- */
-
-static VALUE
-rb_io_isatty(io)
- VALUE io;
-{
- OpenFile *fptr;
-
- GetOpenFile(io, fptr);
- if (isatty(fptr->fd) == 0)
- return Qfalse;
- return Qtrue;
-}
-
-#define FMODE_PREP (1<<16)
-#define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
-#define PREP_STDIO_NAME(f) ((f)->path)
-
-static void
-fptr_finalize(fptr, noraise)
- OpenFile *fptr;
- int noraise;
-{
- if (fptr->wbuf_len) {
- io_fflush(fptr);
- }
- if (IS_PREP_STDIO(fptr) ||
- fptr->fd <= 2) {
- return;
- }
- if (fptr->stdio_file) {
- if (fclose(fptr->stdio_file) < 0 && !noraise) {
- /* fptr->stdio_file is deallocated anyway */
- fptr->stdio_file = 0;
- fptr->fd = -1;
- rb_sys_fail(fptr->path);
- }
- }
- else if (0 <= fptr->fd) {
- if (close(fptr->fd) < 0 && !noraise) {
- /* fptr->fd is still not closed */
- rb_sys_fail(fptr->path);
- }
- }
- fptr->fd = -1;
- fptr->stdio_file = 0;
- fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
-}
-
-static void
-rb_io_fptr_cleanup(fptr, noraise)
- OpenFile *fptr;
- int noraise;
-{
- if (fptr->finalize) {
- (*fptr->finalize)(fptr, noraise);
- }
- else {
- fptr_finalize(fptr, noraise);
- }
-}
-
-int
-rb_io_fptr_finalize(fptr)
- OpenFile *fptr;
-{
- if (!fptr) return 0;
- if (fptr->refcnt <= 0 || --fptr->refcnt) return 0;
- if (fptr->path) {
- free(fptr->path);
- fptr->path = 0;
- }
- if (0 <= fptr->fd)
- rb_io_fptr_cleanup(fptr, Qtrue);
- if (fptr->rbuf) {
- free(fptr->rbuf);
- fptr->rbuf = 0;
- }
- if (fptr->wbuf) {
- free(fptr->wbuf);
- fptr->wbuf = 0;
- }
- free(fptr);
- return 1;
-}
-
-VALUE
-rb_io_close(io)
- VALUE io;
-{
- OpenFile *fptr;
- int fd;
-
- fptr = RFILE(io)->fptr;
- if (!fptr) return Qnil;
- if (fptr->fd < 0) return Qnil;
-
- fd = fptr->fd;
- rb_io_fptr_cleanup(fptr, Qfalse);
- rb_thread_fd_close(fd);
-
- if (fptr->pid) {
- rb_syswait(fptr->pid);
- fptr->pid = 0;
- }
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * ios.close => nil
- *
- * Closes <em>ios</em> and flushes any pending writes to the operating
- * system. The stream is unavailable for any further data operations;
- * an <code>IOError</code> is raised if such an attempt is made. I/O
- * streams are automatically closed when they are claimed by the
- * garbage collector.
- */
-
-static VALUE
-rb_io_close_m(io)
- VALUE io;
-{
- if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
- rb_raise(rb_eSecurityError, "Insecure: can't close");
- }
- rb_io_check_closed(RFILE(io)->fptr);
- rb_io_close(io);
- return Qnil;
-}
-
-static VALUE
-io_close(io)
- VALUE io;
-{
- return rb_funcall(io, rb_intern("close"), 0, 0);
-}
-
-/*
- * call-seq:
- * ios.closed? => true or false
- *
- * Returns <code>true</code> if <em>ios</em> is completely closed (for
- * duplex streams, both reader and writer), <code>false</code>
- * otherwise.
- *
- * f = File.new("testfile")
- * f.close #=> nil
- * f.closed? #=> true
- * f = IO.popen("/bin/sh","r+")
- * f.close_write #=> nil
- * f.closed? #=> false
- * f.close_read #=> nil
- * f.closed? #=> true
- */
-
-
-static VALUE
-rb_io_closed(io)
- VALUE io;
-{
- OpenFile *fptr;
-
- fptr = RFILE(io)->fptr;
- rb_io_check_initialized(fptr);
- return 0 <= fptr->fd ? Qfalse : Qtrue;
-}
-
-/*
- * call-seq:
- * ios.close_read => nil
- *
- * Closes the read end of a duplex I/O stream (i.e., one that contains
- * both a read and a write stream, such as a pipe). Will raise an
- * <code>IOError</code> if the stream is not duplexed.
- *
- * f = IO.popen("/bin/sh","r+")
- * f.close_read
- * f.readlines
- *
- * <em>produces:</em>
- *
- * prog.rb:3:in `readlines': not opened for reading (IOError)
- * from prog.rb:3
- */
-
-static VALUE
-rb_io_close_read(io)
- VALUE io;
-{
- OpenFile *fptr;
-
- if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
- rb_raise(rb_eSecurityError, "Insecure: can't close");
- }
- GetOpenFile(io, fptr);
- if (is_socket(fptr->fd, fptr->path)) {
-#ifndef SHUT_RD
-# define SHUT_RD 0
-#endif
- if (shutdown(fptr->fd, SHUT_RD) < 0)
- rb_sys_fail(fptr->path);
- fptr->mode &= ~FMODE_READABLE;
- if (!(fptr->mode & FMODE_WRITABLE))
- return rb_io_close(io);
- return Qnil;
- }
- if (fptr->mode & FMODE_WRITABLE) {
- rb_raise(rb_eIOError, "closing non-duplex IO for reading");
- }
- return rb_io_close(io);
-}
-
-/*
- * call-seq:
- * ios.close_write => nil
- *
- * Closes the write end of a duplex I/O stream (i.e., one that contains
- * both a read and a write stream, such as a pipe). Will raise an
- * <code>IOError</code> if the stream is not duplexed.
- *
- * f = IO.popen("/bin/sh","r+")
- * f.close_write
- * f.print "nowhere"
- *
- * <em>produces:</em>
- *
- * prog.rb:3:in `write': not opened for writing (IOError)
- * from prog.rb:3:in `print'
- * from prog.rb:3
- */
-
-static VALUE
-rb_io_close_write(io)
- VALUE io;
-{
- OpenFile *fptr;
-
- if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
- rb_raise(rb_eSecurityError, "Insecure: can't close");
- }
- GetOpenFile(io, fptr);
- if (is_socket(fptr->fd, fptr->path)) {
-#ifndef SHUT_WR
-# define SHUT_WR 1
-#endif
- if (shutdown(fptr->fd, SHUT_WR) < 0)
- rb_sys_fail(fptr->path);
- fptr->mode &= ~FMODE_WRITABLE;
- if (!(fptr->mode & FMODE_READABLE))
- return rb_io_close(io);
- return Qnil;
- }
-
- if (fptr->mode & FMODE_READABLE) {
- rb_raise(rb_eIOError, "closing non-duplex IO for writing");
- }
- return rb_io_close(io);
-}
-
-/*
- * call-seq:
- * ios.sysseek(offset, whence=SEEK_SET) => integer
- *
- * Seeks to a given <i>offset</i> in the stream according to the value
- * of <i>whence</i> (see <code>IO#seek</code> for values of
- * <i>whence</i>). Returns the new offset into the file.
- *
- * f = File.new("testfile")
- * f.sysseek(-13, IO::SEEK_END) #=> 53
- * f.sysread(10) #=> "And so on."
- */
-
-static VALUE
-rb_io_sysseek(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE offset, ptrname;
- int whence = SEEK_SET;
- OpenFile *fptr;
- off_t pos;
-
- if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
- whence = NUM2INT(ptrname);
- }
- pos = NUM2OFFT(offset);
- GetOpenFile(io, fptr);
- if ((fptr->mode & FMODE_READABLE) && READ_DATA_BUFFERED(fptr)) {
- rb_raise(rb_eIOError, "sysseek for buffered IO");
- }
- if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf_len) {
- rb_warn("sysseek for buffered IO");
- }
- pos = lseek(fptr->fd, pos, whence);
- if (pos == -1) rb_sys_fail(fptr->path);
-
- return OFFT2NUM(pos);
-}
-
-/*
- * call-seq:
- * ios.syswrite(string) => integer
- *
- * Writes the given string to <em>ios</em> using a low-level write.
- * Returns the number of bytes written. Do not mix with other methods
- * that write to <em>ios</em> or you may get unpredictable results.
- * Raises <code>SystemCallError</code> on error.
- *
- * f = File.new("out", "w")
- * f.syswrite("ABCDEF") #=> 6
- */
-
-static VALUE
-rb_io_syswrite(io, str)
- VALUE io, str;
-{
- OpenFile *fptr;
- long n;
-
- rb_secure(4);
- if (TYPE(str) != T_STRING)
- str = rb_obj_as_string(str);
-
- GetOpenFile(io, fptr);
- rb_io_check_writable(fptr);
-
- if (fptr->wbuf_len) {
- rb_warn("syswrite for buffered IO");
- }
- if (!rb_thread_fd_writable(fptr->fd)) {
- rb_io_check_closed(fptr);
- }
- n = write(fptr->fd, RSTRING(str)->ptr, RSTRING(str)->len);
-
- if (n == -1) rb_sys_fail(fptr->path);
-
- return LONG2FIX(n);
-}
-
-/*
- * call-seq:
- * ios.sysread(integer[, outbuf]) => string
- *
- * Reads <i>integer</i> bytes from <em>ios</em> using a low-level
- * read and returns them as a string. Do not mix with other methods
- * that read from <em>ios</em> or you may get unpredictable results.
- * If the optional <i>outbuf</i> argument is present, it must reference
- * a String, which will receive the data.
- * Raises <code>SystemCallError</code> on error and
- * <code>EOFError</code> at end of file.
- *
- * f = File.new("testfile")
- * f.sysread(16) #=> "This is line one"
- */
-
-static VALUE
-rb_io_sysread(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE len, str;
- OpenFile *fptr;
- long n, ilen;
-
- rb_scan_args(argc, argv, "11", &len, &str);
- ilen = NUM2LONG(len);
-
- if (NIL_P(str)) {
- str = rb_str_new(0, ilen);
- }
- else {
- StringValue(str);
- rb_str_modify(str);
- rb_str_resize(str, ilen);
- }
- if (ilen == 0) return str;
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
-
- if (READ_DATA_BUFFERED(fptr)) {
- rb_raise(rb_eIOError, "sysread for buffered IO");
- }
-
- n = fptr->fd;
- rb_thread_wait_fd(fptr->fd);
- rb_io_check_closed(fptr);
- if (RSTRING(str)->len != ilen) {
- rb_raise(rb_eRuntimeError, "buffer string modified");
- }
- TRAP_BEG;
- n = read(fptr->fd, RSTRING(str)->ptr, ilen);
- TRAP_END;
-
- if (n == -1) {
- rb_sys_fail(fptr->path);
- }
- rb_str_resize(str, n);
- if (n == 0 && ilen > 0) {
- rb_eof_error();
- }
- RSTRING(str)->len = n;
- RSTRING(str)->ptr[n] = '\0';
- OBJ_TAINT(str);
-
- return str;
-}
-
-/*
- * call-seq:
- * ios.binmode => ios
- *
- * Puts <em>ios</em> into binary mode. This is useful only in
- * MS-DOS/Windows environments. Once a stream is in binary mode, it
- * cannot be reset to nonbinary mode.
- */
-
-VALUE
-rb_io_binmode(io)
- VALUE io;
-{
-#if defined(_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) || defined(__EMX__)
- OpenFile *fptr;
-
- GetOpenFile(io, fptr);
- if (!(fptr->mode & FMODE_BINMODE) && READ_DATA_BUFFERED(fptr)) {
- rb_raise(rb_eIOError, "buffer already filled with text-mode content");
- }
- if (0 <= fptr->fd && setmode(fptr->fd, O_BINARY) == -1)
- rb_sys_fail(fptr->path);
-
- fptr->mode |= FMODE_BINMODE;
-#endif
- return io;
-}
-
-static char*
-rb_io_flags_mode(flags)
- int flags;
-{
-#ifdef O_BINARY
-# define MODE_BINMODE(a,b) ((flags & FMODE_BINMODE) ? (b) : (a))
-#else
-# define MODE_BINMODE(a,b) (a)
-#endif
- if (flags & FMODE_APPEND) {
- if ((flags & FMODE_READWRITE) == FMODE_READWRITE) {
- return MODE_BINMODE("a+", "ab+");
- }
- return MODE_BINMODE("a", "ab");
- }
- switch (flags & FMODE_READWRITE) {
- case FMODE_READABLE:
- return MODE_BINMODE("r", "rb");
- case FMODE_WRITABLE:
- return MODE_BINMODE("w", "wb");
- case FMODE_READWRITE:
- if (flags & FMODE_CREATE) {
- return MODE_BINMODE("w+", "wb+");
- }
- return MODE_BINMODE("r+", "rb+");
- }
- rb_raise(rb_eArgError, "illegal access modenum %o", flags);
- return NULL; /* not reached */
-}
-
-int
-rb_io_mode_flags(mode)
- const char *mode;
-{
- int flags = 0;
- const char *m = mode;
-
- switch (*m++) {
- case 'r':
- flags |= FMODE_READABLE;
- break;
- case 'w':
- flags |= FMODE_WRITABLE | FMODE_CREATE;
- break;
- case 'a':
- flags |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
- break;
- default:
- error:
- rb_raise(rb_eArgError, "illegal access mode %s", mode);
- }
-
- while (*m) {
- switch (*m++) {
- case 'b':
- flags |= FMODE_BINMODE;
- break;
- case '+':
- flags |= FMODE_READWRITE;
- break;
- default:
- goto error;
- }
- }
-
- return flags;
-}
-
-int
-rb_io_modenum_flags(mode)
- int mode;
-{
- int flags = 0;
-
- switch (mode & (O_RDONLY|O_WRONLY|O_RDWR)) {
- case O_RDONLY:
- flags = FMODE_READABLE;
- break;
- case O_WRONLY:
- flags = FMODE_WRITABLE;
- break;
- case O_RDWR:
- flags = FMODE_READWRITE;
- break;
- }
-
- if (mode & O_APPEND) {
- flags |= FMODE_APPEND;
- }
- if (mode & O_CREAT) {
- flags |= FMODE_CREATE;
- }
-#ifdef O_BINARY
- if (mode & O_BINARY) {
- flags |= FMODE_BINMODE;
- }
-#endif
-
- return flags;
-}
-
-static int
-rb_io_mode_modenum(mode)
- const char *mode;
-{
- int flags = 0;
- const char *m = mode;
-
- switch (*m++) {
- case 'r':
- flags |= O_RDONLY;
- break;
- case 'w':
- flags |= O_WRONLY | O_CREAT | O_TRUNC;
- break;
- case 'a':
- flags |= O_WRONLY | O_CREAT | O_APPEND;
- break;
- default:
- error:
- rb_raise(rb_eArgError, "illegal access mode %s", mode);
- }
-
- while (*m) {
- switch (*m++) {
- case 'b':
-#ifdef O_BINARY
- flags |= O_BINARY;
-#endif
- break;
- case '+':
- flags = (flags & ~O_ACCMODE) | O_RDWR;
- break;
- default:
- goto error;
- }
- }
-
- return flags;
-}
-
-#define MODENUM_MAX 4
-
-static char*
-rb_io_modenum_mode(flags)
- int flags;
-{
-#ifdef O_BINARY
-# define MODE_BINARY(a,b) ((flags & O_BINARY) ? (b) : (a))
-#else
-# define MODE_BINARY(a,b) (a)
-#endif
- if (flags & O_APPEND) {
- if ((flags & O_RDWR) == O_RDWR) {
- return MODE_BINARY("a+", "ab+");
- }
- return MODE_BINARY("a", "ab");
- }
- switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) {
- case O_RDONLY:
- return MODE_BINARY("r", "rb");
- case O_WRONLY:
- return MODE_BINARY("w", "wb");
- case O_RDWR:
- return MODE_BINARY("r+", "rb+");
- }
- rb_raise(rb_eArgError, "illegal access modenum %o", flags);
- return NULL; /* not reached */
-}
-
-static int
-rb_sysopen(fname, flags, mode)
- char *fname;
- int flags;
- unsigned int mode;
-{
- int fd;
-
- fd = open(fname, flags, mode);
- if (fd < 0) {
- if (errno == EMFILE || errno == ENFILE) {
- rb_gc();
- fd = open(fname, flags, mode);
- }
- if (fd < 0) {
- rb_sys_fail(fname);
- }
- }
- return fd;
-}
-
-FILE *
-rb_fopen(fname, mode)
- const char *fname;
- const char *mode;
-{
- FILE *file;
-
- file = fopen(fname, mode);
- if (!file) {
- if (errno == EMFILE || errno == ENFILE) {
- rb_gc();
- file = fopen(fname, mode);
- }
- if (!file) {
- rb_sys_fail(fname);
- }
- }
-#ifdef USE_SETVBUF
- if (setvbuf(file, NULL, _IOFBF, 0) != 0)
- rb_warn("setvbuf() can't be honoured for %s", fname);
-#endif
-#ifdef __human68k__
- setmode(fileno(file), O_TEXT);
-#endif
- return file;
-}
-
-FILE *
-rb_fdopen(fd, mode)
- int fd;
- const char *mode;
-{
- FILE *file;
-
-#if defined(sun)
- errno = 0;
-#endif
- file = fdopen(fd, mode);
- if (!file) {
-#if defined(sun)
- if (errno == 0 || errno == EMFILE || errno == ENFILE) {
-#else
- if (errno == EMFILE || errno == ENFILE) {
-#endif
- rb_gc();
-#if defined(sun)
- errno = 0;
-#endif
- file = fdopen(fd, mode);
- }
- if (!file) {
-#ifdef _WIN32
- if (errno == 0) errno = EINVAL;
-#elif defined(sun)
- if (errno == 0) errno = EMFILE;
-#endif
- rb_sys_fail(0);
- }
- }
-
- /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
-#ifdef USE_SETVBUF
- if (setvbuf(file, NULL, _IOFBF, 0) != 0)
- rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
-#endif
- return file;
-}
-
-static void
-io_check_tty(OpenFile *fptr)
-{
- if (isatty(fptr->fd))
- fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
-}
-
-static VALUE
-rb_file_open_internal(io, fname, mode)
- VALUE io;
- const char *fname, *mode;
-{
- OpenFile *fptr;
-
- MakeOpenFile(io, fptr);
- fptr->mode = rb_io_mode_flags(mode);
- fptr->path = strdup(fname);
- fptr->fd = rb_sysopen(fptr->path, rb_io_mode_modenum(rb_io_flags_mode(fptr->mode)), 0666);
- io_check_tty(fptr);
-
- return io;
-}
-
-VALUE
-rb_file_open(fname, mode)
- const char *fname, *mode;
-{
- return rb_file_open_internal(io_alloc(rb_cFile), fname, mode);
-}
-
-static VALUE
-rb_file_sysopen_internal(io, fname, flags, mode)
- VALUE io;
- char *fname;
- int flags, mode;
-{
- OpenFile *fptr;
-
- MakeOpenFile(io, fptr);
-
- fptr->path = strdup(fname);
- fptr->mode = rb_io_modenum_flags(flags);
- fptr->fd = rb_sysopen(fptr->path, flags, mode);
- io_check_tty(fptr);
-
- return io;
-}
-
-VALUE
-rb_file_sysopen(fname, flags, mode)
- const char *fname;
- int flags, mode;
-{
- return rb_file_sysopen_internal(io_alloc(rb_cFile), fname, flags, mode);
-}
-
-#if defined(__CYGWIN__) || !defined(HAVE_FORK)
-static struct pipe_list {
- OpenFile *fptr;
- struct pipe_list *next;
-} *pipe_list;
-
-static void
-pipe_add_fptr(fptr)
- OpenFile *fptr;
-{
- struct pipe_list *list;
-
- list = ALLOC(struct pipe_list);
- list->fptr = fptr;
- list->next = pipe_list;
- pipe_list = list;
-}
-
-static void
-pipe_del_fptr(fptr)
- OpenFile *fptr;
-{
- struct pipe_list *list = pipe_list;
- struct pipe_list *tmp;
-
- if (list->fptr == fptr) {
- pipe_list = list->next;
- free(list);
- return;
- }
-
- while (list->next) {
- if (list->next->fptr == fptr) {
- tmp = list->next;
- list->next = list->next->next;
- free(tmp);
- return;
- }
- list = list->next;
- }
-}
-
-static void
-pipe_atexit _((void))
-{
- struct pipe_list *list = pipe_list;
- struct pipe_list *tmp;
-
- while (list) {
- tmp = list->next;
- rb_io_fptr_finalize(list->fptr);
- list = tmp;
- }
-}
-
-static void pipe_finalize _((OpenFile *fptr,int));
-
-static void
-pipe_finalize(fptr, noraise)
- OpenFile *fptr;
- int noraise;
-{
-#if !defined(HAVE_FORK) && !defined(_WIN32)
- extern VALUE rb_last_status;
- int status;
- if (fptr->stdio_file) {
- status = pclose(fptr->stdio_file);
- }
- fptr->fd = -1;
- fptr->stdio_file = 0;
-#if defined DJGPP
- status <<= 8;
-#endif
- rb_last_status = INT2FIX(status);
-#else
- fptr_finalize(fptr, noraise);
-#endif
- pipe_del_fptr(fptr);
-}
-#endif
-
-void
-rb_io_synchronized(fptr)
- OpenFile *fptr;
-{
- fptr->mode |= FMODE_SYNC;
-}
-
-void
-rb_io_unbuffered(fptr)
- OpenFile *fptr;
-{
- rb_io_synchronized(fptr);
-}
-
-struct popen_arg {
- struct rb_exec_arg exec;
- int modef;
- int pair[2];
-};
-
-static void
-popen_redirect(p)
- struct popen_arg *p;
-{
- if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
- close(p->pair[0]);
- dup2(p->pair[1], 0);
- dup2(p->pair[1], 1);
- if (2 <= p->pair[1])
- close(p->pair[1]);
- }
- else if (p->modef & FMODE_READABLE) {
- close(p->pair[0]);
- if (p->pair[1] != 1) {
- dup2(p->pair[1], 1);
- close(p->pair[1]);
- }
- }
- else {
- close(p->pair[1]);
- if (p->pair[0] != 0) {
- dup2(p->pair[0], 0);
- close(p->pair[0]);
- }
- }
-}
-
-#ifdef HAVE_FORK
-static int
-popen_exec(p)
- struct popen_arg *p;
-{
- int fd;
-
- popen_redirect(p);
- for (fd = 3; fd < NOFILE; fd++) {
-#ifdef FD_CLOEXEC
- fcntl(fd, F_SETFL, FD_CLOEXEC);
-#else
- close(fd);
-#endif
- }
- return rb_exec(&p->exec);
-}
-#endif
-
-static VALUE
-pipe_open(argc, argv, mode)
- int argc;
- VALUE *argv;
- char *mode;
-{
- int modef = rb_io_mode_flags(mode);
- int pid = 0;
- OpenFile *fptr;
- VALUE port, prog;
-#if defined(HAVE_FORK)
- int status;
- struct popen_arg arg;
- volatile int doexec;
-#elif defined(_WIN32)
- int openmode = rb_io_mode_modenum(mode);
- char *exename = NULL;
-#endif
- char *cmd;
- FILE *fp = 0;
- int fd = -1;
-
- prog = rb_check_argv(argc, argv);
- if (!prog) {
- if (argc == 1) argc = 0;
- prog = argv[0];
- }
-
-#if defined(HAVE_FORK)
- cmd = StringValueCStr(prog);
- doexec = (strcmp("-", cmd) != 0);
- if (!doexec) {
- fflush(stdin); /* is it really needed? */
- rb_io_flush(rb_stdout);
- rb_io_flush(rb_stderr);
- }
- arg.modef = modef;
- arg.pair[0] = arg.pair[1] = -1;
- if ((modef & FMODE_READABLE) && (modef & FMODE_WRITABLE)) {
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, arg.pair) < 0)
- rb_sys_fail(cmd);
- }
- else if (modef & FMODE_READABLE) {
- if (pipe(arg.pair) < 0)
- rb_sys_fail(cmd);
- }
- else if (modef & FMODE_WRITABLE) {
- if (pipe(arg.pair) < 0)
- rb_sys_fail(cmd);
- }
- else {
- rb_sys_fail(cmd);
- }
- if (doexec) {
- arg.exec.argc = argc;
- arg.exec.argv = argv;
- arg.exec.prog = cmd;
- pid = rb_fork(&status, popen_exec, &arg);
- }
- else {
- pid = rb_fork(&status, 0, 0);
- if (pid == 0) { /* child */
- popen_redirect(&arg);
- rb_io_synchronized(RFILE(orig_stdout)->fptr);
- rb_io_synchronized(RFILE(orig_stderr)->fptr);
- return Qnil;
- }
- }
-
- /* parent */
- if (pid == -1) {
- int e = errno;
- close(arg.pair[0]);
- close(arg.pair[1]);
- errno = e;
- rb_sys_fail(cmd);
- }
- if ((modef & FMODE_READABLE) && (modef & FMODE_WRITABLE)) {
- close(arg.pair[1]);
- fd = arg.pair[0];
- }
- else if (modef & FMODE_READABLE) {
- close(arg.pair[1]);
- fd = arg.pair[0];
- }
- else {
- close(arg.pair[0]);
- fd = arg.pair[1];
- }
-#elif defined(_WIN32)
- if (argc) {
- char **args = ALLOCA_N(char *, argc+1);
- int i;
-
- for (i = 0; i < argc; ++i) {
- args[i] = RSTRING(argv[i])->ptr;
- }
- args[i] = NULL;
- cmd = ALLOCA_N(char, rb_w32_argv_size(args));
- rb_w32_join_argv(cmd, args);
- exename = RSTRING(prog)->ptr;
- }
- else {
- cmd = StringValueCStr(prog);
- }
- while ((pid = rb_w32_pipe_exec(cmd, exename, openmode, &fd)) == -1) {
- /* exec failed */
- switch (errno) {
- case EAGAIN:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
-#endif
- rb_thread_sleep(1);
- break;
- default:
- rb_sys_fail(RSTRING(prog)->ptr);
- break;
- }
- }
-#else
- if (argc)
- prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
- fp = popen(StringValueCStr(prog), mode);
- if (!fp) rb_sys_fail(RSTRING(prog)->ptr);
- fd = fileno(fp);
-#endif
-
- port = io_alloc(rb_cIO);
- MakeOpenFile(port, fptr);
- fptr->fd = fd;
- fptr->stdio_file = fp;
- fptr->mode = modef | FMODE_SYNC|FMODE_DUPLEX;
- fptr->pid = pid;
-
-#if defined (__CYGWIN__) || !defined(HAVE_FORK)
- fptr->finalize = pipe_finalize;
- pipe_add_fptr(fptr);
-#endif
- return port;
-}
-
-/*
- * call-seq:
- * IO.popen(cmd, mode="r") => io
- * IO.popen(cmd, mode="r") {|io| block } => obj
- *
- * Runs the specified command as a subprocess; the subprocess's
- * standard input and output will be connected to the returned
- * <code>IO</code> object. If _cmd_ is a +String+
- * ``<code>-</code>'', then a new instance of Ruby is started as the
- * subprocess. If <i>cmd</i> is an +Array+ of +String+, then it will
- * be used as the subprocess's +argv+ bypassing a shell. The default
- * mode for the new file object is ``r'', but <i>mode</i> may be set
- * to any of the modes listed in the description for class IO.
- *
- * Raises exceptions which <code>IO::pipe</code> and
- * <code>Kernel::system</code> raise.
- *
- * If a block is given, Ruby will run the command as a child connected
- * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
- * parameter to the block. In this case <code>IO::popen</code> returns
- * the value of the block.
- *
- * If a block is given with a _cmd_ of ``<code>-</code>'',
- * the block will be run in two separate processes: once in the parent,
- * and once in a child. The parent process will be passed the pipe
- * object as a parameter to the block, the child version of the block
- * will be passed <code>nil</code>, and the child's standard in and
- * standard out will be connected to the parent through the pipe. Not
- * available on all platforms.
- *
- * f = IO.popen("uname")
- * p f.readlines
- * puts "Parent is #{Process.pid}"
- * IO.popen("date") { |f| puts f.gets }
- * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f}"}
- * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
- * f.puts "bar"; f.close_write; puts f.gets
- * }
- *
- * <em>produces:</em>
- *
- * ["Linux\n"]
- * Parent is 26166
- * Wed Apr 9 08:53:52 CDT 2003
- * 26169 is here, f is
- * 26166 is here, f is #<IO:0x401b3d44>
- * <foo>bar;zot;
- */
-
-static VALUE
-rb_io_s_popen(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- char *mode;
- VALUE pname, pmode, port, tmp;
-
- if (rb_scan_args(argc, argv, "11", &pname, &pmode) == 1) {
- mode = "r";
- }
- else if (FIXNUM_P(pmode)) {
- mode = rb_io_modenum_mode(FIX2INT(pmode));
- }
- else {
- mode = rb_io_flags_mode(rb_io_mode_flags(StringValuePtr(pmode)));
- }
- tmp = rb_check_array_type(pname);
- if (!NIL_P(tmp)) {
- VALUE *argv = ALLOCA_N(VALUE, RARRAY(tmp)->len);
-
- MEMCPY(argv, RARRAY(tmp)->ptr, VALUE, RARRAY(tmp)->len);
- port = pipe_open(RARRAY(tmp)->len, argv, mode);
- pname = tmp;
- }
- else {
- SafeStringValue(pname);
- port = pipe_open(1, &pname, mode);
- }
- if (NIL_P(port)) {
- /* child */
- if (rb_block_given_p()) {
- rb_yield(Qnil);
- rb_io_flush(rb_stdout);
- rb_io_flush(rb_stderr);
- _exit(0);
- }
- return Qnil;
- }
- RBASIC(port)->klass = klass;
- if (rb_block_given_p()) {
- return rb_ensure(rb_yield, port, io_close, port);
- }
- return port;
-}
-
-static VALUE
-rb_open_file(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE fname, vmode, perm;
- char *mode;
- int flags, fmode;
-
- rb_scan_args(argc, argv, "12", &fname, &vmode, &perm);
- FilePathValue(fname);
-
- if (FIXNUM_P(vmode) || !NIL_P(perm)) {
- if (FIXNUM_P(vmode)) {
- flags = FIX2INT(vmode);
- }
- else {
- SafeStringValue(vmode);
- flags = rb_io_mode_modenum(RSTRING(vmode)->ptr);
- }
- fmode = NIL_P(perm) ? 0666 : NUM2INT(perm);
-
- rb_file_sysopen_internal(io, RSTRING(fname)->ptr, flags, fmode);
- }
- else {
- mode = NIL_P(vmode) ? "r" : StringValuePtr(vmode);
- rb_file_open_internal(io, RSTRING(fname)->ptr, mode);
- }
- return io;
-}
-
-/*
- * call-seq:
- * IO.open(fd, mode_string="r" ) => io
- * IO.open(fd, mode_string="r" ) {|io| block } => obj
- *
- * With no associated block, <code>open</code> is a synonym for
- * <code>IO::new</code>. If the optional code block is given, it will
- * be passed <i>io</i> as an argument, and the IO object will
- * automatically be closed when the block terminates. In this instance,
- * <code>IO::open</code> returns the value of the block.
- *
- */
-
-static VALUE
-rb_io_s_open(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE io = rb_class_new_instance(argc, argv, klass);
-
- if (rb_block_given_p()) {
- return rb_ensure(rb_yield, io, io_close, io);
- }
-
- return io;
-}
-
-/*
- * call-seq:
- * IO.sysopen(path, [mode, [perm]]) => fixnum
- *
- * Opens the given path, returning the underlying file descriptor as a
- * <code>Fixnum</code>.
- *
- * IO.sysopen("testfile") #=> 3
- *
- */
-
-static VALUE
-rb_io_s_sysopen(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE fname, vmode, perm;
- int flags, fmode, fd;
- char *path;
-
- rb_scan_args(argc, argv, "12", &fname, &vmode, &perm);
- FilePathValue(fname);
-
- if (NIL_P(vmode)) flags = O_RDONLY;
- else if (FIXNUM_P(vmode)) flags = FIX2INT(vmode);
- else {
- SafeStringValue(vmode);
- flags = rb_io_mode_modenum(RSTRING(vmode)->ptr);
- }
- if (NIL_P(perm)) fmode = 0666;
- else fmode = NUM2INT(perm);
-
- path = ALLOCA_N(char, strlen(RSTRING(fname)->ptr)+1);
- strcpy(path, RSTRING(fname)->ptr);
- fd = rb_sysopen(path, flags, fmode);
- return INT2NUM(fd);
-}
-
-/*
- * call-seq:
- * open(path [, mode [, perm]] ) => io or nil
- * open(path [, mode [, perm]] ) {|io| block } => obj
- *
- * Creates an <code>IO</code> object connected to the given stream,
- * file, or subprocess.
- *
- * If <i>path</i> does not start with a pipe character
- * (``<code>|</code>''), treat it as the name of a file to open using
- * the specified mode (defaulting to ``<code>r</code>''). (See the table
- * of valid modes on page 331.) If a file is being created, its initial
- * permissions may be set using the integer third parameter.
- *
- * If a block is specified, it will be invoked with the
- * <code>File</code> object as a parameter, and the file will be
- * automatically closed when the block terminates. The call
- * returns the value of the block.
- *
- * If <i>path</i> starts with a pipe character, a subprocess is
- * created, connected to the caller by a pair of pipes. The returned
- * <code>IO</code> object may be used to write to the standard input
- * and read from the standard output of this subprocess. If the command
- * following the ``<code>|</code>'' is a single minus sign, Ruby forks,
- * and this subprocess is connected to the parent. In the subprocess,
- * the <code>open</code> call returns <code>nil</code>. If the command
- * is not ``<code>-</code>'', the subprocess runs the command. If a
- * block is associated with an <code>open("|-")</code> call, that block
- * will be run twice---once in the parent and once in the child. The
- * block parameter will be an <code>IO</code> object in the parent and
- * <code>nil</code> in the child. The parent's <code>IO</code> object
- * will be connected to the child's <code>$stdin</code> and
- * <code>$stdout</code>. The subprocess will be terminated at the end
- * of the block.
- *
- * open("testfile") do |f|
- * print f.gets
- * end
- *
- * <em>produces:</em>
- *
- * This is line one
- *
- * Open a subprocess and read its output:
- *
- * cmd = open("|date")
- * print cmd.gets
- * cmd.close
- *
- * <em>produces:</em>
- *
- * Wed Apr 9 08:56:31 CDT 2003
- *
- * Open a subprocess running the same Ruby program:
- *
- * f = open("|-", "w+")
- * if f == nil
- * puts "in Child"
- * exit
- * else
- * puts "Got: #{f.gets}"
- * end
- *
- * <em>produces:</em>
- *
- * Got: in Child
- *
- * Open a subprocess using a block to receive the I/O object:
- *
- * open("|-") do |f|
- * if f == nil
- * puts "in Child"
- * else
- * puts "Got: #{f.gets}"
- * end
- * end
- *
- * <em>produces:</em>
- *
- * Got: in Child
- */
-
-static VALUE
-rb_f_open(argc, argv)
- int argc;
- VALUE *argv;
-{
- if (argc >= 1) {
- ID to_open = rb_intern("to_open");
-
- if (rb_respond_to(argv[0], to_open)) {
- VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);
-
- if (rb_block_given_p()) {
- return rb_ensure(rb_yield, io, io_close, io);
- }
- return io;
- }
- else {
- VALUE tmp = rb_check_string_type(argv[0]);
- if (!NIL_P(tmp)) {
- char *str = StringValuePtr(tmp);
- if (str && str[0] == '|') {
- argv[0] = rb_str_new(str+1, RSTRING(tmp)->len-1);
- OBJ_INFECT(argv[0], tmp);
- return rb_io_s_popen(argc, argv, rb_cIO);
- }
- }
- }
- }
- return rb_io_s_open(argc, argv, rb_cFile);
-}
-
-static VALUE
-rb_io_open(fname, mode)
- char *fname, *mode;
-{
- if (fname[0] == '|') {
- VALUE cmd = rb_str_new2(fname+1);
- return pipe_open(1, &cmd, mode);
- }
- else {
- return rb_file_open(fname, mode);
- }
-}
-
-static VALUE
-io_reopen(io, nfile)
- VALUE io, nfile;
-{
- OpenFile *fptr, *orig;
- int fd, fd2;
- off_t pos = 0;
-
- nfile = rb_io_get_io(nfile);
- if (rb_safe_level() >= 4 && (!OBJ_TAINTED(io) || !OBJ_TAINTED(nfile))) {
- rb_raise(rb_eSecurityError, "Insecure: can't reopen");
- }
- GetOpenFile(io, fptr);
- GetOpenFile(nfile, orig);
-
- if (fptr == orig) return io;
-#if !defined __CYGWIN__
- if (IS_PREP_STDIO(fptr)) {
- if ((fptr->mode & FMODE_READWRITE) != (orig->mode & FMODE_READWRITE)) {
- rb_raise(rb_eArgError,
- "%s can't change access mode from \"%s\" to \"%s\"",
- PREP_STDIO_NAME(fptr), rb_io_flags_mode(fptr->mode),
- rb_io_flags_mode(orig->mode));
- }
- }
-#endif
- if (orig->mode & FMODE_READABLE) {
- pos = io_tell(orig);
- }
- if (orig->mode & FMODE_WRITABLE) {
- io_fflush(orig);
- }
- if (fptr->mode & FMODE_WRITABLE) {
- io_fflush(fptr);
- }
-
- /* copy OpenFile structure */
- fptr->mode = orig->mode;
- fptr->pid = orig->pid;
- fptr->lineno = orig->lineno;
- if (fptr->path) free(fptr->path);
- if (orig->path) fptr->path = strdup(orig->path);
- else fptr->path = 0;
- fptr->finalize = orig->finalize;
-
- fd = fptr->fd;
- fd2 = orig->fd;
- if (fd != fd2) {
-#if !defined __CYGWIN__
- if (IS_PREP_STDIO(fptr)) {
- /* need to keep stdio objects */
- if (dup2(fd2, fd) < 0)
- rb_sys_fail(orig->path);
- }
- else {
-#endif
- if (fptr->stdio_file)
- fclose(fptr->stdio_file);
- else
- close(fptr->fd);
- fptr->stdio_file = 0;
- fptr->fd = -1;
- if (dup2(fd2, fd) < 0)
- rb_sys_fail(orig->path);
- fptr->fd = fd;
-#if !defined __CYGWIN__
- }
-#endif
- rb_thread_fd_close(fd);
- if ((orig->mode & FMODE_READABLE) && pos >= 0) {
- if (io_seek(fptr, pos, SEEK_SET) < 0) {
- rb_sys_fail(fptr->path);
- }
- if (io_seek(orig, pos, SEEK_SET) < 0) {
- rb_sys_fail(orig->path);
- }
- }
- }
-
- if (fptr->mode & FMODE_BINMODE) {
- rb_io_binmode(io);
- }
-
- RBASIC(io)->klass = RBASIC(nfile)->klass;
- return io;
-}
-
-/*
- * call-seq:
- * ios.reopen(other_IO) => ios
- * ios.reopen(path, mode_str) => ios
- *
- * Reassociates <em>ios</em> with the I/O stream given in
- * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
- * dynamically change the actual class of this stream.
- *
- * f1 = File.new("testfile")
- * f2 = File.new("testfile")
- * f2.readlines[0] #=> "This is line one\n"
- * f2.reopen(f1) #=> #<File:testfile>
- * f2.readlines[0] #=> "This is line one\n"
- */
-
-static VALUE
-rb_io_reopen(argc, argv, file)
- int argc;
- VALUE *argv;
- VALUE file;
-{
- VALUE fname, nmode;
- char *mode;
- OpenFile *fptr;
-
- rb_secure(4);
- if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
- VALUE tmp = rb_io_check_io(fname);
- if (!NIL_P(tmp)) {
- return io_reopen(file, tmp);
- }
- }
-
- FilePathValue(fname);
- rb_io_taint_check(file);
- fptr = RFILE(file)->fptr;
- if (!fptr) {
- fptr = RFILE(file)->fptr = ALLOC(OpenFile);
- MEMZERO(fptr, OpenFile, 1);
- }
-
- if (!NIL_P(nmode)) {
- int flags = rb_io_mode_flags(StringValuePtr(nmode));
- if (IS_PREP_STDIO(fptr) &&
- (fptr->mode & FMODE_READWRITE) != (flags & FMODE_READWRITE)) {
- rb_raise(rb_eArgError,
- "%s can't change access mode from \"%s\" to \"%s\"",
- PREP_STDIO_NAME(fptr), rb_io_flags_mode(fptr->mode),
- rb_io_flags_mode(flags));
- }
- fptr->mode = flags;
- }
-
- if (fptr->path) {
- free(fptr->path);
- fptr->path = 0;
- }
-
- fptr->path = strdup(RSTRING(fname)->ptr);
- mode = rb_io_flags_mode(fptr->mode);
- if (fptr->fd < 0) {
- fptr->fd = rb_sysopen(fptr->path, rb_io_mode_modenum(mode), 0666);
- fptr->stdio_file = 0;
- return file;
- }
-
- if (fptr->stdio_file) {
- if (freopen(RSTRING(fname)->ptr, mode, fptr->stdio_file) == 0) {
- rb_sys_fail(fptr->path);
- }
- fptr->fd = fileno(fptr->stdio_file);
-#ifdef USE_SETVBUF
- if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
- rb_warn("setvbuf() can't be honoured for %s", RSTRING(fname)->ptr);
-#endif
- }
- else {
- if (close(fptr->fd) < 0)
- rb_sys_fail(fptr->path);
- fptr->fd = -1;
- fptr->fd = rb_sysopen(fptr->path, rb_io_mode_modenum(mode), 0666);
- }
-
- return file;
-}
-
-/* :nodoc: */
-static VALUE
-rb_io_init_copy(dest, io)
- VALUE dest, io;
-{
- OpenFile *fptr, *orig;
- int fd;
-
- io = rb_io_get_io(io);
- if (dest == io) return dest;
- GetOpenFile(io, orig);
- MakeOpenFile(dest, fptr);
-
- rb_io_flush(io);
-
- /* copy OpenFile structure */
- fptr->mode = orig->mode;
- fptr->pid = orig->pid;
- fptr->lineno = orig->lineno;
- if (orig->path) fptr->path = strdup(orig->path);
- fptr->finalize = orig->finalize;
-
- fd = ruby_dup(orig->fd);
- fptr->fd = fd;
- io_seek(fptr, io_tell(orig), SEEK_SET);
- if (fptr->mode & FMODE_BINMODE) {
- rb_io_binmode(dest);
- }
-
- return dest;
-}
-
-/*
- * call-seq:
- * ios.printf(format_string [, obj, ...] ) => nil
- *
- * Formats and writes to <em>ios</em>, converting parameters under
- * control of the format string. See <code>Kernel#sprintf</code>
- * for details.
- */
-
-VALUE
-rb_io_printf(argc, argv, out)
- int argc;
- VALUE argv[];
- VALUE out;
-{
- rb_io_write(out, rb_f_sprintf(argc, argv));
- return Qnil;
-}
-
-/*
- * call-seq:
- * printf(io, string [, obj ... ] ) => nil
- * printf(string [, obj ... ] ) => nil
- *
- * Equivalent to:
- * io.write(sprintf(string, obj, ...)
- * or
- * $stdout.write(sprintf(string, obj, ...)
- */
-
-static VALUE
-rb_f_printf(argc, argv)
- int argc;
- VALUE argv[];
-{
- VALUE out;
-
- if (argc == 0) return Qnil;
- if (TYPE(argv[0]) == T_STRING) {
- out = rb_stdout;
- }
- else {
- out = argv[0];
- argv++;
- argc--;
- }
- rb_io_write(out, rb_f_sprintf(argc, argv));
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * ios.print() => nil
- * ios.print(obj, ...) => nil
- *
- * Writes the given object(s) to <em>ios</em>. The stream must be
- * opened for writing. If the output record separator (<code>$\</code>)
- * is not <code>nil</code>, it will be appended to the output. If no
- * arguments are given, prints <code>$_</code>. Objects that aren't
- * strings will be converted by calling their <code>to_s</code> method.
- * With no argument, prints the contents of the variable <code>$_</code>.
- * Returns <code>nil</code>.
- *
- * $stdout.print("This is ", 100, " percent.\n")
- *
- * <em>produces:</em>
- *
- * This is 100 percent.
- */
-
-VALUE
-rb_io_print(argc, argv, out)
- int argc;
- VALUE *argv;
- VALUE out;
-{
- int i;
- VALUE line;
-
- /* if no argument given, print `$_' */
- if (argc == 0) {
- argc = 1;
- line = rb_lastline_get();
- argv = &line;
- }
- for (i=0; i<argc; i++) {
- if (!NIL_P(rb_output_fs) && i>0) {
- rb_io_write(out, rb_output_fs);
- }
- switch (TYPE(argv[i])) {
- case T_NIL:
- rb_io_write(out, rb_str_new2("nil"));
- break;
- default:
- rb_io_write(out, argv[i]);
- break;
- }
- }
- if (!NIL_P(rb_output_rs)) {
- rb_io_write(out, rb_output_rs);
- }
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * print(obj, ...) => nil
- *
- * Prints each object in turn to <code>$stdout</code>. If the output
- * field separator (<code>$,</code>) is not +nil+, its
- * contents will appear between each field. If the output record
- * separator (<code>$\</code>) is not +nil+, it will be
- * appended to the output. If no arguments are given, prints
- * <code>$_</code>. Objects that aren't strings will be converted by
- * calling their <code>to_s</code> method.
- *
- * print "cat", [1,2,3], 99, "\n"
- * $, = ", "
- * $\ = "\n"
- * print "cat", [1,2,3], 99
- *
- * <em>produces:</em>
- *
- * cat12399
- * cat, 1, 2, 3, 99
- */
-
-static VALUE
-rb_f_print(argc, argv)
- int argc;
- VALUE *argv;
-{
- rb_io_print(argc, argv, rb_stdout);
- return Qnil;
-}
-
-/*
- * call-seq:
- * ios.putc(obj) => obj
- *
- * If <i>obj</i> is <code>Numeric</code>, write the character whose
- * code is <i>obj</i>, otherwise write the first character of the
- * string representation of <i>obj</i> to <em>ios</em>.
- *
- * $stdout.putc "A"
- * $stdout.putc 65
- *
- * <em>produces:</em>
- *
- * AA
- */
-
-static VALUE
-rb_io_putc(io, ch)
- VALUE io, ch;
-{
- char c = NUM2CHR(ch);
-
- rb_io_write(io, rb_str_new(&c, 1));
- return ch;
-}
-
-/*
- * call-seq:
- * putc(int) => int
- *
- * Equivalent to:
- *
- * $stdout.putc(int)
- */
-
-static VALUE
-rb_f_putc(recv, ch)
- VALUE recv, ch;
-{
- return rb_io_putc(rb_stdout, ch);
-}
-
-static VALUE
-io_puts_ary(ary, out, recur)
- VALUE ary, out;
-{
- VALUE tmp;
- long i;
-
- for (i=0; i<RARRAY(ary)->len; i++) {
- tmp = RARRAY(ary)->ptr[i];
- if (recur) {
- tmp = rb_str_new2("[...]");
- }
- rb_io_puts(1, &tmp, out);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * ios.puts(obj, ...) => nil
- *
- * Writes the given objects to <em>ios</em> as with
- * <code>IO#print</code>. Writes a record separator (typically a
- * newline) after any that do not already end with a newline sequence.
- * If called with an array argument, writes each element on a new line.
- * If called without arguments, outputs a single record separator.
- *
- * $stdout.puts("this", "is", "a", "test")
- *
- * <em>produces:</em>
- *
- * this
- * is
- * a
- * test
- */
-
-VALUE
-rb_io_puts(argc, argv, out)
- int argc;
- VALUE *argv;
- VALUE out;
-{
- int i;
- VALUE line;
-
- /* if no argument given, print newline. */
- if (argc == 0) {
- rb_io_write(out, rb_default_rs);
- return Qnil;
- }
- for (i=0; i<argc; i++) {
- if (NIL_P(argv[i])) {
- line = rb_str_new2("nil");
- }
- else {
- line = rb_check_array_type(argv[i]);
- if (!NIL_P(line)) {
- rb_exec_recursive(io_puts_ary, line, out);
- continue;
- }
- line = rb_obj_as_string(argv[i]);
- }
- rb_io_write(out, line);
- if (RSTRING(line)->len == 0 ||
- RSTRING(line)->ptr[RSTRING(line)->len-1] != '\n') {
- rb_io_write(out, rb_default_rs);
- }
- }
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * puts(obj, ...) => nil
- *
- * Equivalent to
- *
- * $stdout.puts(obj, ...)
- */
-
-static VALUE
-rb_f_puts(argc, argv)
- int argc;
- VALUE *argv;
-{
- rb_io_puts(argc, argv, rb_stdout);
- return Qnil;
-}
-
-void
-rb_p(obj) /* for debug print within C code */
- VALUE obj;
-{
- rb_io_write(rb_stdout, rb_obj_as_string(rb_inspect(obj)));
- rb_io_write(rb_stdout, rb_default_rs);
-}
-
-/*
- * call-seq:
- * p(obj, ...) => nil
- *
- * For each object, directly writes
- * _obj_.+inspect+ followed by the current output
- * record separator to the program's standard output.
- *
- * S = Struct.new(:name, :state)
- * s = S['dave', 'TX']
- * p s
- *
- * <em>produces:</em>
- *
- * #<S name="dave", state="TX">
- */
-
-static VALUE
-rb_f_p(argc, argv)
- int argc;
- VALUE *argv;
-{
- int i;
-
- for (i=0; i<argc; i++) {
- rb_p(argv[i]);
- }
- if (TYPE(rb_stdout) == T_FILE) {
- rb_io_flush(rb_stdout);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * obj.display(port=$>) => nil
- *
- * Prints <i>obj</i> on the given port (default <code>$></code>).
- * Equivalent to:
- *
- * def display(port=$>)
- * port.write self
- * end
- *
- * For example:
- *
- * 1.display
- * "cat".display
- * [ 4, 5, 6 ].display
- * puts
- *
- * <em>produces:</em>
- *
- * 1cat456
- */
-
-static VALUE
-rb_obj_display(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE out;
-
- if (rb_scan_args(argc, argv, "01", &out) == 0) {
- out = rb_stdout;
- }
-
- rb_io_write(out, self);
-
- return Qnil;
-}
-
-void
-rb_write_error2(mesg, len)
- const char *mesg;
- long len;
-{
- rb_io_write(rb_stderr, rb_str_new(mesg, len));
-}
-
-void
-rb_write_error(mesg)
- const char *mesg;
-{
- rb_write_error2(mesg, strlen(mesg));
-}
-
-static void
-must_respond_to(mid, val, id)
- ID mid;
- VALUE val;
- ID id;
-{
- if (!rb_respond_to(val, mid)) {
- rb_raise(rb_eTypeError, "%s must have %s method, %s given",
- rb_id2name(id), rb_id2name(mid),
- rb_obj_classname(val));
- }
-}
-
-static void
-stdout_setter(val, id, variable)
- VALUE val;
- ID id;
- VALUE *variable;
-{
- must_respond_to(id_write, val, id);
- *variable = val;
-}
-
-static void
-defout_setter(val, id, variable)
- VALUE val;
- ID id;
- VALUE *variable;
-{
- stdout_setter(val, id, variable);
- rb_warn("$defout is obsolete; use $stdout instead");
-}
-
-static void
-deferr_setter(val, id, variable)
- VALUE val;
- ID id;
- VALUE *variable;
-{
- stdout_setter(val, id, variable);
- rb_warn("$deferr is obsolete; use $stderr instead");
-}
-
-static VALUE
-prep_io(fd, mode, klass, path)
- int fd;
- int mode;
- VALUE klass;
- const char *path;
-{
- OpenFile *fp;
- VALUE io = io_alloc(klass);
-
- MakeOpenFile(io, fp);
- fp->fd = fd;
-#ifdef __CYGWIN__
- if (!isatty(fd)) {
- mode |= O_BINARY;
- setmode(fd, O_BINARY);
- }
-#endif
- fp->mode = mode;
- io_check_tty(fp);
- if (path) fp->path = strdup(path);
-
- return io;
-}
-
-static VALUE
-prep_stdio(f, mode, klass, path)
- FILE *f;
- int mode;
- VALUE klass;
- const char *path;
-{
- OpenFile *fptr;
- VALUE io = prep_io(fileno(f), mode|FMODE_PREP, klass, path);
-
- GetOpenFile(io, fptr);
- fptr->stdio_file = f;
-
- return io;
-}
-
-FILE *rb_io_stdio_file(OpenFile *fptr)
-{
- if (!fptr->stdio_file) {
- fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_flags_mode(fptr->mode));
- }
- return fptr->stdio_file;
-}
-
-/*
- * call-seq:
- * IO.new(fd, mode) => io
- *
- * Returns a new <code>IO</code> object (a stream) for the given
- * <code>IO</code> object or integer file descriptor and mode
- * string. See also <code>IO#fileno</code> and
- * <code>IO::for_fd</code>.
- *
- * puts IO.new($stdout).fileno # => 1
- *
- * a = IO.new(2,"w") # '2' is standard error
- * $stderr.puts "Hello"
- * a.puts "World"
- *
- * <em>produces:</em>
- *
- * Hello
- * World
- */
-
-static VALUE
-rb_io_initialize(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE fnum, mode, orig;
- OpenFile *fp, *ofp = NULL;
- int fd, flags, fmode;
-
- rb_secure(4);
- rb_scan_args(argc, argv, "11", &fnum, &mode);
- if (argc == 2) {
- if (FIXNUM_P(mode)) {
- flags = FIX2LONG(mode);
- }
- else {
- SafeStringValue(mode);
- flags = rb_io_mode_modenum(RSTRING(mode)->ptr);
- }
- }
- orig = rb_io_check_io(fnum);
- if (NIL_P(orig)) {
- fd = NUM2INT(fnum);
- if (argc != 2) {
-#if defined(HAVE_FCNTL) && defined(F_GETFL)
- flags = fcntl(fd, F_GETFL);
- if (flags == -1) rb_sys_fail(0);
-#else
- flags = O_RDONLY;
-#endif
- }
- MakeOpenFile(io, fp);
- fp->fd = fd;
- fp->mode = rb_io_modenum_flags(flags);
- io_check_tty(fp);
- }
- else if (RFILE(io)->fptr) {
- rb_raise(rb_eRuntimeError, "reinitializing IO");
- }
- else {
- GetOpenFile(orig, ofp);
- if (ofp->refcnt == LONG_MAX) {
- VALUE s = rb_inspect(orig);
- rb_raise(rb_eIOError, "too many shared IO for %s", StringValuePtr(s));
- }
- if (argc == 2) {
- fmode = rb_io_modenum_flags(flags);
- if ((ofp->mode ^ fmode) & (FMODE_READWRITE|FMODE_BINMODE)) {
- if (FIXNUM_P(mode)) {
- rb_raise(rb_eArgError, "incompatible mode 0%o", flags);
- }
- else {
- rb_raise(rb_eArgError, "incompatible mode \"%s\"", RSTRING(mode)->ptr);
- }
- }
- }
- ofp->refcnt++;
- RFILE(io)->fptr = ofp;
- }
-
- return io;
-}
-
-
-/*
- * call-seq:
- * File.new(filename, mode="r") => file
- * File.new(filename [, mode [, perm]]) => file
- *
-
- * Opens the file named by _filename_ according to
- * _mode_ (default is ``r'') and returns a new
- * <code>File</code> object. See the description of class +IO+ for
- * a description of _mode_. The file mode may optionally be
- * specified as a +Fixnum+ by _or_-ing together the
- * flags (O_RDONLY etc, again described under +IO+). Optional
- * permission bits may be given in _perm_. These mode and permission
- * bits are platform dependent; on Unix systems, see
- * <code>open(2)</code> for details.
- *
- * f = File.new("testfile", "r")
- * f = File.new("newfile", "w+")
- * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
- */
-
-static VALUE
-rb_file_initialize(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- if (RFILE(io)->fptr) {
- rb_raise(rb_eRuntimeError, "reinitializing File");
- }
- if (0 < argc && argc < 3) {
- VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");
-
- if (!NIL_P(fd)) {
- argv[0] = fd;
- return rb_io_initialize(argc, argv, io);
- }
- }
- rb_open_file(argc, argv, io);
-
- return io;
-}
-
-/*
- * call-seq:
- * IO.new(fd, mode_string) => io
- *
- * Returns a new <code>IO</code> object (a stream) for the given
- * integer file descriptor and mode string. See also
- * <code>IO#fileno</code> and <code>IO::for_fd</code>.
- *
- * a = IO.new(2,"w") # '2' is standard error
- * $stderr.puts "Hello"
- * a.puts "World"
- *
- * <em>produces:</em>
- *
- * Hello
- * World
- */
-
-static VALUE
-rb_io_s_new(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- if (rb_block_given_p()) {
- char *cname = rb_class2name(klass);
-
- rb_warn("%s::new() does not take block; use %s::open() instead",
- cname, cname);
- }
- return rb_class_new_instance(argc, argv, klass);
-}
-
-
-/*
- * call-seq:
- * IO.for_fd(fd, mode) => io
- *
- * Synonym for <code>IO::new</code>.
- *
- */
-
-static VALUE
-rb_io_s_for_fd(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE io = rb_obj_alloc(klass);
- rb_io_initialize(argc, argv, io);
- return io;
-}
-
-static int binmode = 0;
-
-static VALUE
-argf_forward(argc, argv)
- int argc;
- VALUE *argv;
-{
- return rb_funcall3(current_file, rb_frame_this_func(), argc, argv);
-}
-
-#define ARGF_FORWARD(argc, argv) do {\
- if (TYPE(current_file) != T_FILE)\
- return argf_forward(argc, argv);\
-} while (0)
-#define NEXT_ARGF_FORWARD(argc, argv) do {\
- if (!next_argv()) return Qnil;\
- ARGF_FORWARD(argc, argv);\
-} while (0)
-
-static void
-argf_close(file)
- VALUE file;
-{
- if (TYPE(file) == T_FILE)
- rb_io_close(file);
- else
- rb_funcall3(file, rb_intern("close"), 0, 0);
-}
-
-static int
-next_argv()
-{
- extern VALUE rb_argv;
- char *fn;
- OpenFile *fptr;
- int stdout_binmode = 0;
-
- if (TYPE(rb_stdout) == T_FILE) {
- GetOpenFile(rb_stdout, fptr);
- if (fptr->mode & FMODE_BINMODE)
- stdout_binmode = 1;
- }
-
- if (init_p == 0) {
- if (RARRAY(rb_argv)->len > 0) {
- next_p = 1;
- }
- else {
- next_p = -1;
- }
- init_p = 1;
- gets_lineno = 0;
- }
-
- if (next_p == 1) {
- next_p = 0;
- retry:
- if (RARRAY(rb_argv)->len > 0) {
- filename = rb_ary_shift(rb_argv);
- fn = StringValuePtr(filename);
- if (strlen(fn) == 1 && fn[0] == '-') {
- current_file = rb_stdin;
- if (ruby_inplace_mode) {
- rb_warn("Can't do inplace edit for stdio; skipping");
- goto retry;
- }
- }
- else {
- int fr = rb_sysopen(fn, O_RDONLY, 0);
-
- if (ruby_inplace_mode) {
- struct stat st, st2;
- VALUE str;
- int fw;
-
- if (TYPE(rb_stdout) == T_FILE && rb_stdout != orig_stdout) {
- rb_io_close(rb_stdout);
- }
- fstat(fr, &st);
- if (*ruby_inplace_mode) {
- str = rb_str_new2(fn);
-#ifdef NO_LONG_FNAME
- ruby_add_suffix(str, ruby_inplace_mode);
-#else
- rb_str_cat2(str, ruby_inplace_mode);
-#endif
-#ifdef NO_SAFE_RENAME
- (void)close(fr);
- (void)unlink(RSTRING(str)->ptr);
- (void)rename(fn, RSTRING(str)->ptr);
- fr = rb_sysopen(RSTRING(str)->ptr, O_RDONLY, 0);
-#else
- if (rename(fn, RSTRING(str)->ptr) < 0) {
- rb_warn("Can't rename %s to %s: %s, skipping file",
- fn, RSTRING(str)->ptr, strerror(errno));
- close(fr);
- goto retry;
- }
-#endif
- }
- else {
-#ifdef NO_SAFE_RENAME
- rb_fatal("Can't do inplace edit without backup");
-#else
- if (unlink(fn) < 0) {
- rb_warn("Can't remove %s: %s, skipping file",
- fn, strerror(errno));
- close(fr);
- goto retry;
- }
-#endif
- }
- fw = rb_sysopen(fn, O_WRONLY|O_CREAT|O_TRUNC, 0666);
-#ifndef NO_SAFE_RENAME
- fstat(fw, &st2);
-#ifdef HAVE_FCHMOD
- fchmod(fw, st.st_mode);
-#else
- chmod(fn, st.st_mode);
-#endif
- if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
- fchown(fw, st.st_uid, st.st_gid);
- }
-#endif
- rb_stdout = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
- if (stdout_binmode) rb_io_binmode(rb_stdout);
- }
- current_file = prep_io(fr, FMODE_READABLE, rb_cFile, fn);
- }
- if (binmode) rb_io_binmode(current_file);
- }
- else {
- next_p = 1;
- return Qfalse;
- }
- }
- else if (next_p == -1) {
- current_file = rb_stdin;
- filename = rb_str_new2("-");
- if (ruby_inplace_mode) {
- rb_warn("Can't do inplace edit for stdio");
- rb_stdout = orig_stdout;
- }
- }
- return Qtrue;
-}
-
-static VALUE
-argf_getline(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE line;
-
- retry:
- if (!next_argv()) return Qnil;
- if (argc == 0 && rb_rs == rb_default_rs) {
- line = rb_io_gets(current_file);
- }
- else {
- VALUE rs;
-
- if (argc == 0) {
- rs = rb_rs;
- }
- else {
- rb_scan_args(argc, argv, "1", &rs);
- if (!NIL_P(rs)) StringValue(rs);
- }
- line = rb_io_getline(rs, current_file);
- }
- if (NIL_P(line) && next_p != -1) {
- argf_close(current_file);
- next_p = 1;
- goto retry;
- }
- if (!NIL_P(line)) {
- gets_lineno++;
- lineno = INT2FIX(gets_lineno);
- }
- return line;
-}
-
-/*
- * call-seq:
- * gets(separator=$/) => string or nil
- *
- * Returns (and assigns to <code>$_</code>) the next line from the list
- * of files in +ARGV+ (or <code>$*</code>), or from standard
- * input if no files are present on the command line. Returns
- * +nil+ at end of file. The optional argument specifies the
- * record separator. The separator is included with the contents of
- * each record. A separator of +nil+ reads the entire
- * contents, and a zero-length separator reads the input one paragraph
- * at a time, where paragraphs are divided by two consecutive newlines.
- * If multiple filenames are present in +ARGV+,
- * +gets(nil)+ will read the contents one file at a time.
- *
- * ARGV << "testfile"
- * print while gets
- *
- * <em>produces:</em>
- *
- * This is line one
- * This is line two
- * This is line three
- * And so on...
- *
- * The style of programming using <code>$_</code> as an implicit
- * parameter is gradually losing favor in the Ruby community.
- */
-
-static VALUE
-rb_f_gets(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE line;
-
- if (!next_argv()) return Qnil;
- if (TYPE(current_file) != T_FILE) {
- line = rb_funcall3(current_file, rb_intern("gets"), argc, argv);
- }
- else {
- line = argf_getline(argc, argv);
- }
- rb_lastline_set(line);
- return line;
-}
-
-VALUE
-rb_gets()
-{
- VALUE line;
-
- if (rb_rs != rb_default_rs) {
- return rb_f_gets(0, 0);
- }
-
- retry:
- if (!next_argv()) return Qnil;
- line = rb_io_gets(current_file);
- if (NIL_P(line) && next_p != -1) {
- argf_close(current_file);
- next_p = 1;
- goto retry;
- }
- rb_lastline_set(line);
- if (!NIL_P(line)) {
- gets_lineno++;
- lineno = INT2FIX(gets_lineno);
- }
-
- return line;
-}
-
-/*
- * call-seq:
- * readline(separator=$/) => string
- *
- * Equivalent to <code>Kernel::gets</code>, except
- * +readline+ raises +EOFError+ at end of file.
- */
-
-static VALUE
-rb_f_readline(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE line;
-
- if (!next_argv()) rb_eof_error();
- ARGF_FORWARD(argc, argv);
- line = rb_f_gets(argc, argv);
- if (NIL_P(line)) {
- rb_eof_error();
- }
-
- return line;
-}
-
-/*
- * obsolete
- */
-static VALUE
-rb_f_getc()
-{
- rb_warn("getc is obsolete; use STDIN.getc instead");
- if (TYPE(rb_stdin) != T_FILE) {
- return rb_funcall3(rb_stdin, rb_intern("getc"), 0, 0);
- }
- return rb_io_getc(rb_stdin);
-}
-
-/*
- * call-seq:
- * readlines(separator=$/) => array
- *
- * Returns an array containing the lines returned by calling
- * <code>Kernel.gets(<i>separator</i>)</code> until the end of file.
- */
-
-static VALUE
-rb_f_readlines(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE line, ary;
-
- NEXT_ARGF_FORWARD(argc, argv);
- ary = rb_ary_new();
- while (!NIL_P(line = argf_getline(argc, argv))) {
- rb_ary_push(ary, line);
- }
-
- return ary;
-}
-
-/*
- * call-seq:
- * `cmd` => string
- *
- * Returns the standard output of running _cmd_ in a subshell.
- * The built-in syntax <code>%x{...}</code> uses
- * this method. Sets <code>$?</code> to the process status.
- *
- * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
- * `ls testdir`.split[1] #=> "main.rb"
- * `echo oops && exit 99` #=> "oops\n"
- * $?.exitstatus #=> 99
- */
-
-static VALUE
-rb_f_backquote(obj, str)
- VALUE obj, str;
-{
- VALUE port, result;
- OpenFile *fptr;
-
- SafeStringValue(str);
- port = pipe_open(1, &str, "r");
- if (NIL_P(port)) return rb_str_new(0,0);
-
- GetOpenFile(port, fptr);
- result = read_all(fptr, remain_size(fptr), Qnil);
- rb_io_close(port);
-
- return result;
-}
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-/*
- * call-seq:
- * IO.select(read_array
- * [, write_array
- * [, error_array
- * [, timeout]]] ) => array or nil
- *
- * See <code>Kernel#select</code>.
- */
-
-static VALUE
-rb_f_select(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE read, write, except, timeout, res, list;
- fd_set rset, wset, eset, pset;
- fd_set *rp, *wp, *ep;
- struct timeval *tp, timerec;
- OpenFile *fptr;
- long i;
- int max = 0, n;
- int interrupt_flag = 0;
- int pending = 0;
-
- rb_scan_args(argc, argv, "13", &read, &write, &except, &timeout);
- if (NIL_P(timeout)) {
- tp = 0;
- }
- else {
- timerec = rb_time_interval(timeout);
- tp = &timerec;
- }
-
- FD_ZERO(&pset);
- if (!NIL_P(read)) {
- Check_Type(read, T_ARRAY);
- rp = &rset;
- FD_ZERO(rp);
- for (i=0; i<RARRAY(read)->len; i++) {
- GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr);
- FD_SET(fptr->fd, rp);
- if (READ_DATA_PENDING(fptr)) { /* check for buffered data */
- pending++;
- FD_SET(fptr->fd, &pset);
- }
- if (max < fptr->fd) max = fptr->fd;
- }
- if (pending) { /* no blocking if there's buffered data */
- timerec.tv_sec = timerec.tv_usec = 0;
- tp = &timerec;
- }
- }
- else
- rp = 0;
-
- if (!NIL_P(write)) {
- Check_Type(write, T_ARRAY);
- wp = &wset;
- FD_ZERO(wp);
- for (i=0; i<RARRAY(write)->len; i++) {
- GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr);
- FD_SET(fptr->fd, wp);
- if (max < fptr->fd) max = fptr->fd;
- }
- }
- else
- wp = 0;
-
- if (!NIL_P(except)) {
- Check_Type(except, T_ARRAY);
- ep = &eset;
- FD_ZERO(ep);
- for (i=0; i<RARRAY(except)->len; i++) {
- GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr);
- FD_SET(fptr->fd, ep);
- if (max < fptr->fd) max = fptr->fd;
- }
- }
- else {
- ep = 0;
- }
-
- max++;
-
- n = rb_thread_select(max, rp, wp, ep, tp);
- if (n < 0) {
- rb_sys_fail(0);
- }
- if (!pending && n == 0) return Qnil; /* returns nil on timeout */
-
- res = rb_ary_new2(3);
- rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
- rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
- rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
-
- if (interrupt_flag == 0) {
- if (rp) {
- list = RARRAY(res)->ptr[0];
- for (i=0; i< RARRAY(read)->len; i++) {
- GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr);
- if (FD_ISSET(fptr->fd, rp)
- || FD_ISSET(fptr->fd, &pset)) {
- rb_ary_push(list, rb_ary_entry(read, i));
- }
- }
- }
-
- if (wp) {
- list = RARRAY(res)->ptr[1];
- for (i=0; i< RARRAY(write)->len; i++) {
- GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr);
- if (FD_ISSET(fptr->fd, wp)) {
- rb_ary_push(list, rb_ary_entry(write, i));
- }
- }
- }
-
- if (ep) {
- list = RARRAY(res)->ptr[2];
- for (i=0; i< RARRAY(except)->len; i++) {
- GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr);
- if (FD_ISSET(fptr->fd, ep)) {
- rb_ary_push(list, rb_ary_entry(except, i));
- }
- }
- }
- }
-
- return res; /* returns an empty array on interrupt */
-}
-
-#if !defined(MSDOS) && !defined(__human68k__)
-static int
-io_cntl(fd, cmd, narg, io_p)
- int fd, cmd, io_p;
- long narg;
-{
- int retval;
-
-#ifdef HAVE_FCNTL
- TRAP_BEG;
-# if defined(__CYGWIN__)
- retval = io_p?ioctl(fd, cmd, (void*)narg):fcntl(fd, cmd, narg);
-# else
- retval = io_p?ioctl(fd, cmd, narg):fcntl(fd, cmd, narg);
-# endif
- TRAP_END;
-#else
- if (!io_p) {
- rb_notimplement();
- }
- TRAP_BEG;
- retval = ioctl(fd, cmd, narg);
- TRAP_END;
-#endif
- return retval;
-}
-#endif
-
-static VALUE
-rb_io_ctl(io, req, arg, io_p)
- VALUE io, req, arg;
- int io_p;
-{
-#if !defined(MSDOS) && !defined(__human68k__)
- int cmd = NUM2ULONG(req);
- OpenFile *fptr;
- long len = 0;
- long narg = 0;
- int retval;
-
- rb_secure(2);
-
- if (NIL_P(arg) || arg == Qfalse) {
- narg = 0;
- }
- else if (FIXNUM_P(arg)) {
- narg = FIX2LONG(arg);
- }
- else if (arg == Qtrue) {
- narg = 1;
- }
- else {
- VALUE tmp = rb_check_string_type(arg);
-
- if (NIL_P(tmp)) {
- narg = NUM2LONG(arg);
- }
- else {
- arg = tmp;
-#ifdef IOCPARM_MASK
-#ifndef IOCPARM_LEN
-#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
-#endif
-#endif
-#ifdef IOCPARM_LEN
- len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
-#else
- len = 256; /* otherwise guess at what's safe */
-#endif
- rb_str_modify(arg);
-
- if (len <= RSTRING(arg)->len) {
- len = RSTRING(arg)->len;
- }
- if (RSTRING(arg)->len < len) {
- rb_str_resize(arg, len+1);
- }
- RSTRING(arg)->ptr[len] = 17; /* a little sanity check here */
- narg = (long)RSTRING(arg)->ptr;
- }
- }
- GetOpenFile(io, fptr);
- retval = io_cntl(fptr->fd, cmd, narg, io_p);
- if (retval < 0) rb_sys_fail(fptr->path);
- if (TYPE(arg) == T_STRING && RSTRING(arg)->ptr[len] != 17) {
- rb_raise(rb_eArgError, "return value overflowed string");
- }
-
- return INT2NUM(retval);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-
-/*
- * call-seq:
- * ios.ioctl(integer_cmd, arg) => integer
- *
- * Provides a mechanism for issuing low-level commands to control or
- * query I/O devices. Arguments and results are platform dependent. If
- * <i>arg</i> is a number, its value is passed directly. If it is a
- * string, it is interpreted as a binary sequence of bytes. On Unix
- * platforms, see <code>ioctl(2)</code> for details. Not implemented on
- * all platforms.
- */
-
-static VALUE
-rb_io_ioctl(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE req, arg;
-
- rb_scan_args(argc, argv, "11", &req, &arg);
- return rb_io_ctl(io, req, arg, 1);
-}
-
-/*
- * call-seq:
- * ios.fcntl(integer_cmd, arg) => integer
- *
- * Provides a mechanism for issuing low-level commands to control or
- * query file-oriented I/O streams. Arguments and results are platform
- * dependent. If <i>arg</i> is a number, its value is passed
- * directly. If it is a string, it is interpreted as a binary sequence
- * of bytes (<code>Array#pack</code> might be a useful way to build this
- * string). On Unix platforms, see <code>fcntl(2)</code> for details.
- * Not implemented on all platforms.
- */
-
-static VALUE
-rb_io_fcntl(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
-#ifdef HAVE_FCNTL
- VALUE req, arg;
-
- rb_scan_args(argc, argv, "11", &req, &arg);
- return rb_io_ctl(io, req, arg, 0);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-/*
- * call-seq:
- * syscall(fixnum [, args...]) => integer
- *
- * Calls the operating system function identified by _fixnum_,
- * passing in the arguments, which must be either +String+
- * objects, or +Integer+ objects that ultimately fit within
- * a native +long+. Up to nine parameters may be passed (14
- * on the Atari-ST). The function identified by _fixnum_ is system
- * dependent. On some Unix systems, the numbers may be obtained from a
- * header file called <code>syscall.h</code>.
- *
- * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
- *
- * <em>produces:</em>
- *
- * hello
- */
-
-static VALUE
-rb_f_syscall(argc, argv)
- int argc;
- VALUE *argv;
-{
-#if defined(HAVE_SYSCALL) && !defined(__CHECKER__)
-#ifdef atarist
- unsigned long arg[14]; /* yes, we really need that many ! */
-#else
- unsigned long arg[8];
-#endif
- int retval = -1;
- int i = 1;
- int items = argc - 1;
-
- /* This probably won't work on machines where sizeof(long) != sizeof(int)
- * or where sizeof(long) != sizeof(char*). But such machines will
- * not likely have syscall implemented either, so who cares?
- */
-
- rb_secure(2);
- if (argc == 0)
- rb_raise(rb_eArgError, "too few arguments for syscall");
- arg[0] = NUM2LONG(argv[0]); argv++;
- while (items--) {
- VALUE v = rb_check_string_type(*argv);
-
- if (!NIL_P(v)) {
- StringValue(v);
- rb_str_modify(v);
- arg[i] = (unsigned long)RSTRING(v)->ptr;
- }
- else {
- arg[i] = (unsigned long)NUM2LONG(*argv);
- }
- argv++;
- i++;
- }
- TRAP_BEG;
- switch (argc) {
- case 1:
- retval = syscall(arg[0]);
- break;
- case 2:
- retval = syscall(arg[0],arg[1]);
- break;
- case 3:
- retval = syscall(arg[0],arg[1],arg[2]);
- break;
- case 4:
- retval = syscall(arg[0],arg[1],arg[2],arg[3]);
- break;
- case 5:
- retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4]);
- break;
- case 6:
- retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
- break;
- case 7:
- retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
- break;
- case 8:
- retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
- arg[7]);
- break;
-#ifdef atarist
- case 9:
- retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
- arg[7], arg[8]);
- break;
- case 10:
- retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
- arg[7], arg[8], arg[9]);
- break;
- case 11:
- retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
- arg[7], arg[8], arg[9], arg[10]);
- break;
- case 12:
- retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
- arg[7], arg[8], arg[9], arg[10], arg[11]);
- break;
- case 13:
- retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
- arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]);
- break;
- case 14:
- retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
- arg[7], arg[8], arg[9], arg[10], arg[11], arg[12], arg[13]);
- break;
-#endif /* atarist */
- }
- TRAP_END;
- if (retval < 0) rb_sys_fail(0);
- return INT2NUM(retval);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-static VALUE io_new_instance _((VALUE));
-static VALUE
-io_new_instance(args)
- VALUE args;
-{
- return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
-}
-
-/*
- * call-seq:
- * IO.pipe -> array
- *
- * Creates a pair of pipe endpoints (connected to each other) and
- * returns them as a two-element array of <code>IO</code> objects:
- * <code>[</code> <i>read_file</i>, <i>write_file</i> <code>]</code>. Not
- * available on all platforms.
- *
- * In the example below, the two processes close the ends of the pipe
- * that they are not using. This is not just a cosmetic nicety. The
- * read end of a pipe will not generate an end of file condition if
- * there are any writers with the pipe still open. In the case of the
- * parent process, the <code>rd.read</code> will never return if it
- * does not first issue a <code>wr.close</code>.
- *
- * rd, wr = IO.pipe
- *
- * if fork
- * wr.close
- * puts "Parent got: <#{rd.read}>"
- * rd.close
- * Process.wait
- * else
- * rd.close
- * puts "Sending message to parent"
- * wr.write "Hi Dad"
- * wr.close
- * end
- *
- * <em>produces:</em>
- *
- * Sending message to parent
- * Parent got: <Hi Dad>
- */
-
-static VALUE
-rb_io_s_pipe(klass)
- VALUE klass;
-{
-#ifndef __human68k__
- int pipes[2], state;
- VALUE r, w, args[3];
-
-#ifdef _WIN32
- if (_pipe(pipes, 1024, O_BINARY) == -1)
-#else
- if (pipe(pipes) == -1)
-#endif
- rb_sys_fail(0);
-
- args[0] = klass;
- args[1] = INT2NUM(pipes[0]);
- args[2] = INT2FIX(O_RDONLY);
- r = rb_protect(io_new_instance, (VALUE)args, &state);
- if (state) {
- close(pipes[0]);
- close(pipes[1]);
- rb_jump_tag(state);
- }
- args[1] = INT2NUM(pipes[1]);
- args[2] = INT2FIX(O_WRONLY);
- w = rb_protect(io_new_instance, (VALUE)args, &state);
- if (state) {
- close(pipes[1]);
- if (!NIL_P(r)) rb_io_close(r);
- rb_jump_tag(state);
- }
- rb_io_synchronized(RFILE(w)->fptr);
-
- return rb_assoc_new(r, w);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-struct foreach_arg {
- int argc;
- VALUE sep;
- VALUE io;
-};
-
-static VALUE
-io_s_foreach(arg)
- struct foreach_arg *arg;
-{
- VALUE str;
-
- while (!NIL_P(str = rb_io_getline(arg->sep, arg->io))) {
- rb_yield(str);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * IO.foreach(name, sep_string=$/) {|line| block } => nil
- *
- * Executes the block for every line in the named I/O port, where lines
- * are separated by <em>sep_string</em>.
- *
- * IO.foreach("testfile") {|x| print "GOT ", x }
- *
- * <em>produces:</em>
- *
- * GOT This is line one
- * GOT This is line two
- * GOT This is line three
- * GOT And so on...
- */
-
-static VALUE
-rb_io_s_foreach(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE fname;
- struct foreach_arg arg;
-
- rb_scan_args(argc, argv, "11", &fname, &arg.sep);
- FilePathValue(fname);
- if (argc == 1) {
- arg.sep = rb_default_rs;
- }
- else if (!NIL_P(arg.sep)) {
- StringValue(arg.sep);
- }
- arg.io = rb_io_open(RSTRING(fname)->ptr, "r");
- if (NIL_P(arg.io)) return Qnil;
-
- return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
-}
-
-static VALUE
-io_s_readlines(arg)
- struct foreach_arg *arg;
-{
- return rb_io_readlines(arg->argc, &arg->sep, arg->io);
-}
-
-/*
- * call-seq:
- * IO.readlines(name, sep_string=$/) => array
- *
- * Reads the entire file specified by <i>name</i> as individual
- * lines, and returns those lines in an array. Lines are separated by
- * <i>sep_string</i>.
- *
- * a = IO.readlines("testfile")
- * a[0] #=> "This is line one\n"
- *
- */
-
-static VALUE
-rb_io_s_readlines(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE fname;
- struct foreach_arg arg;
-
- rb_scan_args(argc, argv, "11", &fname, &arg.sep);
- FilePathValue(fname);
- arg.argc = argc - 1;
- arg.io = rb_io_open(RSTRING(fname)->ptr, "r");
- if (NIL_P(arg.io)) return Qnil;
- return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
-}
-
-static VALUE
-io_s_read(arg)
- struct foreach_arg *arg;
-{
- return io_read(arg->argc, &arg->sep, arg->io);
-}
-
-/*
- * call-seq:
- * IO.read(name, [length [, offset]] ) => string
- *
- * Opens the file, optionally seeks to the given offset, then returns
- * <i>length</i> bytes (defaulting to the rest of the file).
- * <code>read</code> ensures the file is closed before returning.
- *
- * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
- * IO.read("testfile", 20) #=> "This is line one\nThi"
- * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
- */
-
-static VALUE
-rb_io_s_read(argc, argv, io)
- int argc;
- VALUE *argv;
- VALUE io;
-{
- VALUE fname, offset;
- struct foreach_arg arg;
-
- rb_scan_args(argc, argv, "12", &fname, &arg.sep, &offset);
- FilePathValue(fname);
- arg.argc = argc ? 1 : 0;
- arg.io = rb_io_open(RSTRING(fname)->ptr, "r");
- if (NIL_P(arg.io)) return Qnil;
- if (!NIL_P(offset)) {
- rb_io_seek(arg.io, offset, SEEK_SET);
- }
- return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
-}
-
-static VALUE
-argf_tell()
-{
- if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream to tell");
- }
- ARGF_FORWARD(0, 0);
- return rb_io_tell(current_file);
-}
-
-static VALUE
-argf_seek_m(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream to seek");
- }
- ARGF_FORWARD(argc, argv);
- return rb_io_seek_m(argc, argv, current_file);
-}
-
-static VALUE
-argf_set_pos(self, offset)
- VALUE self, offset;
-{
- if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream to set position");
- }
- ARGF_FORWARD(1, &offset);
- return rb_io_set_pos(current_file, offset);
-}
-
-static VALUE
-argf_rewind()
-{
- if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream to rewind");
- }
- ARGF_FORWARD(0, 0);
- return rb_io_rewind(current_file);
-}
-
-static VALUE
-argf_fileno()
-{
- if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream");
- }
- ARGF_FORWARD(0, 0);
- return rb_io_fileno(current_file);
-}
-
-static VALUE
-argf_to_io()
-{
- next_argv();
- ARGF_FORWARD(0, 0);
- return current_file;
-}
-
-static VALUE
-argf_eof()
-{
- if (current_file) {
- if (init_p == 0) return Qtrue;
- ARGF_FORWARD(0, 0);
- if (rb_io_eof(current_file)) {
- return Qtrue;
- }
- }
- return Qfalse;
-}
-
-static VALUE
-argf_read(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE tmp, str, length;
- long len = 0;
-
- rb_scan_args(argc, argv, "02", &length, &str);
- if (!NIL_P(length)) {
- len = NUM2LONG(argv[0]);
- }
- if (!NIL_P(str)) {
- StringValue(str);
- rb_str_resize(str,0);
- argv[1] = Qnil;
- }
-
- retry:
- if (!next_argv()) {
- return str;
- }
- if (TYPE(current_file) != T_FILE) {
- tmp = argf_forward(argc, argv);
- }
- else {
- tmp = io_read(argc, argv, current_file);
- }
- if (NIL_P(str)) str = tmp;
- else if (!NIL_P(tmp)) rb_str_append(str, tmp);
- if (NIL_P(tmp) || NIL_P(length)) {
- if (next_p != -1) {
- argf_close(current_file);
- next_p = 1;
- goto retry;
- }
- }
- else if (argc >= 1) {
- if (RSTRING(str)->len < len) {
- len -= RSTRING(str)->len;
- argv[0] = INT2NUM(len);
- goto retry;
- }
- }
- return str;
-}
-
-static VALUE
-argf_readpartial_rescue(VALUE dummy)
-{
- return Qnil;
-}
-
-static VALUE
-argf_readpartial(int argc, VALUE *argv)
-{
- VALUE tmp, str, length;
-
- rb_scan_args(argc, argv, "11", &length, &str);
- if (!NIL_P(str)) {
- StringValue(str);
- argv[1] = str;
- }
-
- if (!next_argv()) {
- rb_str_resize(str, 0);
- rb_eof_error();
- }
- if (TYPE(current_file) != T_FILE) {
- tmp = rb_rescue2(argf_forward, (VALUE)argv,
- argf_readpartial_rescue, (VALUE)Qnil,
- rb_eEOFError, (VALUE)0);
- }
- else {
- tmp = io_getpartial(argc, argv, current_file);
- }
- if (NIL_P(tmp)) {
- if (next_p == -1) {
- rb_eof_error();
- }
- argf_close(current_file);
- next_p = 1;
- if (RARRAY(rb_argv)->len == 0)
- rb_eof_error();
- if (NIL_P(str))
- str = rb_str_new(NULL, 0);
- return str;
- }
- return tmp;
-}
-
-static VALUE
-argf_getc()
-{
- VALUE byte;
-
- retry:
- if (!next_argv()) return Qnil;
- if (TYPE(current_file) != T_FILE) {
- byte = rb_funcall3(current_file, rb_intern("getc"), 0, 0);
- }
- else {
- byte = rb_io_getc(current_file);
- }
- if (NIL_P(byte) && next_p != -1) {
- argf_close(current_file);
- next_p = 1;
- goto retry;
- }
-
- return byte;
-}
-
-static VALUE
-argf_readchar()
-{
- VALUE c;
-
- NEXT_ARGF_FORWARD(0, 0);
- c = argf_getc();
- if (NIL_P(c)) {
- rb_eof_error();
- }
- return c;
-}
-
-static VALUE
-argf_each_line(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE str;
-
- if (!next_argv()) return Qnil;
- if (TYPE(current_file) != T_FILE) {
- for (;;) {
- if (!next_argv()) return argf;
- rb_iterate(rb_each, current_file, rb_yield, 0);
- next_p = 1;
- }
- }
- while (!NIL_P(str = argf_getline(argc, argv))) {
- rb_yield(str);
- }
- return argf;
-}
-
-static VALUE
-argf_each_byte()
-{
- VALUE byte;
-
- while (!NIL_P(byte = argf_getc())) {
- rb_yield(byte);
- }
- return argf;
-}
-
-static VALUE
-argf_filename()
-{
- next_argv();
- return filename;
-}
-
-static VALUE
-argf_file()
-{
- next_argv();
- return current_file;
-}
-
-static VALUE
-argf_binmode()
-{
- binmode = 1;
- next_argv();
- ARGF_FORWARD(0, 0);
- rb_io_binmode(current_file);
- return argf;
-}
-
-static VALUE
-argf_skip()
-{
- if (next_p != -1) {
- argf_close(current_file);
- next_p = 1;
- }
- return argf;
-}
-
-static VALUE
-argf_close_m()
-{
- next_argv();
- argf_close(current_file);
- if (next_p != -1) {
- next_p = 1;
- }
- gets_lineno = 0;
- return argf;
-}
-
-static VALUE
-argf_closed()
-{
- next_argv();
- ARGF_FORWARD(0, 0);
- return rb_io_closed(current_file);
-}
-
-static VALUE
-argf_to_s()
-{
- return rb_str_new2("ARGF");
-}
-
-static VALUE
-opt_i_get()
-{
- if (!ruby_inplace_mode) return Qnil;
- return rb_str_new2(ruby_inplace_mode);
-}
-
-static void
-opt_i_set(val)
- VALUE val;
-{
- if (!RTEST(val)) {
- if (ruby_inplace_mode) free(ruby_inplace_mode);
- ruby_inplace_mode = 0;
- return;
- }
- StringValue(val);
- if (ruby_inplace_mode) free(ruby_inplace_mode);
- ruby_inplace_mode = 0;
- ruby_inplace_mode = strdup(RSTRING(val)->ptr);
-}
-
-/*
- * Class <code>IO</code> is the basis for all input and output in Ruby.
- * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
- * so may use more than one native operating system stream.
- *
- * Many of the examples in this section use class <code>File</code>,
- * the only standard subclass of <code>IO</code>. The two classes are
- * closely associated.
- *
- * As used in this section, <em>portname</em> may take any of the
- * following forms.
- *
- * * A plain string represents a filename suitable for the underlying
- * operating system.
- *
- * * A string starting with ``<code>|</code>'' indicates a subprocess.
- * The remainder of the string following the ``<code>|</code>'' is
- * invoked as a process with appropriate input/output channels
- * connected to it.
- *
- * * A string equal to ``<code>|-</code>'' will create another Ruby
- * instance as a subprocess.
- *
- * Ruby will convert pathnames between different operating system
- * conventions if possible. For instance, on a Windows system the
- * filename ``<code>/gumby/ruby/test.rb</code>'' will be opened as
- * ``<code>\gumby\ruby\test.rb</code>''. When specifying a
- * Windows-style filename in a Ruby string, remember to escape the
- * backslashes:
- *
- * "c:\\gumby\\ruby\\test.rb"
- *
- * Our examples here will use the Unix-style forward slashes;
- * <code>File::SEPARATOR</code> can be used to get the
- * platform-specific separator character.
- *
- * I/O ports may be opened in any one of several different modes, which
- * are shown in this section as <em>mode</em>. The mode may
- * either be a Fixnum or a String. If numeric, it should be
- * one of the operating system specific constants (O_RDONLY,
- * O_WRONLY, O_RDWR, O_APPEND and so on). See man open(2) for
- * more information.
- *
- * If the mode is given as a String, it must be one of the
- * values listed in the following table.
- *
- * Mode | Meaning
- * -----+--------------------------------------------------------
- * "r" | Read-only, starts at beginning of file (default mode).
- * -----+--------------------------------------------------------
- * "r+" | Read-write, starts at beginning of file.
- * -----+--------------------------------------------------------
- * "w" | Write-only, truncates existing file
- * | to zero length or creates a new file for writing.
- * -----+--------------------------------------------------------
- * "w+" | Read-write, truncates existing file to zero length
- * | or creates a new file for reading and writing.
- * -----+--------------------------------------------------------
- * "a" | Write-only, starts at end of file if file exists,
- * | otherwise creates a new file for writing.
- * -----+--------------------------------------------------------
- * "a+" | Read-write, starts at end of file if file exists,
- * | otherwise creates a new file for reading and
- * | writing.
- * -----+--------------------------------------------------------
- * "b" | (DOS/Windows only) Binary file mode (may appear with
- * | any of the key letters listed above).
- *
- *
- * The global constant ARGF (also accessible as $<) provides an
- * IO-like stream which allows access to all files mentioned on the
- * command line (or STDIN if no files are mentioned). ARGF provides
- * the methods <code>#path</code> and <code>#filename</code> to access
- * the name of the file currently being read.
- */
-
-void
-Init_IO()
-{
-#ifdef __CYGWIN__
-#include <sys/cygwin.h>
- static struct __cygwin_perfile pf[] =
- {
- {"", O_RDONLY | O_BINARY},
- {"", O_WRONLY | O_BINARY},
- {"", O_RDWR | O_BINARY},
- {"", O_APPEND | O_BINARY},
- {NULL, 0}
- };
- cygwin_internal(CW_PERFILE, pf);
-#endif
-
- rb_eIOError = rb_define_class("IOError", rb_eStandardError);
- rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
-
- id_write = rb_intern("write");
- id_read = rb_intern("read");
- id_getc = rb_intern("getc");
- id_flush = rb_intern("flush");
-
- rb_define_global_function("syscall", rb_f_syscall, -1);
-
- rb_define_global_function("open", rb_f_open, -1);
- rb_define_global_function("printf", rb_f_printf, -1);
- rb_define_global_function("print", rb_f_print, -1);
- rb_define_global_function("putc", rb_f_putc, 1);
- rb_define_global_function("puts", rb_f_puts, -1);
- rb_define_global_function("gets", rb_f_gets, -1);
- rb_define_global_function("readline", rb_f_readline, -1);
- rb_define_global_function("getc", rb_f_getc, 0);
- rb_define_global_function("select", rb_f_select, -1);
-
- rb_define_global_function("readlines", rb_f_readlines, -1);
-
- rb_define_global_function("`", rb_f_backquote, 1);
-
- rb_define_global_function("p", rb_f_p, -1);
- rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
-
- rb_cIO = rb_define_class("IO", rb_cObject);
- rb_include_module(rb_cIO, rb_mEnumerable);
-
- rb_define_alloc_func(rb_cIO, io_alloc);
- rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
- rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
- rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
- rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
- rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
- rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
- rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
- rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
- rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
- rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, 0);
-
- rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
-
- rb_output_fs = Qnil;
- rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
-
- rb_rs = rb_default_rs = rb_str_new2("\n");
- rb_output_rs = Qnil;
- rb_global_variable(&rb_default_rs);
- OBJ_FREEZE(rb_default_rs); /* avoid modifying RS_default */
- rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
- rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
- rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter);
-
- rb_define_hooked_variable("$.", &lineno, 0, lineno_setter);
- rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set);
-
- rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
- rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
-
- rb_define_method(rb_cIO, "print", rb_io_print, -1);
- rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
- rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
- rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
-
- rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
- rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
- rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
-
- rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
- rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
-
- rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
- rb_define_alias(rb_cIO, "to_i", "fileno");
- rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
-
- rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
- rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
- rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
-
- rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
- rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
-
- rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
-
- rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
- rb_define_method(rb_cIO, "read", io_read, -1);
- rb_define_method(rb_cIO, "write", io_write, 1);
- rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
- rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
- rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
- rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
- rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
- rb_define_method(rb_cIO, "<<", rb_io_addstr, 1);
- rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
- rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
- rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
- rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
- rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
- rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
- rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
- rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
- rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
- rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
- rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
-
- rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
- rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
- rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
- rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
-
- rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
- rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
- rb_define_method(rb_cIO, "binmode", rb_io_binmode, 0);
- rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
-
- rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
- rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
- rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
- rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
-
- rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
- rb_define_variable("$stdin", &rb_stdin);
- rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
- rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
- rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
- rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
- rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
- orig_stdout = rb_stdout;
- rb_deferr = orig_stderr = rb_stderr;
-
- /* variables to be removed in 1.8.1 */
- rb_define_hooked_variable("$defout", &rb_stdout, 0, defout_setter);
- rb_define_hooked_variable("$deferr", &rb_stderr, 0, deferr_setter);
-
- /* constants to hold original stdin/stdout/stderr */
- rb_define_global_const("STDIN", rb_stdin);
- rb_define_global_const("STDOUT", rb_stdout);
- rb_define_global_const("STDERR", rb_stderr);
-
- argf = rb_obj_alloc(rb_cObject);
- rb_extend_object(argf, rb_mEnumerable);
-
- rb_define_readonly_variable("$<", &argf);
- rb_define_global_const("ARGF", argf);
-
- rb_define_singleton_method(argf, "to_s", argf_to_s, 0);
-
- rb_define_singleton_method(argf, "fileno", argf_fileno, 0);
- rb_define_singleton_method(argf, "to_i", argf_fileno, 0);
- rb_define_singleton_method(argf, "to_io", argf_to_io, 0);
- rb_define_singleton_method(argf, "each", argf_each_line, -1);
- rb_define_singleton_method(argf, "each_line", argf_each_line, -1);
- rb_define_singleton_method(argf, "each_byte", argf_each_byte, 0);
-
- rb_define_singleton_method(argf, "read", argf_read, -1);
- rb_define_singleton_method(argf, "readpartial", argf_readpartial, -1);
- rb_define_singleton_method(argf, "readlines", rb_f_readlines, -1);
- rb_define_singleton_method(argf, "to_a", rb_f_readlines, -1);
- rb_define_singleton_method(argf, "gets", rb_f_gets, -1);
- rb_define_singleton_method(argf, "readline", rb_f_readline, -1);
- rb_define_singleton_method(argf, "getc", argf_getc, 0);
- rb_define_singleton_method(argf, "readchar", argf_readchar, 0);
- rb_define_singleton_method(argf, "tell", argf_tell, 0);
- rb_define_singleton_method(argf, "seek", argf_seek_m, -1);
- rb_define_singleton_method(argf, "rewind", argf_rewind, 0);
- rb_define_singleton_method(argf, "pos", argf_tell, 0);
- rb_define_singleton_method(argf, "pos=", argf_set_pos, 1);
- rb_define_singleton_method(argf, "eof", argf_eof, 0);
- rb_define_singleton_method(argf, "eof?", argf_eof, 0);
- rb_define_singleton_method(argf, "binmode", argf_binmode, 0);
-
- rb_define_singleton_method(argf, "filename", argf_filename, 0);
- rb_define_singleton_method(argf, "path", argf_filename, 0);
- rb_define_singleton_method(argf, "file", argf_file, 0);
- rb_define_singleton_method(argf, "skip", argf_skip, 0);
- rb_define_singleton_method(argf, "close", argf_close_m, 0);
- rb_define_singleton_method(argf, "closed?", argf_closed, 0);
-
- rb_define_singleton_method(argf, "lineno", argf_lineno, 0);
- rb_define_singleton_method(argf, "lineno=", argf_set_lineno, 1);
-
- rb_global_variable(&current_file);
- filename = rb_str_new2("-");
- rb_define_readonly_variable("$FILENAME", &filename);
-
- rb_define_virtual_variable("$-i", opt_i_get, opt_i_set);
-
-#if defined (_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__)
- atexit(pipe_atexit);
-#endif
-
- Init_File();
-
- rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
-
- rb_file_const("RDONLY", INT2FIX(O_RDONLY));
- rb_file_const("WRONLY", INT2FIX(O_WRONLY));
- rb_file_const("RDWR", INT2FIX(O_RDWR));
- rb_file_const("APPEND", INT2FIX(O_APPEND));
- rb_file_const("CREAT", INT2FIX(O_CREAT));
- rb_file_const("EXCL", INT2FIX(O_EXCL));
-#if defined(O_NDELAY) || defined(O_NONBLOCK)
-# ifdef O_NONBLOCK
- rb_file_const("NONBLOCK", INT2FIX(O_NONBLOCK));
-# else
- rb_file_const("NONBLOCK", INT2FIX(O_NDELAY));
-# endif
-#endif
- rb_file_const("TRUNC", INT2FIX(O_TRUNC));
-#ifdef O_NOCTTY
- rb_file_const("NOCTTY", INT2FIX(O_NOCTTY));
-#endif
-#ifdef O_BINARY
- rb_file_const("BINARY", INT2FIX(O_BINARY));
-#endif
-#ifdef O_SYNC
- rb_file_const("SYNC", INT2FIX(O_SYNC));
-#endif
-}
-/* C code produced by gperf version 2.7.2 */
-/* Command-line: gperf -p -j1 -i 1 -g -o -t -N rb_reserved_word -k'1,3,$' keywords */
-struct kwtable {char *name; int id[2]; enum lex_state_e state;};
-struct kwtable *rb_reserved_word _((const char *, unsigned int));
-#ifndef RIPPER
-;
-
-#define TOTAL_KEYWORDS 40
-#define MIN_WORD_LENGTH 2
-#define MAX_WORD_LENGTH 8
-#define MIN_HASH_VALUE 6
-#define MAX_HASH_VALUE 55
-/* maximum key range = 50, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
-hash (str, len)
- register const char *str;
- register unsigned int len;
-{
- static unsigned char asso_values[] =
- {
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 11, 56, 56, 36, 56, 1, 37,
- 31, 1, 56, 56, 56, 56, 29, 56, 1, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 1, 56, 32, 1, 2,
- 1, 1, 4, 23, 56, 17, 56, 20, 9, 2,
- 9, 26, 14, 56, 5, 1, 1, 16, 56, 21,
- 20, 9, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56
- };
- register int hval = len;
-
- switch (hval)
- {
- default:
- case 3:
- hval += asso_values[(unsigned char)str[2]];
- case 2:
- case 1:
- hval += asso_values[(unsigned char)str[0]];
- break;
- }
- return hval + asso_values[(unsigned char)str[len - 1]];
-}
-
-#ifdef __GNUC__
-__inline
-#endif
-struct kwtable *
-rb_reserved_word (str, len)
- register const char *str;
- register unsigned int len;
-{
- static struct kwtable wordlist[] =
- {
- {""}, {""}, {""}, {""}, {""}, {""},
- {"end", {kEND, kEND}, EXPR_END},
- {"else", {kELSE, kELSE}, EXPR_BEG},
- {"case", {kCASE, kCASE}, EXPR_VALUE},
- {"ensure", {kENSURE, kENSURE}, EXPR_BEG},
- {"module", {kMODULE, kMODULE}, EXPR_VALUE},
- {"elsif", {kELSIF, kELSIF}, EXPR_VALUE},
- {"def", {kDEF, kDEF}, EXPR_FNAME},
- {"rescue", {kRESCUE, kRESCUE_MOD}, EXPR_MID},
- {"not", {kNOT, kNOT}, EXPR_VALUE},
- {"then", {kTHEN, kTHEN}, EXPR_BEG},
- {"yield", {kYIELD, kYIELD}, EXPR_ARG},
- {"for", {kFOR, kFOR}, EXPR_VALUE},
- {"self", {kSELF, kSELF}, EXPR_END},
- {"false", {kFALSE, kFALSE}, EXPR_END},
- {"retry", {kRETRY, kRETRY}, EXPR_END},
- {"return", {kRETURN, kRETURN}, EXPR_MID},
- {"true", {kTRUE, kTRUE}, EXPR_END},
- {"if", {kIF, kIF_MOD}, EXPR_VALUE},
- {"defined?", {kDEFINED, kDEFINED}, EXPR_ARG},
- {"super", {kSUPER, kSUPER}, EXPR_ARG},
- {"undef", {kUNDEF, kUNDEF}, EXPR_FNAME},
- {"break", {kBREAK, kBREAK}, EXPR_MID},
- {"in", {kIN, kIN}, EXPR_VALUE},
- {"do", {kDO, kDO}, EXPR_BEG},
- {"nil", {kNIL, kNIL}, EXPR_END},
- {"until", {kUNTIL, kUNTIL_MOD}, EXPR_VALUE},
- {"unless", {kUNLESS, kUNLESS_MOD}, EXPR_VALUE},
- {"or", {kOR, kOR}, EXPR_VALUE},
- {"next", {kNEXT, kNEXT}, EXPR_MID},
- {"when", {kWHEN, kWHEN}, EXPR_VALUE},
- {"redo", {kREDO, kREDO}, EXPR_END},
- {"and", {kAND, kAND}, EXPR_VALUE},
- {"begin", {kBEGIN, kBEGIN}, EXPR_BEG},
- {"__LINE__", {k__LINE__, k__LINE__}, EXPR_END},
- {"class", {kCLASS, kCLASS}, EXPR_CLASS},
- {"__FILE__", {k__FILE__, k__FILE__}, EXPR_END},
- {"END", {klEND, klEND}, EXPR_END},
- {"BEGIN", {klBEGIN, klBEGIN}, EXPR_END},
- {"while", {kWHILE, kWHILE_MOD}, EXPR_VALUE},
- {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
- {""},
- {"alias", {kALIAS, kALIAS}, EXPR_FNAME}
- };
-
- if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
- {
- register int key = hash (str, len);
-
- if (key <= MAX_HASH_VALUE && key >= 0)
- {
- register const char *s = wordlist[key].name;
-
- if (*str == *s && !strcmp (str + 1, s + 1))
- return &wordlist[key];
- }
- }
- return 0;
-}
-#endif
-/**********************************************************************
-
- main.c -
-
- $Author: michal $
- $Date: 2004/06/23 12:59:01 $
- created at: Fri Aug 19 13:19:58 JST 1994
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-
-#if defined(__MACOS__) && defined(__MWERKS__)
-#include <console.h>
-#endif
-
-/* to link startup code with ObjC support */
-#if (defined(__APPLE__) || defined(__NeXT__)) && defined(__MACH__)
-static void objcdummyfunction( void ) { objc_msgSend(); }
-#endif
-
-int
-main(argc, argv, envp)
- int argc;
- char **argv, **envp;
-{
-#ifdef _WIN32
- NtInitialize(&argc, &argv);
-#endif
-#if defined(__MACOS__) && defined(__MWERKS__)
- argc = ccommand(&argv);
-#endif
-
- ruby_init();
- ruby_options(argc, argv);
- ruby_run();
- return 0;
-}
-/**********************************************************************
-
- marshal.c -
-
- $Author: matz $
- $Date: 2005/03/04 06:47:42 $
- created at: Thu Apr 27 16:30:01 JST 1995
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include "rubyio.h"
-#include "st.h"
-#include "util.h"
-
-#include <math.h>
-#ifdef HAVE_FLOAT_H
-#include <float.h>
-#endif
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
-#define BITSPERSHORT (2*CHAR_BIT)
-#define SHORTMASK ((1<<BITSPERSHORT)-1)
-#define SHORTDN(x) RSHIFT(x,BITSPERSHORT)
-
-#if SIZEOF_SHORT == SIZEOF_BDIGITS
-#define SHORTLEN(x) (x)
-#else
-static int
-shortlen(len, ds)
- long len;
- BDIGIT *ds;
-{
- BDIGIT num;
- int offset = 0;
-
- num = ds[len-1];
- while (num) {
- num = SHORTDN(num);
- offset++;
- }
- return (len - 1)*sizeof(BDIGIT)/2 + offset;
-}
-#define SHORTLEN(x) shortlen((x),d)
-#endif
-
-#define MARSHAL_MAJOR 4
-#define MARSHAL_MINOR 8
-
-#define TYPE_NIL '0'
-#define TYPE_TRUE 'T'
-#define TYPE_FALSE 'F'
-#define TYPE_FIXNUM 'i'
-
-#define TYPE_EXTENDED 'e'
-#define TYPE_UCLASS 'C'
-#define TYPE_OBJECT 'o'
-#define TYPE_DATA 'd'
-#define TYPE_USERDEF 'u'
-#define TYPE_USRMARSHAL 'U'
-#define TYPE_FLOAT 'f'
-#define TYPE_BIGNUM 'l'
-#define TYPE_STRING '"'
-#define TYPE_REGEXP '/'
-#define TYPE_ARRAY '['
-#define TYPE_HASH '{'
-#define TYPE_HASH_DEF '}'
-#define TYPE_STRUCT 'S'
-#define TYPE_MODULE_OLD 'M'
-#define TYPE_CLASS 'c'
-#define TYPE_MODULE 'm'
-
-#define TYPE_SYMBOL ':'
-#define TYPE_SYMLINK ';'
-
-#define TYPE_IVAR 'I'
-#define TYPE_LINK '@'
-
-static ID s_dump, s_load, s_mdump, s_mload;
-static ID s_dump_data, s_load_data, s_alloc;
-static ID s_getc, s_read, s_write, s_binmode;
-
-struct dump_arg {
- VALUE obj;
- VALUE str, dest;
- st_table *symbols;
- st_table *data;
- int taint;
-};
-
-struct dump_call_arg {
- VALUE obj;
- struct dump_arg *arg;
- int limit;
-};
-
-static VALUE
-class2path(klass)
- VALUE klass;
-{
- VALUE path = rb_class_path(klass);
- char *n = RSTRING(path)->ptr;
-
- if (n[0] == '#') {
- rb_raise(rb_eTypeError, "can't dump anonymous %s %s",
- (TYPE(klass) == T_CLASS ? "class" : "module"),
- n);
- }
- if (rb_path2class(n) != rb_class_real(klass)) {
- rb_raise(rb_eTypeError, "%s can't be referred", n);
- }
- return path;
-}
-
-static void w_long _((long, struct dump_arg*));
-
-static void
-w_nbyte(s, n, arg)
- char *s;
- int n;
- struct dump_arg *arg;
-{
- VALUE buf = arg->str;
- rb_str_buf_cat(buf, s, n);
- if (arg->dest && RSTRING(buf)->len >= BUFSIZ) {
- if (arg->taint) OBJ_TAINT(buf);
- rb_io_write(arg->dest, buf);
- rb_str_resize(buf, 0);
- }
-}
-
-static void
-w_byte(c, arg)
- char c;
- struct dump_arg *arg;
-{
- w_nbyte(&c, 1, arg);
-}
-
-static void
-w_bytes(s, n, arg)
- char *s;
- int n;
- struct dump_arg *arg;
-{
- w_long(n, arg);
- w_nbyte(s, n, arg);
-}
-
-static void
-w_short(x, arg)
- int x;
- struct dump_arg *arg;
-{
- w_byte((x >> 0) & 0xff, arg);
- w_byte((x >> 8) & 0xff, arg);
-}
-
-static void
-w_long(x, arg)
- long x;
- struct dump_arg *arg;
-{
- char buf[sizeof(long)+1];
- int i, len = 0;
-
-#if SIZEOF_LONG > 4
- if (!(RSHIFT(x, 31) == 0 || RSHIFT(x, 31) == -1)) {
- /* big long does not fit in 4 bytes */
- rb_raise(rb_eTypeError, "long too big to dump");
- }
-#endif
-
- if (x == 0) {
- w_byte(0, arg);
- return;
- }
- if (0 < x && x < 123) {
- w_byte(x + 5, arg);
- return;
- }
- if (-124 < x && x < 0) {
- w_byte((x - 5)&0xff, arg);
- return;
- }
- for (i=1;i<sizeof(long)+1;i++) {
- buf[i] = x & 0xff;
- x = RSHIFT(x,8);
- if (x == 0) {
- buf[0] = i;
- break;
- }
- if (x == -1) {
- buf[0] = -i;
- break;
- }
- }
- len = i;
- for (i=0;i<=len;i++) {
- w_byte(buf[i], arg);
- }
-}
-
-#ifdef DBL_MANT_DIG
-#define DECIMAL_MANT (53-16) /* from IEEE754 double precision */
-
-#if DBL_MANT_DIG > 32
-#define MANT_BITS 32
-#elif DBL_MANT_DIG > 24
-#define MANT_BITS 24
-#elif DBL_MANT_DIG > 16
-#define MANT_BITS 16
-#else
-#define MANT_BITS 8
-#endif
-
-static int
-save_mantissa(d, buf)
- double d;
- char *buf;
-{
- int e, i = 0;
- unsigned long m;
- double n;
-
- d = modf(ldexp(frexp(fabs(d), &e), DECIMAL_MANT), &d);
- if (d > 0) {
- buf[i++] = 0;
- do {
- d = modf(ldexp(d, MANT_BITS), &n);
- m = (unsigned long)n;
-#if MANT_BITS > 24
- buf[i++] = m >> 24;
-#endif
-#if MANT_BITS > 16
- buf[i++] = m >> 16;
-#endif
-#if MANT_BITS > 8
- buf[i++] = m >> 8;
-#endif
- buf[i++] = m;
- } while (d > 0);
- while (!buf[i - 1]) --i;
- }
- return i;
-}
-
-static double
-load_mantissa(d, buf, len)
- double d;
- const char *buf;
- int len;
-{
- if (--len > 0 && !*buf++) { /* binary mantissa mark */
- int e, s = d < 0, dig = 0;
- unsigned long m;
-
- modf(ldexp(frexp(fabs(d), &e), DECIMAL_MANT), &d);
- do {
- m = 0;
- switch (len) {
- default: m = *buf++ & 0xff;
-#if MANT_BITS > 24
- case 3: m = (m << 8) | (*buf++ & 0xff);
-#endif
-#if MANT_BITS > 16
- case 2: m = (m << 8) | (*buf++ & 0xff);
-#endif
-#if MANT_BITS > 8
- case 1: m = (m << 8) | (*buf++ & 0xff);
-#endif
- }
- dig -= len < MANT_BITS / 8 ? 8 * (unsigned)len : MANT_BITS;
- d += ldexp((double)m, dig);
- } while ((len -= MANT_BITS / 8) > 0);
- d = ldexp(d, e - DECIMAL_MANT);
- if (s) d = -d;
- }
- return d;
-}
-#else
-#define load_mantissa(d, buf, len) (d)
-#define save_mantissa(d, buf) 0
-#endif
-
-#ifdef DBL_DIG
-#define FLOAT_DIG (DBL_DIG+2)
-#else
-#define FLOAT_DIG 17
-#endif
-
-static void
-w_float(d, arg)
- double d;
- struct dump_arg *arg;
-{
- char buf[100];
-
- if (isinf(d)) {
- if (d < 0) strcpy(buf, "-inf");
- else strcpy(buf, "inf");
- }
- else if (isnan(d)) {
- strcpy(buf, "nan");
- }
- else if (d == 0.0) {
- if (1.0/d < 0) strcpy(buf, "-0");
- else strcpy(buf, "0");
- }
- else {
- int len;
-
- /* xxx: should not use system's sprintf(3) */
- sprintf(buf, "%.*g", FLOAT_DIG, d);
- len = strlen(buf);
- w_bytes(buf, len + save_mantissa(d, buf + len), arg);
- return;
- }
- w_bytes(buf, strlen(buf), arg);
-}
-
-static void
-w_symbol(id, arg)
- ID id;
- struct dump_arg *arg;
-{
- char *sym = rb_id2name(id);
- st_data_t num;
-
- if (st_lookup(arg->symbols, id, &num)) {
- w_byte(TYPE_SYMLINK, arg);
- w_long((long)num, arg);
- }
- else {
- w_byte(TYPE_SYMBOL, arg);
- w_bytes(sym, strlen(sym), arg);
- st_add_direct(arg->symbols, id, arg->symbols->num_entries);
- }
-}
-
-static void
-w_unique(s, arg)
- char *s;
- struct dump_arg *arg;
-{
- if (s[0] == '#') {
- rb_raise(rb_eTypeError, "can't dump anonymous class %s", s);
- }
- w_symbol(rb_intern(s), arg);
-}
-
-static void w_object _((VALUE,struct dump_arg*,int));
-
-static int
-hash_each(key, value, arg)
- VALUE key, value;
- struct dump_call_arg *arg;
-{
- w_object(key, arg->arg, arg->limit);
- w_object(value, arg->arg, arg->limit);
- return ST_CONTINUE;
-}
-
-static void
-w_extended(klass, arg, check)
- VALUE klass;
- struct dump_arg *arg;
- int check;
-{
- char *path;
-
- if (FL_TEST(klass, FL_SINGLETON)) {
- if (check && RCLASS(klass)->m_tbl->num_entries ||
- (RCLASS(klass)->iv_tbl && RCLASS(klass)->iv_tbl->num_entries > 1)) {
- rb_raise(rb_eTypeError, "singleton can't be dumped");
- }
- klass = RCLASS(klass)->super;
- }
- while (BUILTIN_TYPE(klass) == T_ICLASS) {
- path = rb_class2name(RBASIC(klass)->klass);
- w_byte(TYPE_EXTENDED, arg);
- w_unique(path, arg);
- klass = RCLASS(klass)->super;
- }
-}
-
-static void
-w_class(type, obj, arg, check)
- int type;
- VALUE obj;
- struct dump_arg *arg;
- int check;
-{
- char *path;
-
- VALUE klass = CLASS_OF(obj);
- w_extended(klass, arg, check);
- w_byte(type, arg);
- path = RSTRING(class2path(rb_class_real(klass)))->ptr;
- w_unique(path, arg);
-}
-
-static void
-w_uclass(obj, base_klass, arg)
- VALUE obj, base_klass;
- struct dump_arg *arg;
-{
- VALUE klass = CLASS_OF(obj);
-
- w_extended(klass, arg, Qtrue);
- klass = rb_class_real(klass);
- if (klass != base_klass) {
- w_byte(TYPE_UCLASS, arg);
- w_unique(RSTRING(class2path(klass))->ptr, arg);
- }
-}
-
-static int
-w_obj_each(id, value, arg)
- ID id;
- VALUE value;
- struct dump_call_arg *arg;
-{
- w_symbol(id, arg->arg);
- w_object(value, arg->arg, arg->limit);
- return ST_CONTINUE;
-}
-
-static void
-w_ivar(tbl, arg)
- st_table *tbl;
- struct dump_call_arg *arg;
-{
- if (tbl) {
- w_long(tbl->num_entries, arg->arg);
- st_foreach_safe(tbl, w_obj_each, (st_data_t)arg);
- }
- else {
- w_long(0, arg->arg);
- }
-}
-
-static void
-w_object(obj, arg, limit)
- VALUE obj;
- struct dump_arg *arg;
- int limit;
-{
- struct dump_call_arg c_arg;
- st_table *ivtbl = 0;
- st_data_t num;
-
- if (limit == 0) {
- rb_raise(rb_eArgError, "exceed depth limit");
- }
-
- limit--;
- c_arg.limit = limit;
- c_arg.arg = arg;
-
- if (st_lookup(arg->data, obj, &num)) {
- w_byte(TYPE_LINK, arg);
- w_long((long)num, arg);
- return;
- }
-
- if (ivtbl = rb_generic_ivar_table(obj)) {
- w_byte(TYPE_IVAR, arg);
- }
- if (obj == Qnil) {
- w_byte(TYPE_NIL, arg);
- }
- else if (obj == Qtrue) {
- w_byte(TYPE_TRUE, arg);
- }
- else if (obj == Qfalse) {
- w_byte(TYPE_FALSE, arg);
- }
- else if (FIXNUM_P(obj)) {
-#if SIZEOF_LONG <= 4
- w_byte(TYPE_FIXNUM, arg);
- w_long(FIX2INT(obj), arg);
-#else
- if (RSHIFT((long)obj, 31) == 0 || RSHIFT((long)obj, 31) == -1) {
- w_byte(TYPE_FIXNUM, arg);
- w_long(FIX2LONG(obj), arg);
- }
- else {
- w_object(rb_int2big(FIX2LONG(obj)), arg, limit);
- }
-#endif
- }
- else if (SYMBOL_P(obj)) {
- w_symbol(SYM2ID(obj), arg);
- }
- else {
- if (OBJ_TAINTED(obj)) arg->taint = Qtrue;
-
- st_add_direct(arg->data, obj, arg->data->num_entries);
- if (rb_respond_to(obj, s_mdump)) {
- VALUE v;
-
- v = rb_funcall(obj, s_mdump, 0, 0);
- w_class(TYPE_USRMARSHAL, obj, arg, Qfalse);
- w_object(v, arg, limit);
- if (ivtbl) w_ivar(0, &c_arg);
- return;
- }
- if (rb_respond_to(obj, s_dump)) {
- VALUE v;
-
- v = rb_funcall(obj, s_dump, 1, INT2NUM(limit));
- if (TYPE(v) != T_STRING) {
- rb_raise(rb_eTypeError, "_dump() must return string");
- }
- if (!ivtbl && (ivtbl = rb_generic_ivar_table(v))) {
- w_byte(TYPE_IVAR, arg);
- }
- w_class(TYPE_USERDEF, obj, arg, Qfalse);
- w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, arg);
- if (ivtbl) {
- w_ivar(ivtbl, &c_arg);
- }
- return;
- }
-
- switch (BUILTIN_TYPE(obj)) {
- case T_CLASS:
- if (FL_TEST(obj, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "singleton class can't be dumped");
- }
- w_byte(TYPE_CLASS, arg);
- {
- VALUE path = class2path(obj);
- w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg);
- }
- break;
-
- case T_MODULE:
- w_byte(TYPE_MODULE, arg);
- {
- VALUE path = class2path(obj);
- w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg);
- }
- break;
-
- case T_FLOAT:
- w_byte(TYPE_FLOAT, arg);
- w_float(RFLOAT(obj)->value, arg);
- break;
-
- case T_BIGNUM:
- w_byte(TYPE_BIGNUM, arg);
- {
- char sign = RBIGNUM(obj)->sign ? '+' : '-';
- long len = RBIGNUM(obj)->len;
- BDIGIT *d = RBIGNUM(obj)->digits;
-
- w_byte(sign, arg);
- w_long(SHORTLEN(len), arg); /* w_short? */
- while (len--) {
-#if SIZEOF_BDIGITS > SIZEOF_SHORT
- BDIGIT num = *d;
- int i;
-
- for (i=0; i<SIZEOF_BDIGITS; i+=SIZEOF_SHORT) {
- w_short(num & SHORTMASK, arg);
- num = SHORTDN(num);
- if (len == 0 && num == 0) break;
- }
-#else
- w_short(*d, arg);
-#endif
- d++;
- }
- }
- break;
-
- case T_STRING:
- w_uclass(obj, rb_cString, arg);
- w_byte(TYPE_STRING, arg);
- w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, arg);
- break;
-
- case T_REGEXP:
- w_uclass(obj, rb_cRegexp, arg);
- w_byte(TYPE_REGEXP, arg);
- w_bytes(RREGEXP(obj)->str, RREGEXP(obj)->len, arg);
- w_byte(rb_reg_options(obj), arg);
- break;
-
- case T_ARRAY:
- w_uclass(obj, rb_cArray, arg);
- w_byte(TYPE_ARRAY, arg);
- {
- long len = RARRAY(obj)->len;
- VALUE *ptr = RARRAY(obj)->ptr;
-
- w_long(len, arg);
- while (len--) {
- w_object(*ptr, arg, limit);
- ptr++;
- }
- }
- break;
-
- case T_HASH:
- w_uclass(obj, rb_cHash, arg);
- if (NIL_P(RHASH(obj)->ifnone)) {
- w_byte(TYPE_HASH, arg);
- }
- else if (FL_TEST(obj, FL_USER2)) {
- /* FL_USER2 means HASH_PROC_DEFAULT (see hash.c) */
- rb_raise(rb_eTypeError, "can't dump hash with default proc");
- }
- else {
- w_byte(TYPE_HASH_DEF, arg);
- }
- w_long(RHASH(obj)->tbl->num_entries, arg);
- rb_hash_foreach(obj, hash_each, (st_data_t)&c_arg);
- if (!NIL_P(RHASH(obj)->ifnone)) {
- w_object(RHASH(obj)->ifnone, arg, limit);
- }
- break;
-
- case T_STRUCT:
- w_class(TYPE_STRUCT, obj, arg, Qtrue);
- {
- long len = RSTRUCT(obj)->len;
- VALUE mem;
- long i;
-
- w_long(len, arg);
- mem = rb_struct_members(obj);
- for (i=0; i<len; i++) {
- w_symbol(SYM2ID(RARRAY(mem)->ptr[i]), arg);
- w_object(RSTRUCT(obj)->ptr[i], arg, limit);
- }
- }
- break;
-
- case T_OBJECT:
- w_class(TYPE_OBJECT, obj, arg, Qtrue);
- w_ivar(ROBJECT(obj)->iv_tbl, &c_arg);
- break;
-
- case T_DATA:
- {
- VALUE v;
-
- w_class(TYPE_DATA, obj, arg, Qtrue);
- if (!rb_respond_to(obj, s_dump_data)) {
- rb_raise(rb_eTypeError,
- "no marshal_dump is defined for class %s",
- rb_obj_classname(obj));
- }
- v = rb_funcall(obj, s_dump_data, 0);
- w_object(v, arg, limit);
- }
- break;
-
- default:
- rb_raise(rb_eTypeError, "can't dump %s",
- rb_obj_classname(obj));
- break;
- }
- }
- if (ivtbl) {
- w_ivar(ivtbl, &c_arg);
- }
-}
-
-static VALUE
-dump(arg)
- struct dump_call_arg *arg;
-{
- w_object(arg->obj, arg->arg, arg->limit);
- if (arg->arg->dest) {
- rb_io_write(arg->arg->dest, arg->arg->str);
- rb_str_resize(arg->arg->str, 0);
- }
- return 0;
-}
-
-static VALUE
-dump_ensure(arg)
- struct dump_arg *arg;
-{
- st_free_table(arg->symbols);
- st_free_table(arg->data);
- if (arg->taint) {
- OBJ_TAINT(arg->str);
- }
- return 0;
-}
-
-/*
- * call-seq:
- * dump( obj [, anIO] , limit=--1 ) => anIO
- *
- * Serializes obj and all descendent objects. If anIO is
- * specified, the serialized data will be written to it, otherwise the
- * data will be returned as a String. If limit is specified, the
- * traversal of subobjects will be limited to that depth. If limit is
- * negative, no checking of depth will be performed.
- *
- * class Klass
- * def initialize(str)
- * @str = str
- * end
- * def sayHello
- * @str
- * end
- * end
- *
- * (produces no output)
- *
- * o = Klass.new("hello\n")
- * data = Marshal.dump(o)
- * obj = Marshal.load(data)
- * obj.sayHello #=> "hello\n"
- */
-static VALUE
-marshal_dump(argc, argv)
- int argc;
- VALUE* argv;
-{
- VALUE obj, port, a1, a2;
- int limit = -1;
- struct dump_arg arg;
- struct dump_call_arg c_arg;
-
- port = Qnil;
- rb_scan_args(argc, argv, "12", &obj, &a1, &a2);
- if (argc == 3) {
- if (!NIL_P(a2)) limit = NUM2INT(a2);
- if (NIL_P(a1)) goto type_error;
- port = a1;
- }
- else if (argc == 2) {
- if (FIXNUM_P(a1)) limit = FIX2INT(a1);
- else if (NIL_P(a1)) goto type_error;
- else port = a1;
- }
- arg.dest = 0;
- if (!NIL_P(port)) {
- if (!rb_respond_to(port, s_write)) {
- type_error:
- rb_raise(rb_eTypeError, "instance of IO needed");
- }
- arg.str = rb_str_buf_new(0);
- arg.dest = port;
- if (rb_respond_to(port, s_binmode)) {
- rb_funcall2(port, s_binmode, 0, 0);
- }
- }
- else {
- port = rb_str_buf_new(0);
- arg.str = port;
- }
-
- arg.symbols = st_init_numtable();
- arg.data = st_init_numtable();
- arg.taint = Qfalse;
- c_arg.obj = obj;
- c_arg.arg = &arg;
- c_arg.limit = limit;
-
- w_byte(MARSHAL_MAJOR, &arg);
- w_byte(MARSHAL_MINOR, &arg);
-
- rb_ensure(dump, (VALUE)&c_arg, dump_ensure, (VALUE)&arg);
-
- return port;
-}
-
-struct load_arg {
- VALUE src;
- long offset;
- st_table *symbols;
- VALUE data;
- VALUE proc;
- int taint;
-};
-
-static VALUE r_object _((struct load_arg *arg));
-
-static int
-r_byte(arg)
- struct load_arg *arg;
-{
- int c;
-
- if (TYPE(arg->src) == T_STRING) {
- if (RSTRING(arg->src)->len > arg->offset) {
- c = (unsigned char)RSTRING(arg->src)->ptr[arg->offset++];
- }
- else {
- rb_raise(rb_eArgError, "marshal data too short");
- }
- }
- else {
- VALUE src = arg->src;
- VALUE v = rb_funcall2(src, s_getc, 0, 0);
- if (NIL_P(v)) rb_eof_error();
- c = (unsigned char)FIX2INT(v);
- }
- return c;
-}
-
-static void
-long_toobig(size)
- int size;
-{
- rb_raise(rb_eTypeError, "long too big for this architecture (size %d, given %d)",
- sizeof(long), size);
-}
-
-#undef SIGN_EXTEND_CHAR
-#if __STDC__
-# define SIGN_EXTEND_CHAR(c) ((signed char)(c))
-#else /* not __STDC__ */
-/* As in Harbison and Steele. */
-# define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
-#endif
-
-static long
-r_long(arg)
- struct load_arg *arg;
-{
- register long x;
- int c = SIGN_EXTEND_CHAR(r_byte(arg));
- long i;
-
- if (c == 0) return 0;
- if (c > 0) {
- if (4 < c && c < 128) {
- return c - 5;
- }
- if (c > sizeof(long)) long_toobig(c);
- x = 0;
- for (i=0;i<c;i++) {
- x |= (long)r_byte(arg) << (8*i);
- }
- }
- else {
- if (-129 < c && c < -4) {
- return c + 5;
- }
- c = -c;
- if (c > sizeof(long)) long_toobig(c);
- x = -1;
- for (i=0;i<c;i++) {
- x &= ~((long)0xff << (8*i));
- x |= (long)r_byte(arg) << (8*i);
- }
- }
- return x;
-}
-
-#define r_bytes(arg) r_bytes0(r_long(arg), (arg))
-
-static VALUE
-r_bytes0(len, arg)
- long len;
- struct load_arg *arg;
-{
- VALUE str;
-
- if (len == 0) return rb_str_new(0, 0);
- if (TYPE(arg->src) == T_STRING) {
- if (RSTRING(arg->src)->len > arg->offset) {
- str = rb_str_new(RSTRING(arg->src)->ptr+arg->offset, len);
- arg->offset += len;
- }
- else {
- too_short:
- rb_raise(rb_eArgError, "marshal data too short");
- }
- }
- else {
- VALUE src = arg->src;
- VALUE n = LONG2NUM(len);
- str = rb_funcall2(src, s_read, 1, &n);
- if (NIL_P(str)) goto too_short;
- StringValue(str);
- if (RSTRING(str)->len != len) goto too_short;
- if (OBJ_TAINTED(str)) arg->taint = Qtrue;
- }
- return str;
-}
-
-static ID
-r_symlink(arg)
- struct load_arg *arg;
-{
- ID id;
- long num = r_long(arg);
-
- if (st_lookup(arg->symbols, num, &id)) {
- return id;
- }
- rb_raise(rb_eArgError, "bad symbol");
-}
-
-static ID
-r_symreal(arg)
- struct load_arg *arg;
-{
- ID id;
-
- id = rb_intern(RSTRING(r_bytes(arg))->ptr);
- st_insert(arg->symbols, arg->symbols->num_entries, id);
-
- return id;
-}
-
-static ID
-r_symbol(arg)
- struct load_arg *arg;
-{
- if (r_byte(arg) == TYPE_SYMLINK) {
- return r_symlink(arg);
- }
- return r_symreal(arg);
-}
-
-static char*
-r_unique(arg)
- struct load_arg *arg;
-{
- return rb_id2name(r_symbol(arg));
-}
-
-static VALUE
-r_string(arg)
- struct load_arg *arg;
-{
- return r_bytes(arg);
-}
-
-static VALUE
-r_entry(v, arg)
- VALUE v;
- struct load_arg *arg;
-{
- rb_hash_aset(arg->data, INT2FIX(RHASH(arg->data)->tbl->num_entries), v);
- if (arg->taint) OBJ_TAINT(v);
- return v;
-}
-
-static void
-r_ivar(obj, arg)
- VALUE obj;
- struct load_arg *arg;
-{
- long len;
-
- len = r_long(arg);
- if (len > 0) {
- while (len--) {
- ID id = r_symbol(arg);
- VALUE val = r_object(arg);
- rb_ivar_set(obj, id, val);
- }
- }
-}
-
-static VALUE
-path2class(path)
- char *path;
-{
- VALUE v = rb_path2class(path);
-
- if (TYPE(v) != T_CLASS) {
- rb_raise(rb_eArgError, "%s does not refer class", path);
- }
- return v;
-}
-
-static VALUE
-path2module(path)
- char *path;
-{
- VALUE v = rb_path2class(path);
-
- if (TYPE(v) != T_MODULE) {
- rb_raise(rb_eArgError, "%s does not refer module", path);
- }
- return v;
-}
-
-static VALUE
-r_object0(arg, proc, ivp, extmod)
- struct load_arg *arg;
- VALUE proc;
- int *ivp;
- VALUE extmod;
-{
- VALUE v = Qnil;
- int type = r_byte(arg);
- long id;
-
- switch (type) {
- case TYPE_LINK:
- id = r_long(arg);
- v = rb_hash_aref(arg->data, LONG2FIX(id));
- if (NIL_P(v)) {
- rb_raise(rb_eArgError, "dump format error (unlinked)");
- }
- return v;
-
- case TYPE_IVAR:
- {
- int ivar = Qtrue;
-
- v = r_object0(arg, 0, &ivar, extmod);
- if (ivar) r_ivar(v, arg);
- }
- break;
-
- case TYPE_EXTENDED:
- {
- VALUE m = path2module(r_unique(arg));
-
- if (NIL_P(extmod)) extmod = rb_ary_new2(0);
- rb_ary_push(extmod, m);
-
- v = r_object0(arg, 0, 0, extmod);
- while (RARRAY(extmod)->len > 0) {
- m = rb_ary_pop(extmod);
- rb_extend_object(v, m);
- }
- }
- break;
-
- case TYPE_UCLASS:
- {
- VALUE c = path2class(r_unique(arg));
-
- if (FL_TEST(c, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "singleton can't be loaded");
- }
- v = r_object0(arg, 0, 0, extmod);
- if (rb_special_const_p(v) || TYPE(v) == T_OBJECT || TYPE(v) == T_CLASS) {
- format_error:
- rb_raise(rb_eArgError, "dump format error (user class)");
- }
- if (TYPE(v) == T_MODULE || !RTEST(rb_class_inherited_p(c, RBASIC(v)->klass))) {
- VALUE tmp = rb_obj_alloc(c);
-
- if (TYPE(v) != TYPE(tmp)) goto format_error;
- }
- RBASIC(v)->klass = c;
- }
- break;
-
- case TYPE_NIL:
- v = Qnil;
- break;
-
- case TYPE_TRUE:
- v = Qtrue;
- break;
-
- case TYPE_FALSE:
- v = Qfalse;
- break;
-
- case TYPE_FIXNUM:
- {
- long i = r_long(arg);
- v = LONG2FIX(i);
- }
- break;
-
- case TYPE_FLOAT:
- {
- double d, t = 0.0;
- VALUE str = r_bytes(arg);
- const char *ptr = RSTRING(str)->ptr;
-
- if (strcmp(ptr, "nan") == 0) {
- d = t / t;
- }
- else if (strcmp(ptr, "inf") == 0) {
- d = 1.0 / t;
- }
- else if (strcmp(ptr, "-inf") == 0) {
- d = -1.0 / t;
- }
- else {
- char *e;
- d = strtod(ptr, &e);
- d = load_mantissa(d, e, RSTRING(str)->len - (e - ptr));
- }
- v = rb_float_new(d);
- r_entry(v, arg);
- }
- break;
-
- case TYPE_BIGNUM:
- {
- long len;
- BDIGIT *digits;
- VALUE data;
-
- NEWOBJ(big, struct RBignum);
- OBJSETUP(big, rb_cBignum, T_BIGNUM);
- big->sign = (r_byte(arg) == '+');
- len = r_long(arg);
- data = r_bytes0(len * 2, arg);
-#if SIZEOF_BDIGITS == SIZEOF_SHORT
- big->len = len;
-#else
- big->len = (len + 1) * 2 / sizeof(BDIGIT);
-#endif
- big->digits = digits = ALLOC_N(BDIGIT, big->len);
- MEMCPY(digits, RSTRING(data)->ptr, char, len * 2);
-#if SIZEOF_BDIGITS > SIZEOF_SHORT
- MEMZERO((char *)digits + len * 2, char,
- big->len * sizeof(BDIGIT) - len * 2);
-#endif
- len = big->len;
- while (len > 0) {
- unsigned char *p = (unsigned char *)digits;
- BDIGIT num = 0;
-#if SIZEOF_BDIGITS > SIZEOF_SHORT
- int shift = 0;
- int i;
-
- for (i=0; i<SIZEOF_BDIGITS; i++) {
- num |= (int)p[i] << shift;
- shift += 8;
- }
-#else
- num = p[0] | (p[1] << 8);
-#endif
- *digits++ = num;
- len--;
- }
- v = rb_big_norm((VALUE)big);
- r_entry(v, arg);
- }
- break;
-
- case TYPE_STRING:
- v = r_entry(r_string(arg), arg);
- break;
-
- case TYPE_REGEXP:
- {
- volatile VALUE str = r_bytes(arg);
- int options = r_byte(arg);
- v = r_entry(rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len, options), arg);
- }
- break;
-
- case TYPE_ARRAY:
- {
- volatile long len = r_long(arg); /* gcc 2.7.2.3 -O2 bug?? */
-
- v = rb_ary_new2(len);
- r_entry(v, arg);
- while (len--) {
- rb_ary_push(v, r_object(arg));
- }
- }
- break;
-
- case TYPE_HASH:
- case TYPE_HASH_DEF:
- {
- long len = r_long(arg);
-
- v = rb_hash_new();
- r_entry(v, arg);
- while (len--) {
- VALUE key = r_object(arg);
- VALUE value = r_object(arg);
- rb_hash_aset(v, key, value);
- }
- if (type == TYPE_HASH_DEF) {
- RHASH(v)->ifnone = r_object(arg);
- }
- }
- break;
-
- case TYPE_STRUCT:
- {
- VALUE klass, mem, values;
- volatile long i; /* gcc 2.7.2.3 -O2 bug?? */
- long len;
- ID slot;
-
- klass = path2class(r_unique(arg));
- mem = rb_struct_s_members(klass);
- if (mem == Qnil) {
- rb_raise(rb_eTypeError, "uninitialized struct");
- }
- len = r_long(arg);
-
- values = rb_ary_new2(len);
- for (i=0; i<len; i++) {
- rb_ary_push(values, Qnil);
- }
- v = rb_struct_alloc(klass, values);
- r_entry(v, arg);
- for (i=0; i<len; i++) {
- slot = r_symbol(arg);
-
- if (RARRAY(mem)->ptr[i] != ID2SYM(slot)) {
- rb_raise(rb_eTypeError, "struct %s not compatible (:%s for :%s)",
- rb_class2name(klass),
- rb_id2name(slot),
- rb_id2name(SYM2ID(RARRAY(mem)->ptr[i])));
- }
- rb_struct_aset(v, LONG2FIX(i), r_object(arg));
- }
- }
- break;
-
- case TYPE_USERDEF:
- {
- VALUE klass = path2class(r_unique(arg));
- VALUE data;
-
- if (!rb_respond_to(klass, s_load)) {
- rb_raise(rb_eTypeError, "class %s needs to have method `_load'",
- rb_class2name(klass));
- }
- data = r_string(arg);
- if (ivp) {
- r_ivar(data, arg);
- *ivp = Qfalse;
- }
- v = rb_funcall(klass, s_load, 1, data);
- r_entry(v, arg);
- }
- break;
-
- case TYPE_USRMARSHAL:
- {
- VALUE klass = path2class(r_unique(arg));
- VALUE data;
-
- v = rb_obj_alloc(klass);
- if (! NIL_P(extmod)) {
- while (RARRAY(extmod)->len > 0) {
- VALUE m = rb_ary_pop(extmod);
- rb_extend_object(v, m);
- }
- }
- if (!rb_respond_to(v, s_mload)) {
- rb_raise(rb_eTypeError, "instance of %s needs to have method `marshal_load'",
- rb_class2name(klass));
- }
- r_entry(v, arg);
- data = r_object(arg);
- rb_funcall(v, s_mload, 1, data);
- }
- break;
-
- case TYPE_OBJECT:
- {
- VALUE klass = path2class(r_unique(arg));
-
- v = rb_obj_alloc(klass);
- if (TYPE(v) != T_OBJECT) {
- rb_raise(rb_eArgError, "dump format error");
- }
- r_entry(v, arg);
- r_ivar(v, arg);
- }
- break;
-
- case TYPE_DATA:
- {
- VALUE klass = path2class(r_unique(arg));
- if (rb_respond_to(klass, s_alloc)) {
- static int warn = Qtrue;
- if (warn) {
- rb_warn("define `allocate' instead of `_alloc'");
- warn = Qfalse;
- }
- v = rb_funcall(klass, s_alloc, 0);
- }
- else {
- v = rb_obj_alloc(klass);
- }
- if (TYPE(v) != T_DATA) {
- rb_raise(rb_eArgError, "dump format error");
- }
- r_entry(v, arg);
- if (!rb_respond_to(v, s_load_data)) {
- rb_raise(rb_eTypeError,
- "class %s needs to have instance method `_load_data'",
- rb_class2name(klass));
- }
- rb_funcall(v, s_load_data, 1, r_object0(arg, 0, 0, extmod));
- }
- break;
-
- case TYPE_MODULE_OLD:
- {
- volatile VALUE str = r_bytes(arg);
-
- v = rb_path2class(RSTRING(str)->ptr);
- r_entry(v, arg);
- }
- break;
-
- case TYPE_CLASS:
- {
- volatile VALUE str = r_bytes(arg);
-
- v = path2class(RSTRING(str)->ptr);
- r_entry(v, arg);
- }
- break;
-
- case TYPE_MODULE:
- {
- volatile VALUE str = r_bytes(arg);
-
- v = path2module(RSTRING(str)->ptr);
- r_entry(v, arg);
- }
- break;
-
- case TYPE_SYMBOL:
- v = ID2SYM(r_symreal(arg));
- break;
-
- case TYPE_SYMLINK:
- return ID2SYM(r_symlink(arg));
-
- default:
- rb_raise(rb_eArgError, "dump format error(0x%x)", type);
- break;
- }
- if (proc) {
- rb_funcall(proc, rb_intern("call"), 1, v);
- }
- return v;
-}
-
-static VALUE
-r_object(arg)
- struct load_arg *arg;
-{
- return r_object0(arg, arg->proc, 0, Qnil);
-}
-
-static VALUE
-load(arg)
- struct load_arg *arg;
-{
- return r_object(arg);
-}
-
-static VALUE
-load_ensure(arg)
- struct load_arg *arg;
-{
- st_free_table(arg->symbols);
- return 0;
-}
-
-/*
- * call-seq:
- * load( source [, proc] ) => obj
- * restore( source [, proc] ) => obj
- *
- * Returns the result of converting the serialized data in source into a
- * Ruby object (possibly with associated subordinate objects). source
- * may be either an instance of IO or an object that responds to
- * to_str. If proc is specified, it will be passed each object as it
- * is deserialized.
- */
-static VALUE
-marshal_load(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE port, proc;
- int major, minor;
- VALUE v;
- struct load_arg arg;
-
- rb_scan_args(argc, argv, "11", &port, &proc);
- if (rb_respond_to(port, rb_intern("to_str"))) {
- arg.taint = OBJ_TAINTED(port); /* original taintedness */
- StringValue(port); /* possible conversion */
- }
- else if (rb_respond_to(port, s_getc) && rb_respond_to(port, s_read)) {
- if (rb_respond_to(port, s_binmode)) {
- rb_funcall2(port, s_binmode, 0, 0);
- }
- arg.taint = Qtrue;
- }
- else {
- rb_raise(rb_eTypeError, "instance of IO needed");
- }
- arg.src = port;
- arg.offset = 0;
-
- major = r_byte(&arg);
- minor = r_byte(&arg);
- if (major != MARSHAL_MAJOR || minor > MARSHAL_MINOR) {
- rb_raise(rb_eTypeError, "incompatible marshal file format (can't be read)\n\
-\tformat version %d.%d required; %d.%d given",
- MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
- }
- if (RTEST(ruby_verbose) && minor != MARSHAL_MINOR) {
- rb_warn("incompatible marshal file format (can be read)\n\
-\tformat version %d.%d required; %d.%d given",
- MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
- }
-
- arg.symbols = st_init_numtable();
- arg.data = rb_hash_new();
- if (NIL_P(proc)) arg.proc = 0;
- else arg.proc = proc;
- v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg);
-
- return v;
-}
-
-/*
- * The marshaling library converts collections of Ruby objects into a
- * byte stream, allowing them to be stored outside the currently
- * active script. This data may subsequently be read and the original
- * objects reconstituted.
- * Marshaled data has major and minor version numbers stored along
- * with the object information. In normal use, marshaling can only
- * load data written with the same major version number and an equal
- * or lower minor version number. If Ruby's ``verbose'' flag is set
- * (normally using -d, -v, -w, or --verbose) the major and minor
- * numbers must match exactly. Marshal versioning is independent of
- * Ruby's version numbers. You can extract the version by reading the
- * first two bytes of marshaled data.
- *
- * str = Marshal.dump("thing")
- * RUBY_VERSION #=> "1.8.0"
- * str[0] #=> 4
- * str[1] #=> 8
- *
- * Some objects cannot be dumped: if the objects to be dumped include
- * bindings, procedure or method objects, instances of class IO, or
- * singleton objects, a TypeError will be raised.
- * If your class has special serialization needs (for example, if you
- * want to serialize in some specific format), or if it contains
- * objects that would otherwise not be serializable, you can implement
- * your own serialization strategy by defining two methods, _dump and
- * _load:
- * The instance method _dump should return a String object containing
- * all the information necessary to reconstitute objects of this class
- * and all referenced objects up to a maximum depth given as an integer
- * parameter (a value of -1 implies that you should disable depth checking).
- * The class method _load should take a String and return an object of this class.
- */
-void
-Init_marshal()
-{
- VALUE rb_mMarshal = rb_define_module("Marshal");
-
- s_dump = rb_intern("_dump");
- s_load = rb_intern("_load");
- s_mdump = rb_intern("marshal_dump");
- s_mload = rb_intern("marshal_load");
- s_dump_data = rb_intern("_dump_data");
- s_load_data = rb_intern("_load_data");
- s_alloc = rb_intern("_alloc");
- s_getc = rb_intern("getc");
- s_read = rb_intern("read");
- s_write = rb_intern("write");
- s_binmode = rb_intern("binmode");
-
- rb_define_module_function(rb_mMarshal, "dump", marshal_dump, -1);
- rb_define_module_function(rb_mMarshal, "load", marshal_load, -1);
- rb_define_module_function(rb_mMarshal, "restore", marshal_load, -1);
-
- rb_define_const(rb_mMarshal, "MAJOR_VERSION", INT2FIX(MARSHAL_MAJOR));
- rb_define_const(rb_mMarshal, "MINOR_VERSION", INT2FIX(MARSHAL_MINOR));
-}
-
-VALUE
-rb_marshal_dump(obj, port)
- VALUE obj, port;
-{
- int argc = 1;
- VALUE argv[2];
-
- argv[0] = obj;
- argv[1] = port;
- if (!NIL_P(port)) argc = 2;
- return marshal_dump(argc, argv);
-}
-
-VALUE
-rb_marshal_load(port)
- VALUE port;
-{
- return marshal_load(1, &port);
-}
-/**********************************************************************
-
- math.c -
-
- $Author: matz $
- $Date: 2004/09/03 17:38:34 $
- created at: Tue Jan 25 14:12:56 JST 1994
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include <math.h>
-#include <errno.h>
-
-VALUE rb_mMath;
-
-#define Need_Float(x) (x) = rb_Float(x)
-#define Need_Float2(x,y) do {\
- Need_Float(x);\
- Need_Float(y);\
-} while (0)
-
-
-/*
- * call-seq:
- * Math.atan2(y, x) => float
- *
- * Computes the arc tangent given <i>y</i> and <i>x</i>. Returns
- * -PI..PI.
- *
- */
-
-static VALUE
-math_atan2(obj, y, x)
- VALUE obj, x, y;
-{
- Need_Float2(y, x);
- return rb_float_new(atan2(RFLOAT(y)->value, RFLOAT(x)->value));
-}
-
-
-
-/*
- * call-seq:
- * Math.cos(x) => float
- *
- * Computes the cosine of <i>x</i> (expressed in radians). Returns
- * -1..1.
- */
-
-static VALUE
-math_cos(obj, x)
- VALUE obj, x;
-{
- Need_Float(x);
- return rb_float_new(cos(RFLOAT(x)->value));
-}
-
-/*
- * call-seq:
- * Math.sin(x) => float
- *
- * Computes the sine of <i>x</i> (expressed in radians). Returns
- * -1..1.
- */
-
-static VALUE
-math_sin(obj, x)
- VALUE obj, x;
-{
- Need_Float(x);
-
- return rb_float_new(sin(RFLOAT(x)->value));
-}
-
-
-/*
- * call-seq:
- * Math.tan(x) => float
- *
- * Returns the tangent of <i>x</i> (expressed in radians).
- */
-
-static VALUE
-math_tan(obj, x)
- VALUE obj, x;
-{
- Need_Float(x);
-
- return rb_float_new(tan(RFLOAT(x)->value));
-}
-
-/*
- * call-seq:
- * Math.acos(x) => float
- *
- * Computes the arc cosine of <i>x</i>. Returns 0..PI.
- */
-
-static VALUE
-math_acos(obj, x)
- VALUE obj, x;
-{
- double d;
-
- Need_Float(x);
- errno = 0;
- d = acos(RFLOAT(x)->value);
- if (errno) {
- rb_sys_fail("acos");
- }
- return rb_float_new(d);
-}
-
-/*
- * call-seq:
- * Math.asin(x) => float
- *
- * Computes the arc sine of <i>x</i>. Returns 0..PI.
- */
-
-static VALUE
-math_asin(obj, x)
- VALUE obj, x;
-{
- double d;
-
- Need_Float(x);
- errno = 0;
- d = asin(RFLOAT(x)->value);
- if (errno) {
- rb_sys_fail("asin");
- }
- return rb_float_new(d);
-}
-
-/*
- * call-seq:
- * Math.atan(x) => float
- *
- * Computes the arc tangent of <i>x</i>. Returns -{PI/2} .. {PI/2}.
- */
-
-static VALUE
-math_atan(obj, x)
- VALUE obj, x;
-{
- Need_Float(x);
- return rb_float_new(atan(RFLOAT(x)->value));
-}
-
-#ifndef HAVE_COSH
-double
-cosh(x)
- double x;
-{
- return (exp(x) + exp(-x)) / 2;
-}
-#endif
-
-/*
- * call-seq:
- * Math.cosh(x) => float
- *
- * Computes the hyperbolic cosine of <i>x</i> (expressed in radians).
- */
-
-static VALUE
-math_cosh(obj, x)
- VALUE obj, x;
-{
- Need_Float(x);
-
- return rb_float_new(cosh(RFLOAT(x)->value));
-}
-
-#ifndef HAVE_SINH
-double
-sinh(x)
- double x;
-{
- return (exp(x) - exp(-x)) / 2;
-}
-#endif
-
-/*
- * call-seq:
- * Math.sinh(x) => float
- *
- * Computes the hyperbolic sine of <i>x</i> (expressed in
- * radians).
- */
-
-static VALUE
-math_sinh(obj, x)
- VALUE obj, x;
-{
- Need_Float(x);
- return rb_float_new(sinh(RFLOAT(x)->value));
-}
-
-#ifndef HAVE_TANH
-double
-tanh(x)
- double x;
-{
- return sinh(x) / cosh(x);
-}
-#endif
-
-/*
- * call-seq:
- * Math.tanh() => float
- *
- * Computes the hyperbolic tangent of <i>x</i> (expressed in
- * radians).
- */
-
-static VALUE
-math_tanh(obj, x)
- VALUE obj, x;
-{
- Need_Float(x);
- return rb_float_new(tanh(RFLOAT(x)->value));
-}
-
-/*
- * call-seq:
- * Math.acosh(x) => float
- *
- * Computes the inverse hyperbolic cosine of <i>x</i>.
- */
-
-static VALUE
-math_acosh(obj, x)
- VALUE obj, x;
-{
- double d;
-
- Need_Float(x);
- errno = 0;
- d = acosh(RFLOAT(x)->value);
- if (errno) {
- rb_sys_fail("acosh");
- }
- return rb_float_new(d);
-}
-
-/*
- * call-seq:
- * Math.asinh(x) => float
- *
- * Computes the inverse hyperbolic sine of <i>x</i>.
- */
-
-static VALUE
-math_asinh(obj, x)
- VALUE obj, x;
-{
- Need_Float(x);
- return rb_float_new(asinh(RFLOAT(x)->value));
-}
-
-/*
- * call-seq:
- * Math.atanh(x) => float
- *
- * Computes the inverse hyperbolic tangent of <i>x</i>.
- */
-
-static VALUE
-math_atanh(obj, x)
- VALUE obj, x;
-{
- double d;
-
- Need_Float(x);
- errno = 0;
- d = atanh(RFLOAT(x)->value);
- if (errno) {
- rb_sys_fail("atanh");
- }
- return rb_float_new(d);
-}
-
-/*
- * call-seq:
- * Math.exp(x) => float
- *
- * Returns e**x.
- */
-
-static VALUE
-math_exp(obj, x)
- VALUE obj, x;
-{
- Need_Float(x);
- return rb_float_new(exp(RFLOAT(x)->value));
-}
-
-#if defined __CYGWIN__
-# include <cygwin/version.h>
-# if CYGWIN_VERSION_DLL_MAJOR < 1005
-# define nan(x) nan()
-# endif
-# define log(x) ((x) < 0.0 ? nan("") : log(x))
-# define log10(x) ((x) < 0.0 ? nan("") : log10(x))
-#endif
-
-/*
- * call-seq:
- * Math.log(numeric) => float
- *
- * Returns the natural logarithm of <i>numeric</i>.
- */
-
-static VALUE
-math_log(obj, x)
- VALUE obj, x;
-{
- double d;
-
- Need_Float(x);
- errno = 0;
- d = log(RFLOAT(x)->value);
- if (errno) {
- rb_sys_fail("log");
- }
- return rb_float_new(d);
-}
-
-/*
- * call-seq:
- * Math.log10(numeric) => float
- *
- * Returns the base 10 logarithm of <i>numeric</i>.
- */
-
-static VALUE
-math_log10(obj, x)
- VALUE obj, x;
-{
- double d;
-
- Need_Float(x);
- errno = 0;
- d = log10(RFLOAT(x)->value);
- if (errno) {
- rb_sys_fail("log10");
- }
- return rb_float_new(d);
-}
-
-/*
- * call-seq:
- * Math.sqrt(numeric) => float
- *
- * Returns the non-negative square root of <i>numeric</i>. Raises
- * <code>ArgError</code> if <i>numeric</i> is less than zero.
- */
-
-static VALUE
-math_sqrt(obj, x)
- VALUE obj, x;
-{
- double d;
-
- Need_Float(x);
- errno = 0;
- d = sqrt(RFLOAT(x)->value);
- if (errno) {
- rb_sys_fail("sqrt");
- }
- return rb_float_new(d);
-}
-
-/*
- * call-seq:
- * Math.frexp(numeric) => [ fraction, exponent ]
- *
- * Returns a two-element array containing the normalized fraction (a
- * <code>Float</code>) and exponent (a <code>Fixnum</code>) of
- * <i>numeric</i>.
- *
- * fraction, exponent = Math.frexp(1234) #=> [0.6025390625, 11]
- * fraction * 2**exponent #=> 1234.0
- */
-
-static VALUE
-math_frexp(obj, x)
- VALUE obj, x;
-{
- double d;
- int exp;
-
- Need_Float(x);
-
- d = frexp(RFLOAT(x)->value, &exp);
- return rb_assoc_new(rb_float_new(d), INT2NUM(exp));
-}
-
-/*
- * call-seq:
- * Math.ldexp(flt, int) -> float
- *
- * Returns the value of <i>flt</i>*(2**<i>int</i>).
- *
- * fraction, exponent = Math.frexp(1234)
- * Math.ldexp(fraction, exponent) #=> 1234.0
- */
-
-static VALUE
-math_ldexp(obj, x, n)
- VALUE obj, x, n;
-{
- Need_Float(x);
- return rb_float_new(ldexp(RFLOAT(x)->value, NUM2INT(n)));
-}
-
-/*
- * call-seq:
- * Math.hypot(x, y) => float
- *
- * Returns sqrt(x**2 + y**2), the hypotenuse of a right-angled triangle
- * with sides <i>x</i> and <i>y</i>.
- *
- * Math.hypot(3, 4) #=> 5.0
- */
-
-static VALUE
-math_hypot(obj, x, y)
- VALUE obj, x, y;
-{
- Need_Float2(x, y);
- return rb_float_new(hypot(RFLOAT(x)->value, RFLOAT(y)->value));
-}
-
-/*
- * call-seq:
- * Math.erf(x) => float
- *
- * Calculates the error function of x.
- */
-
-static VALUE
-math_erf(obj, x)
- VALUE obj, x;
-{
- Need_Float(x);
- return rb_float_new(erf(RFLOAT(x)->value));
-}
-
-/*
- * call-seq:
- * Math.erfc(x) => float
- *
- * Calculates the complementary error function of x.
- */
-
-static VALUE
-math_erfc(obj, x)
- VALUE obj, x;
-{
- Need_Float(x);
- return rb_float_new(erfc(RFLOAT(x)->value));
-}
-
-/*
- * The <code>Math</code> module contains module functions for basic
- * trigonometric and transcendental functions. See class
- * <code>Float</code> for a list of constants that
- * define Ruby's floating point accuracy.
- */
-
-
-void
-Init_Math()
-{
- rb_mMath = rb_define_module("Math");
-
-#ifdef M_PI
- rb_define_const(rb_mMath, "PI", rb_float_new(M_PI));
-#else
- rb_define_const(rb_mMath, "PI", rb_float_new(atan(1.0)*4.0));
-#endif
-
-#ifdef M_E
- rb_define_const(rb_mMath, "E", rb_float_new(M_E));
-#else
- rb_define_const(rb_mMath, "E", rb_float_new(exp(1.0)));
-#endif
-
- rb_define_module_function(rb_mMath, "atan2", math_atan2, 2);
- rb_define_module_function(rb_mMath, "cos", math_cos, 1);
- rb_define_module_function(rb_mMath, "sin", math_sin, 1);
- rb_define_module_function(rb_mMath, "tan", math_tan, 1);
-
- rb_define_module_function(rb_mMath, "acos", math_acos, 1);
- rb_define_module_function(rb_mMath, "asin", math_asin, 1);
- rb_define_module_function(rb_mMath, "atan", math_atan, 1);
-
- rb_define_module_function(rb_mMath, "cosh", math_cosh, 1);
- rb_define_module_function(rb_mMath, "sinh", math_sinh, 1);
- rb_define_module_function(rb_mMath, "tanh", math_tanh, 1);
-
- rb_define_module_function(rb_mMath, "acosh", math_acosh, 1);
- rb_define_module_function(rb_mMath, "asinh", math_asinh, 1);
- rb_define_module_function(rb_mMath, "atanh", math_atanh, 1);
-
- rb_define_module_function(rb_mMath, "exp", math_exp, 1);
- rb_define_module_function(rb_mMath, "log", math_log, 1);
- rb_define_module_function(rb_mMath, "log10", math_log10, 1);
- rb_define_module_function(rb_mMath, "sqrt", math_sqrt, 1);
-
- rb_define_module_function(rb_mMath, "frexp", math_frexp, 1);
- rb_define_module_function(rb_mMath, "ldexp", math_ldexp, 2);
-
- rb_define_module_function(rb_mMath, "hypot", math_hypot, 2);
-
- rb_define_module_function(rb_mMath, "erf", math_erf, 1);
- rb_define_module_function(rb_mMath, "erfc", math_erfc, 1);
-}
-/**********************************************************************
-
- numeric.c -
-
- $Author: matz $
- $Date: 2005/04/18 06:38:30 $
- created at: Fri Aug 13 18:33:09 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include "env.h"
-#include <ctype.h>
-#include <math.h>
-#include <stdio.h>
-
-#if defined(__FreeBSD__) && __FreeBSD__ < 4
-#include <floatingpoint.h>
-#endif
-
-#ifdef HAVE_FLOAT_H
-#include <float.h>
-#endif
-
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
-/* use IEEE 64bit values if not defined */
-#ifndef FLT_RADIX
-#define FLT_RADIX 2
-#endif
-#ifndef FLT_ROUNDS
-#define FLT_ROUNDS 1
-#endif
-#ifndef DBL_MIN
-#define DBL_MIN 2.2250738585072014e-308
-#endif
-#ifndef DBL_MAX
-#define DBL_MAX 1.7976931348623157e+308
-#endif
-#ifndef DBL_MIN_EXP
-#define DBL_MIN_EXP (-1021)
-#endif
-#ifndef DBL_MAX_EXP
-#define DBL_MAX_EXP 1024
-#endif
-#ifndef DBL_MIN_10_EXP
-#define DBL_MIN_10_EXP (-307)
-#endif
-#ifndef DBL_MAX_10_EXP
-#define DBL_MAX_10_EXP 308
-#endif
-#ifndef DBL_DIG
-#define DBL_DIG 15
-#endif
-#ifndef DBL_MANT_DIG
-#define DBL_MANT_DIG 53
-#endif
-#ifndef DBL_EPSILON
-#define DBL_EPSILON 2.2204460492503131e-16
-#endif
-
-static ID id_coerce, id_to_i, id_eq;
-
-VALUE rb_cNumeric;
-VALUE rb_cFloat;
-VALUE rb_cInteger;
-VALUE rb_cFixnum;
-
-VALUE rb_eZeroDivError;
-VALUE rb_eFloatDomainError;
-
-void
-rb_num_zerodiv()
-{
- rb_raise(rb_eZeroDivError, "divided by 0");
-}
-
-
-/*
- * call-seq:
- * num.coerce(numeric) => array
- *
- * If <i>aNumeric</i> is the same type as <i>num</i>, returns an array
- * containing <i>aNumeric</i> and <i>num</i>. Otherwise, returns an
- * array with both <i>aNumeric</i> and <i>num</i> represented as
- * <code>Float</code> objects. This coercion mechanism is used by
- * Ruby to handle mixed-type numeric operations: it is intended to
- * find a compatible common type between the two operands of the operator.
- *
- * 1.coerce(2.5) #=> [2.5, 1.0]
- * 1.2.coerce(3) #=> [3.0, 1.2]
- * 1.coerce(2) #=> [2, 1]
- */
-
-static VALUE
-num_coerce(x, y)
- VALUE x, y;
-{
- if (CLASS_OF(x) == CLASS_OF(y))
- return rb_assoc_new(y, x);
- return rb_assoc_new(rb_Float(y), rb_Float(x));
-}
-
-static VALUE
-coerce_body(x)
- VALUE *x;
-{
- return rb_funcall(x[1], id_coerce, 1, x[0]);
-}
-
-static VALUE
-coerce_rescue(x)
- VALUE *x;
-{
- volatile VALUE v = rb_inspect(x[1]);
-
- rb_raise(rb_eTypeError, "%s can't be coerced into %s",
- rb_special_const_p(x[1])?
- RSTRING(v)->ptr:
- rb_obj_classname(x[1]),
- rb_obj_classname(x[0]));
- return Qnil; /* dummy */
-}
-
-static int
-do_coerce(x, y, err)
- VALUE *x, *y;
- int err;
-{
- VALUE ary;
- VALUE a[2];
-
- a[0] = *x; a[1] = *y;
-
- ary = rb_rescue(coerce_body, (VALUE)a, err?coerce_rescue:0, (VALUE)a);
- if (TYPE(ary) != T_ARRAY || RARRAY(ary)->len != 2) {
- if (err) {
- rb_raise(rb_eTypeError, "coerce must return [x, y]");
- }
- return Qfalse;
- }
-
- *x = RARRAY(ary)->ptr[0];
- *y = RARRAY(ary)->ptr[1];
- return Qtrue;
-}
-
-VALUE
-rb_num_coerce_bin(x, y)
- VALUE x, y;
-{
- do_coerce(&x, &y, Qtrue);
- return rb_funcall(x, rb_frame_this_func(), 1, y);
-}
-
-VALUE
-rb_num_coerce_cmp(x, y)
- VALUE x, y;
-{
- if (do_coerce(&x, &y, Qfalse))
- return rb_funcall(x, rb_frame_this_func(), 1, y);
- return Qnil;
-}
-
-VALUE
-rb_num_coerce_relop(x, y)
- VALUE x, y;
-{
- VALUE c, x0 = x, y0 = y;
-
- if (!do_coerce(&x, &y, Qfalse) ||
- NIL_P(c = rb_funcall(x, rb_frame_this_func(), 1, y))) {
- rb_cmperr(x0, y0);
- return Qnil; /* not reached */
- }
- return c;
-}
-
-/*
- * Trap attempts to add methods to <code>Numeric</code> objects. Always
- * raises a <code>TypeError</code>
- */
-
-static VALUE
-num_sadded(x, name)
- VALUE x, name;
-{
- ruby_frame = ruby_frame->prev; /* pop frame for "singleton_method_added" */
- /* Numerics should be values; singleton_methods should not be added to them */
- rb_raise(rb_eTypeError,
- "can't define singleton method \"%s\" for %s",
- rb_id2name(rb_to_id(name)),
- rb_obj_classname(x));
- return Qnil; /* not reached */
-}
-
-/* :nodoc: */
-static VALUE
-num_init_copy(x, y)
- VALUE x, y;
-{
- /* Numerics are immutable values, which should not be copied */
- rb_raise(rb_eTypeError, "can't copy %s", rb_obj_classname(x));
- return Qnil; /* not reached */
-}
-
-/*
- * call-seq:
- * +num => num
- *
- * Unary Plus---Returns the receiver's value.
- */
-
-static VALUE
-num_uplus(num)
- VALUE num;
-{
- return num;
-}
-
-/*
- * call-seq:
- * -num => numeric
- *
- * Unary Minus---Returns the receiver's value, negated.
- */
-
-static VALUE
-num_uminus(num)
- VALUE num;
-{
- VALUE zero;
-
- zero = INT2FIX(0);
- do_coerce(&zero, &num, Qtrue);
-
- return rb_funcall(zero, '-', 1, num);
-}
-
-/*
- * call-seq:
- * num.quo(numeric) => result
- *
- * Equivalent to <code>Numeric#/</code>, but overridden in subclasses.
- */
-
-static VALUE
-num_quo(x, y)
- VALUE x, y;
-{
- return rb_funcall(x, '/', 1, y);
-}
-
-
-/*
- * call-seq:
- * num.div(numeric) => integer
- *
- * Uses <code>/</code> to perform division, then converts the result to
- * an integer. <code>Numeric</code> does not define the <code>/</code>
- * operator; this is left to subclasses.
- */
-
-static VALUE
-num_div(x, y)
- VALUE x, y;
-{
- return rb_Integer(rb_funcall(x, '/', 1, y));
-}
-
-
-
-/*
- * call-seq:
- * num.divmod( aNumeric ) -> anArray
- *
- * Returns an array containing the quotient and modulus obtained by
- * dividing <i>num</i> by <i>aNumeric</i>. If <code>q, r =
- * x.divmod(y)</code>, then
- *
- * q = floor(float(x)/float(y))
- * x = q*y + r
- *
- * The quotient is rounded toward -infinity, as shown in the following table:
- *
- * a | b | a.divmod(b) | a/b | a.modulo(b) | a.remainder(b)
- * ------+-----+---------------+---------+-------------+---------------
- * 13 | 4 | 3, 1 | 3 | 1 | 1
- * ------+-----+---------------+---------+-------------+---------------
- * 13 | -4 | -4, -3 | -3 | -3 | 1
- * ------+-----+---------------+---------+-------------+---------------
- * -13 | 4 | -4, 3 | -4 | 3 | -1
- * ------+-----+---------------+---------+-------------+---------------
- * -13 | -4 | 3, -1 | 3 | -1 | -1
- * ------+-----+---------------+---------+-------------+---------------
- * 11.5 | 4 | 2.0, 3.5 | 2.875 | 3.5 | 3.5
- * ------+-----+---------------+---------+-------------+---------------
- * 11.5 | -4 | -3.0, -0.5 | -2.875 | -0.5 | 3.5
- * ------+-----+---------------+---------+-------------+---------------
- * -11.5 | 4 | -3.0 0.5 | -2.875 | 0.5 | -3.5
- * ------+-----+---------------+---------+-------------+---------------
- * -11.5 | -4 | 2.0 -3.5 | 2.875 | -3.5 | -3.5
- *
- *
- * Examples
- * 11.divmod(3) #=> [3, 2]
- * 11.divmod(-3) #=> [-4, -1]
- * 11.divmod(3.5) #=> [3.0, 0.5]
- * (-11).divmod(3.5) #=> [-4.0, 3.0]
- * (11.5).divmod(3.5) #=> [3.0, 1.0]
- */
-
-static VALUE
-num_divmod(x, y)
- VALUE x, y;
-{
- return rb_assoc_new(num_div(x, y), rb_funcall(x, '%', 1, y));
-}
-
-/*
- * call-seq:
- * num.modulo(numeric) => result
- *
- * Equivalent to
- * <i>num</i>.<code>divmod(</code><i>aNumeric</i><code>)[1]</code>.
- */
-
-static VALUE
-num_modulo(x, y)
- VALUE x, y;
-{
- return rb_funcall(x, '%', 1, y);
-}
-
-/*
- * call-seq:
- * num.remainder(numeric) => result
- *
- * If <i>num</i> and <i>numeric</i> have different signs, returns
- * <em>mod</em>-<i>numeric</i>; otherwise, returns <em>mod</em>. In
- * both cases <em>mod</em> is the value
- * <i>num</i>.<code>modulo(</code><i>numeric</i><code>)</code>. The
- * differences between <code>remainder</code> and modulo
- * (<code>%</code>) are shown in the table under <code>Numeric#divmod</code>.
- */
-
-static VALUE
-num_remainder(x, y)
- VALUE x, y;
-{
- VALUE z = rb_funcall(x, '%', 1, y);
-
- if ((!rb_equal(z, INT2FIX(0))) &&
- ((RTEST(rb_funcall(x, '<', 1, INT2FIX(0))) &&
- RTEST(rb_funcall(y, '>', 1, INT2FIX(0)))) ||
- (RTEST(rb_funcall(x, '>', 1, INT2FIX(0))) &&
- RTEST(rb_funcall(y, '<', 1, INT2FIX(0)))))) {
- return rb_funcall(z, '-', 1, y);
- }
- return z;
-}
-
-/*
- * call-seq:
- * num.integer? -> true or false
- *
- * Returns <code>true</code> if <i>num</i> is an <code>Integer</code>
- * (including <code>Fixnum</code> and <code>Bignum</code>).
- */
-
-static VALUE
-num_int_p(num)
- VALUE num;
-{
- return Qfalse;
-}
-
-/*
- * call-seq:
- * num.abs => num or numeric
- *
- * Returns the absolute value of <i>num</i>.
- *
- * 12.abs #=> 12
- * (-34.56).abs #=> 34.56
- * -34.56.abs #=> 34.56
- */
-
-static VALUE
-num_abs(num)
- VALUE num;
-{
- if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) {
- return rb_funcall(num, rb_intern("-@"), 0);
- }
- return num;
-}
-
-
-/*
- * call-seq:
- * num.zero? => true or false
- *
- * Returns <code>true</code> if <i>num</i> has a zero value.
- */
-
-static VALUE
-num_zero_p(num)
- VALUE num;
-{
- if (rb_equal(num, INT2FIX(0))) {
- return Qtrue;
- }
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * num.nonzero? => num or nil
- *
- * Returns <i>num</i> if <i>num</i> is not zero, <code>nil</code>
- * otherwise. This behavior is useful when chaining comparisons:
- *
- * a = %w( z Bb bB bb BB a aA Aa AA A )
- * b = a.sort {|a,b| (a.downcase <=> b.downcase).nonzero? || a <=> b }
- * b #=> ["A", "a", "AA", "Aa", "aA", "BB", "Bb", "bB", "bb", "z"]
- */
-
-static VALUE
-num_nonzero_p(num)
- VALUE num;
-{
- if (RTEST(rb_funcall(num, rb_intern("zero?"), 0, 0))) {
- return Qnil;
- }
- return num;
-}
-
-/*
- * call-seq:
- * num.to_int => integer
- *
- * Invokes the child class's <code>to_i</code> method to convert
- * <i>num</i> to an integer.
- */
-
-static VALUE
-num_to_int(num)
- VALUE num;
-{
- return rb_funcall(num, id_to_i, 0, 0);
-}
-
-
-/********************************************************************
- *
- * Document-class: Float
- *
- * <code>Float</code> objects represent real numbers using the native
- * architecture's double-precision floating point representation.
- */
-
-VALUE
-rb_float_new(d)
- double d;
-{
- NEWOBJ(flt, struct RFloat);
- OBJSETUP(flt, rb_cFloat, T_FLOAT);
-
- flt->value = d;
- return (VALUE)flt;
-}
-
-/*
- * call-seq:
- * flt.to_s => string
- *
- * Returns a string containing a representation of self. As well as a
- * fixed or exponential form of the number, the call may return
- * ``<code>NaN</code>'', ``<code>Infinity</code>'', and
- * ``<code>-Infinity</code>''.
- */
-
-static VALUE
-flo_to_s(flt)
- VALUE flt;
-{
- char buf[32];
- double value = RFLOAT(flt)->value;
- char *p, *e;
-
- if (isinf(value))
- return rb_str_new2(value < 0 ? "-Infinity" : "Infinity");
- else if(isnan(value))
- return rb_str_new2("NaN");
-
- sprintf(buf, "%#.15g", value); /* ensure to print decimal point */
- if (!(e = strchr(buf, 'e'))) {
- e = buf + strlen(buf);
- }
- if (!ISDIGIT(e[-1])) { /* reformat if ended with decimal point (ex 111111111111111.) */
- sprintf(buf, "%#.14e", value);
- if (!(e = strchr(buf, 'e'))) {
- e = buf + strlen(buf);
- }
- }
- p = e;
- while (p[-1]=='0' && ISDIGIT(p[-2]))
- p--;
- memmove(p, e, strlen(e)+1);
- return rb_str_new2(buf);
-}
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-flo_coerce(x, y)
- VALUE x, y;
-{
- return rb_assoc_new(rb_Float(y), x);
-}
-
-/*
- * call-seq:
- * -float => float
- *
- * Returns float, negated.
- */
-
-static VALUE
-flo_uminus(flt)
- VALUE flt;
-{
- return rb_float_new(-RFLOAT(flt)->value);
-}
-
-/*
- * call-seq:
- * float + other => float
- *
- * Returns a new float which is the sum of <code>float</code>
- * and <code>other</code>.
- */
-
-static VALUE
-flo_plus(x, y)
- VALUE x, y;
-{
- switch (TYPE(y)) {
- case T_FIXNUM:
- return rb_float_new(RFLOAT(x)->value + (double)FIX2LONG(y));
- case T_BIGNUM:
- return rb_float_new(RFLOAT(x)->value + rb_big2dbl(y));
- case T_FLOAT:
- return rb_float_new(RFLOAT(x)->value + RFLOAT(y)->value);
- default:
- return rb_num_coerce_bin(x, y);
- }
-}
-
-/*
- * call-seq:
- * float + other => float
- *
- * Returns a new float which is the difference of <code>float</code>
- * and <code>other</code>.
- */
-
-static VALUE
-flo_minus(x, y)
- VALUE x, y;
-{
- switch (TYPE(y)) {
- case T_FIXNUM:
- return rb_float_new(RFLOAT(x)->value - (double)FIX2LONG(y));
- case T_BIGNUM:
- return rb_float_new(RFLOAT(x)->value - rb_big2dbl(y));
- case T_FLOAT:
- return rb_float_new(RFLOAT(x)->value - RFLOAT(y)->value);
- default:
- return rb_num_coerce_bin(x, y);
- }
-}
-
-/*
- * call-seq:
- * float * other => float
- *
- * Returns a new float which is the product of <code>float</code>
- * and <code>other</code>.
- */
-
-static VALUE
-flo_mul(x, y)
- VALUE x, y;
-{
- switch (TYPE(y)) {
- case T_FIXNUM:
- return rb_float_new(RFLOAT(x)->value * (double)FIX2LONG(y));
- case T_BIGNUM:
- return rb_float_new(RFLOAT(x)->value * rb_big2dbl(y));
- case T_FLOAT:
- return rb_float_new(RFLOAT(x)->value * RFLOAT(y)->value);
- default:
- return rb_num_coerce_bin(x, y);
- }
-}
-
-/*
- * call-seq:
- * float / other => float
- *
- * Returns a new float which is the result of dividing
- * <code>float</code> by <code>other</code>.
- */
-
-static VALUE
-flo_div(x, y)
- VALUE x, y;
-{
- long f_y;
- double d;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- f_y = FIX2LONG(y);
- return rb_float_new(RFLOAT(x)->value / (double)f_y);
- case T_BIGNUM:
- d = rb_big2dbl(y);
- return rb_float_new(RFLOAT(x)->value / d);
- case T_FLOAT:
- return rb_float_new(RFLOAT(x)->value / RFLOAT(y)->value);
- default:
- return rb_num_coerce_bin(x, y);
- }
-}
-
-
-static void
-flodivmod(x, y, divp, modp)
- double x, y;
- double *divp, *modp;
-{
- double div, mod;
-
-#ifdef HAVE_FMOD
- mod = fmod(x, y);
-#else
- {
- double z;
-
- modf(x/y, &z);
- mod = x - z * y;
- }
-#endif
- div = (x - mod) / y;
- if (y*mod < 0) {
- mod += y;
- div -= 1.0;
- }
- if (modp) *modp = mod;
- if (divp) *divp = div;
-}
-
-
-/*
- * call-seq:
- * flt % other => float
- * flt.modulo(other) => float
- *
- * Return the modulo after division of <code>flt</code> by <code>other</code>.
- *
- * 6543.21.modulo(137) #=> 104.21
- * 6543.21.modulo(137.24) #=> 92.9299999999996
- */
-
-static VALUE
-flo_mod(x, y)
- VALUE x, y;
-{
- double fy, mod;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- fy = (double)FIX2LONG(y);
- break;
- case T_BIGNUM:
- fy = rb_big2dbl(y);
- break;
- case T_FLOAT:
- fy = RFLOAT(y)->value;
- break;
- default:
- return rb_num_coerce_bin(x, y);
- }
- flodivmod(RFLOAT(x)->value, fy, 0, &mod);
- return rb_float_new(mod);
-}
-
-/*
- * call-seq:
- * flt.divmod(numeric) => array
- *
- * See <code>Numeric#divmod</code>.
- */
-
-static VALUE
-flo_divmod(x, y)
- VALUE x, y;
-{
- double fy, div, mod;
- volatile VALUE a, b;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- fy = (double)FIX2LONG(y);
- break;
- case T_BIGNUM:
- fy = rb_big2dbl(y);
- break;
- case T_FLOAT:
- fy = RFLOAT(y)->value;
- break;
- default:
- return rb_num_coerce_bin(x, y);
- }
- flodivmod(RFLOAT(x)->value, fy, &div, &mod);
- a = rb_float_new(div);
- b = rb_float_new(mod);
- return rb_assoc_new(a, b);
-}
-
-/*
- * call-seq:
- *
- * flt ** other => float
- *
- * Raises <code>float</code> the <code>other</code> power.
- */
-
-static VALUE
-flo_pow(x, y)
- VALUE x, y;
-{
- switch (TYPE(y)) {
- case T_FIXNUM:
- return rb_float_new(pow(RFLOAT(x)->value, (double)FIX2LONG(y)));
- case T_BIGNUM:
- return rb_float_new(pow(RFLOAT(x)->value, rb_big2dbl(y)));
- case T_FLOAT:
- return rb_float_new(pow(RFLOAT(x)->value, RFLOAT(y)->value));
- default:
- return rb_num_coerce_bin(x, y);
- }
-}
-
-/*
- * call-seq:
- * num.eql?(numeric) => true or false
- *
- * Returns <code>true</code> if <i>num</i> and <i>numeric</i> are the
- * same type and have equal values.
- *
- * 1 == 1.0 #=> true
- * 1.eql?(1.0) #=> false
- * (1.0).eql?(1.0) #=> true
- */
-
-static VALUE
-num_eql(x, y)
- VALUE x, y;
-{
- if (TYPE(x) != TYPE(y)) return Qfalse;
-
- return rb_equal(x, y);
-}
-
-/*
- * call-seq:
- * num <=> other -> 0 or nil
- *
- * Returns zero if <i>num</i> equals <i>other</i>, <code>nil</code>
- * otherwise.
- */
-
-static VALUE
-num_cmp(x, y)
- VALUE x, y;
-{
- if (x == y) return INT2FIX(0);
- return Qnil;
-}
-
-static VALUE
-num_equal(x, y)
- VALUE x, y;
-{
- if (x == y) return Qtrue;
- return rb_funcall(y, id_eq, 1, x);
-}
-
-/*
- * call-seq:
- * flt == obj => true or false
- *
- * Returns <code>true</code> only if <i>obj</i> has the same value
- * as <i>flt</i>. Contrast this with <code>Float#eql?</code>, which
- * requires <i>obj</i> to be a <code>Float</code>.
- *
- * 1.0 == 1 #=> true
- *
- */
-
-static VALUE
-flo_eq(x, y)
- VALUE x, y;
-{
- volatile double a, b;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- b = FIX2LONG(y);
- break;
- case T_BIGNUM:
- b = rb_big2dbl(y);
- break;
- case T_FLOAT:
- b = RFLOAT(y)->value;
- break;
- default:
- return num_equal(x, y);
- }
- a = RFLOAT(x)->value;
- if (isnan(a) || isnan(b)) return Qfalse;
- return (a == b)?Qtrue:Qfalse;
-}
-
-/*
- * call-seq:
- * flt.hash => integer
- *
- * Returns a hash code for this float.
- */
-
-static VALUE
-flo_hash(num)
- VALUE num;
-{
- double d;
- char *c;
- int i, hash;
-
- d = RFLOAT(num)->value;
- if (d == 0) d = fabs(d);
- c = (char*)&d;
- for (hash=0, i=0; i<sizeof(double);i++) {
- hash += c[i] * 971;
- }
- if (hash < 0) hash = -hash;
- return INT2FIX(hash);
-}
-
-VALUE
-rb_dbl_cmp(a, b)
- double a, b;
-{
- if (isnan(a) || isnan(b)) return Qnil;
- if (a == b) return INT2FIX(0);
- if (a > b) return INT2FIX(1);
- if (a < b) return INT2FIX(-1);
- return Qnil;
-}
-
-/*
- * call-seq:
- * flt <=> numeric => -1, 0, +1
- *
- * Returns -1, 0, or +1 depending on whether <i>flt</i> is less than,
- * equal to, or greater than <i>numeric</i>. This is the basis for the
- * tests in <code>Comparable</code>.
- */
-
-static VALUE
-flo_cmp(x, y)
- VALUE x, y;
-{
- double a, b;
-
- a = RFLOAT(x)->value;
- switch (TYPE(y)) {
- case T_FIXNUM:
- b = (double)FIX2LONG(y);
- break;
-
- case T_BIGNUM:
- b = rb_big2dbl(y);
- break;
-
- case T_FLOAT:
- b = RFLOAT(y)->value;
- break;
-
- default:
- return rb_num_coerce_cmp(x, y);
- }
- return rb_dbl_cmp(a, b);
-}
-
-/*
- * call-seq:
- * flt > other => true or false
- *
- * <code>true</code> if <code>flt</code> is greater than <code>other</code>.
- */
-
-static VALUE
-flo_gt(x, y)
- VALUE x, y;
-{
- double a, b;
-
- a = RFLOAT(x)->value;
- switch (TYPE(y)) {
- case T_FIXNUM:
- b = (double)FIX2LONG(y);
- break;
-
- case T_BIGNUM:
- b = rb_big2dbl(y);
- break;
-
- case T_FLOAT:
- b = RFLOAT(y)->value;
- break;
-
- default:
- return rb_num_coerce_relop(x, y);
- }
- if (isnan(a) || isnan(b)) return Qfalse;
- return (a > b)?Qtrue:Qfalse;
-}
-
-/*
- * call-seq:
- * flt >= other => true or false
- *
- * <code>true</code> if <code>flt</code> is greater than
- * or equal to <code>other</code>.
- */
-
-static VALUE
-flo_ge(x, y)
- VALUE x, y;
-{
- double a, b;
-
- a = RFLOAT(x)->value;
- switch (TYPE(y)) {
- case T_FIXNUM:
- b = (double)FIX2LONG(y);
- break;
-
- case T_BIGNUM:
- b = rb_big2dbl(y);
- break;
-
- case T_FLOAT:
- b = RFLOAT(y)->value;
- break;
-
- default:
- return rb_num_coerce_relop(x, y);
- }
- if (isnan(a) || isnan(b)) return Qfalse;
- return (a >= b)?Qtrue:Qfalse;
-}
-
-/*
- * call-seq:
- * flt < other => true or false
- *
- * <code>true</code> if <code>flt</code> is less than <code>other</code>.
- */
-
-static VALUE
-flo_lt(x, y)
- VALUE x, y;
-{
- double a, b;
-
- a = RFLOAT(x)->value;
- switch (TYPE(y)) {
- case T_FIXNUM:
- b = (double)FIX2LONG(y);
- break;
-
- case T_BIGNUM:
- b = rb_big2dbl(y);
- break;
-
- case T_FLOAT:
- b = RFLOAT(y)->value;
- break;
-
- default:
- return rb_num_coerce_relop(x, y);
- }
- if (isnan(a) || isnan(b)) return Qfalse;
- return (a < b)?Qtrue:Qfalse;
-}
-
-/*
- * call-seq:
- * flt <= other => true or false
- *
- * <code>true</code> if <code>flt</code> is less than
- * or equal to <code>other</code>.
- */
-
-static VALUE
-flo_le(x, y)
- VALUE x, y;
-{
- double a, b;
-
- a = RFLOAT(x)->value;
- switch (TYPE(y)) {
- case T_FIXNUM:
- b = (double)FIX2LONG(y);
- break;
-
- case T_BIGNUM:
- b = rb_big2dbl(y);
- break;
-
- case T_FLOAT:
- b = RFLOAT(y)->value;
- break;
-
- default:
- return rb_num_coerce_relop(x, y);
- }
- if (isnan(a) || isnan(b)) return Qfalse;
- return (a <= b)?Qtrue:Qfalse;
-}
-
-/*
- * call-seq:
- * flt.eql?(obj) => true or false
- *
- * Returns <code>true</code> only if <i>obj</i> is a
- * <code>Float</code> with the same value as <i>flt</i>. Contrast this
- * with <code>Float#==</code>, which performs type conversions.
- *
- * 1.0.eql?(1) #=> false
- */
-
-static VALUE
-flo_eql(x, y)
- VALUE x, y;
-{
- if (TYPE(y) == T_FLOAT) {
- double a = RFLOAT(x)->value;
- double b = RFLOAT(y)->value;
-
- if (isnan(a) || isnan(b)) return Qfalse;
- if (a == b) return Qtrue;
- }
- return Qfalse;
-}
-
-/*
- * call-seq:
- * flt.to_f => flt
- *
- * As <code>flt</code> is already a float, returns <i>self</i>.
- */
-
-static VALUE
-flo_to_f(num)
- VALUE num;
-{
- return num;
-}
-
-/*
- * call-seq:
- * flt.abs => float
- *
- * Returns the absolute value of <i>flt</i>.
- *
- * (-34.56).abs #=> 34.56
- * -34.56.abs #=> 34.56
- *
- */
-
-static VALUE
-flo_abs(flt)
- VALUE flt;
-{
- double val = fabs(RFLOAT(flt)->value);
- return rb_float_new(val);
-}
-
-/*
- * call-seq:
- * flt.zero? -> true or false
- *
- * Returns <code>true</code> if <i>flt</i> is 0.0.
- *
- */
-
-static VALUE
-flo_zero_p(num)
- VALUE num;
-{
- if (RFLOAT(num)->value == 0.0) {
- return Qtrue;
- }
- return Qfalse;
-}
-
-/*
- * call-seq:
- * flt.nan? -> true or false
- *
- * Returns <code>true</code> if <i>flt</i> is an invalid IEEE floating
- * point number.
- *
- * a = -1.0 #=> -1.0
- * a.nan? #=> false
- * a = 0.0/0.0 #=> NaN
- * a.nan? #=> true
- */
-
-static VALUE
-flo_is_nan_p(num)
- VALUE num;
-{
- double value = RFLOAT(num)->value;
-
- return isnan(value) ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- * flt.infinite? -> nil, -1, +1
- *
- * Returns <code>nil</code>, -1, or +1 depending on whether <i>flt</i>
- * is finite, -infinity, or +infinity.
- *
- * (0.0).infinite? #=> nil
- * (-1.0/0.0).infinite? #=> -1
- * (+1.0/0.0).infinite? #=> 1
- */
-
-static VALUE
-flo_is_infinite_p(num)
- VALUE num;
-{
- double value = RFLOAT(num)->value;
-
- if (isinf(value)) {
- return INT2FIX( value < 0 ? -1 : 1 );
- }
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * flt.finite? -> true or false
- *
- * Returns <code>true</code> if <i>flt</i> is a valid IEEE floating
- * point number (it is not infinite, and <code>nan?</code> is
- * <code>false</code>).
- *
- */
-
-static VALUE
-flo_is_finite_p(num)
- VALUE num;
-{
- double value = RFLOAT(num)->value;
-
-#if HAVE_FINITE
- if (!finite(value))
- return Qfalse;
-#else
- if (isinf(value) || isnan(value))
- return Qfalse;
-#endif
-
- return Qtrue;
-}
-
-/*
- * call-seq:
- * flt.floor => integer
- *
- * Returns the largest integer less than or equal to <i>flt</i>.
- *
- * 1.2.floor #=> 1
- * 2.0.floor #=> 2
- * (-1.2).floor #=> -2
- * (-2.0).floor #=> -2
- */
-
-static VALUE
-flo_floor(num)
- VALUE num;
-{
- double f = floor(RFLOAT(num)->value);
- long val;
-
- if (!FIXABLE(f)) {
- return rb_dbl2big(f);
- }
- val = f;
- return LONG2FIX(val);
-}
-
-/*
- * call-seq:
- * flt.ceil => integer
- *
- * Returns the smallest <code>Integer</code> greater than or equal to
- * <i>flt</i>.
- *
- * 1.2.ceil #=> 2
- * 2.0.ceil #=> 2
- * (-1.2).ceil #=> -1
- * (-2.0).ceil #=> -2
- */
-
-static VALUE
-flo_ceil(num)
- VALUE num;
-{
- double f = ceil(RFLOAT(num)->value);
- long val;
-
- if (!FIXABLE(f)) {
- return rb_dbl2big(f);
- }
- val = f;
- return LONG2FIX(val);
-}
-
-/*
- * call-seq:
- * flt.round => integer
- *
- * Rounds <i>flt</i> to the nearest integer. Equivalent to:
- *
- * def round
- * return floor(self+0.5) if self > 0.0
- * return ceil(self-0.5) if self < 0.0
- * return 0.0
- * end
- *
- * 1.5.round #=> 2
- * (-1.5).round #=> -2
- *
- */
-
-static VALUE
-flo_round(num)
- VALUE num;
-{
- double f = RFLOAT(num)->value;
- long val;
-
- if (f > 0.0) f = floor(f+0.5);
- if (f < 0.0) f = ceil(f-0.5);
-
- if (!FIXABLE(f)) {
- return rb_dbl2big(f);
- }
- val = f;
- return LONG2FIX(val);
-}
-
-/*
- * call-seq:
- * flt.to_i => integer
- * flt.to_int => integer
- * flt.truncate => integer
- *
- * Returns <i>flt</i> truncated to an <code>Integer</code>.
- */
-
-static VALUE
-flo_truncate(num)
- VALUE num;
-{
- double f = RFLOAT(num)->value;
- long val;
-
- if (f > 0.0) f = floor(f);
- if (f < 0.0) f = ceil(f);
-
- if (!FIXABLE(f)) {
- return rb_dbl2big(f);
- }
- val = f;
- return LONG2FIX(val);
-}
-
-
-/*
- * call-seq:
- * num.floor => integer
- *
- * Returns the largest integer less than or equal to <i>num</i>.
- * <code>Numeric</code> implements this by converting <i>anInteger</i>
- * to a <code>Float</code> and invoking <code>Float#floor</code>.
- *
- * 1.floor #=> 1
- * (-1).floor #=> -1
- */
-
-static VALUE
-num_floor(num)
- VALUE num;
-{
- return flo_floor(rb_Float(num));
-}
-
-
-/*
- * call-seq:
- * num.ceil => integer
- *
- * Returns the smallest <code>Integer</code> greater than or equal to
- * <i>num</i>. Class <code>Numeric</code> achieves this by converting
- * itself to a <code>Float</code> then invoking
- * <code>Float#ceil</code>.
- *
- * 1.ceil #=> 1
- * 1.2.ceil #=> 2
- * (-1.2).ceil #=> -1
- * (-1.0).ceil #=> -1
- */
-
-static VALUE
-num_ceil(num)
- VALUE num;
-{
- return flo_ceil(rb_Float(num));
-}
-
-/*
- * call-seq:
- * num.round => integer
- *
- * Rounds <i>num</i> to the nearest integer. <code>Numeric</code>
- * implements this by converting itself to a
- * <code>Float</code> and invoking <code>Float#round</code>.
- */
-
-static VALUE
-num_round(num)
- VALUE num;
-{
- return flo_round(rb_Float(num));
-}
-
-/*
- * call-seq:
- * num.truncate => integer
- *
- * Returns <i>num</i> truncated to an integer. <code>Numeric</code>
- * implements this by converting its value to a float and invoking
- * <code>Float#truncate</code>.
- */
-
-static VALUE
-num_truncate(num)
- VALUE num;
-{
- return flo_truncate(rb_Float(num));
-}
-
-
-/*
- * call-seq:
- * num.step(limit, step ) {|i| block } => num
- *
- * Invokes <em>block</em> with the sequence of numbers starting at
- * <i>num</i>, incremented by <i>step</i> on each call. The loop
- * finishes when the value to be passed to the block is greater than
- * <i>limit</i> (if <i>step</i> is positive) or less than
- * <i>limit</i> (if <i>step</i> is negative). If all the arguments are
- * integers, the loop operates using an integer counter. If any of the
- * arguments are floating point numbers, all are converted to floats,
- * and the loop is executed <i>floor(n + n*epsilon)+ 1</i> times,
- * where <i>n = (limit - num)/step</i>. Otherwise, the loop
- * starts at <i>num</i>, uses either the <code><</code> or
- * <code>></code> operator to compare the counter against
- * <i>limit</i>, and increments itself using the <code>+</code>
- * operator.
- *
- * 1.step(10, 2) { |i| print i, " " }
- * Math::E.step(Math::PI, 0.2) { |f| print f, " " }
- *
- * <em>produces:</em>
- *
- * 1 3 5 7 9
- * 2.71828182845905 2.91828182845905 3.11828182845905
- */
-
-static VALUE
-num_step(argc, argv, from)
- int argc;
- VALUE *argv;
- VALUE from;
-{
- VALUE to, step;
-
- if (argc == 1) {
- to = argv[0];
- step = INT2FIX(1);
- }
- else {
- if (argc == 2) {
- to = argv[0];
- step = argv[1];
- }
- else {
- rb_raise(rb_eArgError, "wrong number of arguments");
- }
- if (rb_equal(step, INT2FIX(0))) {
- rb_raise(rb_eArgError, "step can't be 0");
- }
- }
-
- if (FIXNUM_P(from) && FIXNUM_P(to) && FIXNUM_P(step)) {
- long i, end, diff;
-
- i = FIX2LONG(from);
- end = FIX2LONG(to);
- diff = FIX2LONG(step);
-
- if (diff > 0) {
- while (i <= end) {
- rb_yield(LONG2FIX(i));
- i += diff;
- }
- }
- else {
- while (i >= end) {
- rb_yield(LONG2FIX(i));
- i += diff;
- }
- }
- }
- else if (TYPE(from) == T_FLOAT || TYPE(to) == T_FLOAT || TYPE(step) == T_FLOAT) {
- const double epsilon = DBL_EPSILON;
- double beg = NUM2DBL(from);
- double end = NUM2DBL(to);
- double unit = NUM2DBL(step);
- double n = (end - beg)/unit;
- double err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon;
- long i;
-
- if (err>0.5) err=0.5;
- n = floor(n + err) + 1;
- for (i=0; i<n; i++) {
- rb_yield(rb_float_new(i*unit+beg));
- }
- }
- else {
- VALUE i = from;
- ID cmp;
-
- if (RTEST(rb_funcall(step, '>', 1, INT2FIX(0)))) {
- cmp = '>';
- }
- else {
- cmp = '<';
- }
- for (;;) {
- if (RTEST(rb_funcall(i, cmp, 1, to))) break;
- rb_yield(i);
- i = rb_funcall(i, '+', 1, step);
- }
- }
- return from;
-}
-
-long
-rb_num2long(val)
- VALUE val;
-{
- if (NIL_P(val)) {
- rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
- }
-
- if (FIXNUM_P(val)) return FIX2LONG(val);
-
- switch (TYPE(val)) {
- case T_FLOAT:
- if (RFLOAT(val)->value <= (double)LONG_MAX
- && RFLOAT(val)->value >= (double)LONG_MIN) {
- return (long)(RFLOAT(val)->value);
- }
- else {
- char buf[24];
- char *s;
-
- sprintf(buf, "%-.10g", RFLOAT(val)->value);
- if (s = strchr(buf, ' ')) *s = '\0';
- rb_raise(rb_eRangeError, "float %s out of range of integer", buf);
- }
-
- case T_BIGNUM:
- return rb_big2long(val);
-
- default:
- val = rb_to_int(val);
- return NUM2LONG(val);
- }
-}
-
-unsigned long
-rb_num2ulong(val)
- VALUE val;
-{
- if (TYPE(val) == T_BIGNUM) {
- return rb_big2ulong(val);
- }
- return (unsigned long)rb_num2long(val);
-}
-
-#if SIZEOF_INT < SIZEOF_LONG
-static void
-check_int(num)
- long num;
-{
- const char *s;
-
- if (num < INT_MIN) {
- s = "small";
- }
- else if (num > INT_MAX) {
- s = "big";
- }
- else {
- return;
- }
- rb_raise(rb_eRangeError, "integer %ld too %s to convert to `int'", num, s);
-}
-
-static void
-check_uint(num)
- unsigned long num;
-{
- if (num > UINT_MAX) {
- rb_raise(rb_eRangeError, "integer %lu too big to convert to `unsigned int'", num);
- }
-}
-
-long
-rb_num2int(val)
- VALUE val;
-{
- long num = rb_num2long(val);
-
- check_int(num);
- return num;
-}
-
-long
-rb_fix2int(val)
- VALUE val;
-{
- long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2long(val);
-
- check_int(num);
- return num;
-}
-
-unsigned long
-rb_num2uint(val)
- VALUE val;
-{
- unsigned long num = rb_num2ulong(val);
-
- if (RTEST(rb_funcall(INT2FIX(0), '<', 1, val))) {
- check_uint(num);
- }
- return num;
-}
-
-unsigned long
-rb_fix2uint(val)
- VALUE val;
-{
- unsigned long num;
-
- if (!FIXNUM_P(val)) {
- return rb_num2uint(val);
- }
- num = FIX2ULONG(val);
- if (FIX2LONG(val) > 0) {
- check_uint(num);
- }
- return num;
-}
-#else
-long
-rb_num2int(val)
- VALUE val;
-{
- return rb_num2long(val);
-}
-
-long
-rb_fix2int(val)
- VALUE val;
-{
- return FIX2INT(val);
-}
-#endif
-
-VALUE
-rb_num2fix(val)
- VALUE val;
-{
- long v;
-
- if (FIXNUM_P(val)) return val;
-
- v = rb_num2long(val);
- if (!FIXABLE(v))
- rb_raise(rb_eRangeError, "integer %ld out of range of fixnum", v);
- return LONG2FIX(v);
-}
-
-#if HAVE_LONG_LONG
-
-LONG_LONG
-rb_num2ll(val)
- VALUE val;
-{
- if (NIL_P(val)) {
- rb_raise(rb_eTypeError, "no implicit conversion from nil");
- }
-
- if (FIXNUM_P(val)) return (LONG_LONG)FIX2LONG(val);
-
- switch (TYPE(val)) {
- case T_FLOAT:
- if (RFLOAT(val)->value <= (double)LLONG_MAX
- && RFLOAT(val)->value >= (double)LLONG_MIN) {
- return (LONG_LONG)(RFLOAT(val)->value);
- }
- else {
- char buf[24];
- char *s;
-
- sprintf(buf, "%-.10g", RFLOAT(val)->value);
- if (s = strchr(buf, ' ')) *s = '\0';
- rb_raise(rb_eRangeError, "float %s out of range of long long", buf);
- }
-
- case T_BIGNUM:
- return rb_big2ll(val);
-
- case T_STRING:
- rb_raise(rb_eTypeError, "no implicit conversion from string");
- return Qnil; /* not reached */
-
- case T_TRUE:
- case T_FALSE:
- rb_raise(rb_eTypeError, "no implicit conversion from boolean");
- return Qnil; /* not reached */
-
- default:
- val = rb_to_int(val);
- return NUM2LL(val);
- }
-}
-
-unsigned LONG_LONG
-rb_num2ull(val)
- VALUE val;
-{
- if (TYPE(val) == T_BIGNUM) {
- return rb_big2ull(val);
- }
- return (unsigned LONG_LONG)rb_num2ll(val);
-}
-
-#endif /* HAVE_LONG_LONG */
-
-
-/*
- * Document-class: Integer
- *
- * <code>Integer</code> is the basis for the two concrete classes that
- * hold whole numbers, <code>Bignum</code> and <code>Fixnum</code>.
- *
- */
-
-
-/*
- * call-seq:
- * int.to_i => int
- * int.to_int => int
- * int.floor => int
- * int.ceil => int
- * int.round => int
- * int.truncate => int
- *
- * As <i>int</i> is already an <code>Integer</code>, all these
- * methods simply return the receiver.
- */
-
-static VALUE
-int_to_i(num)
- VALUE num;
-{
- return num;
-}
-
-/*
- * call-seq:
- * int.integer? -> true
- *
- * Always returns <code>true</code>.
- */
-
-static VALUE
-int_int_p(num)
- VALUE num;
-{
- return Qtrue;
-}
-
-/*
- * call-seq:
- * int.next => integer
- * int.succ => integer
- *
- * Returns the <code>Integer</code> equal to <i>int</i> + 1.
- *
- * 1.next #=> 2
- * (-1).next #=> 0
- */
-
-static VALUE
-int_succ(num)
- VALUE num;
-{
- if (FIXNUM_P(num)) {
- long i = FIX2LONG(num) + 1;
- return LONG2NUM(i);
- }
- return rb_funcall(num, '+', 1, INT2FIX(1));
-}
-
-/*
- * call-seq:
- * int.chr => string
- *
- * Returns a string containing the ASCII character represented by the
- * receiver's value.
- *
- * 65.chr #=> "A"
- * ?a.chr #=> "a"
- * 230.chr #=> "\346"
- */
-
-static VALUE
-int_chr(num)
- VALUE num;
-{
- char c;
- long i = NUM2LONG(num);
-
- if (i < 0 || 0xff < i)
- rb_raise(rb_eRangeError, "%ld out of char range", i);
- c = i;
- return rb_str_new(&c, 1);
-}
-
-/********************************************************************
- *
- * Document-class: Fixnum
- *
- * A <code>Fixnum</code> holds <code>Integer</code> values that can be
- * represented in a native machine word (minus 1 bit). If any operation
- * on a <code>Fixnum</code> exceeds this range, the value is
- * automatically converted to a <code>Bignum</code>.
- *
- * <code>Fixnum</code> objects have immediate value. This means that
- * when they are assigned or passed as parameters, the actual object is
- * passed, rather than a reference to that object. Assignment does not
- * alias <code>Fixnum</code> objects. There is effectively only one
- * <code>Fixnum</code> object instance for any given integer value, so,
- * for example, you cannot add a singleton method to a
- * <code>Fixnum</code>.
- */
-
-
-/*
- * call-seq:
- * Fixnum.induced_from(obj) => fixnum
- *
- * Convert <code>obj</code> to a Fixnum. Works with numeric parameters.
- * Also works with Symbols, but this is deprecated.
- */
-
-static VALUE
-rb_fix_induced_from(klass, x)
- VALUE klass, x;
-{
- return rb_num2fix(x);
-}
-
-/*
- * call-seq:
- * Integer.induced_from(obj) => fixnum, bignum
- *
- * Convert <code>obj</code> to an Integer.
- */
-
-static VALUE
-rb_int_induced_from(klass, x)
- VALUE klass, x;
-{
- switch (TYPE(x)) {
- case T_FIXNUM:
- case T_BIGNUM:
- return x;
- case T_FLOAT:
- return rb_funcall(x, id_to_i, 0);
- default:
- rb_raise(rb_eTypeError, "failed to convert %s into Integer",
- rb_obj_classname(x));
- }
-}
-
-/*
- * call-seq:
- * Float.induced_from(obj) => float
- *
- * Convert <code>obj</code> to a float.
- */
-
-static VALUE
-rb_flo_induced_from(klass, x)
- VALUE klass, x;
-{
- switch (TYPE(x)) {
- case T_FIXNUM:
- case T_BIGNUM:
- return rb_funcall(x, rb_intern("to_f"), 0);
- case T_FLOAT:
- return x;
- default:
- rb_raise(rb_eTypeError, "failed to convert %s into Float",
- rb_obj_classname(x));
- }
-}
-
-/*
- * call-seq:
- * -fix => integer
- *
- * Negates <code>fix</code> (which might return a Bignum).
- */
-
-static VALUE
-fix_uminus(num)
- VALUE num;
-{
- return LONG2NUM(-FIX2LONG(num));
-}
-
-VALUE
-rb_fix2str(x, base)
- VALUE x;
- int base;
-{
- extern const char ruby_digitmap[];
- char buf[SIZEOF_LONG*CHAR_BIT + 2], *b = buf + sizeof buf;
- long val = FIX2LONG(x);
- int neg = 0;
-
- if (base < 2 || 36 < base) {
- rb_raise(rb_eArgError, "illegal radix %d", base);
- }
- if (val == 0) {
- return rb_str_new2("0");
- }
- if (val < 0) {
- val = -val;
- neg = 1;
- }
- *--b = '\0';
- do {
- *--b = ruby_digitmap[(int)(val % base)];
- } while (val /= base);
- if (neg) {
- *--b = '-';
- }
-
- return rb_str_new2(b);
-}
-
-/*
- * call-seq:
- * fix.to_s( base=10 ) -> aString
- *
- * Returns a string containing the representation of <i>fix</i> radix
- * <i>base</i> (between 2 and 36).
- *
- * 12345.to_s #=> "12345"
- * 12345.to_s(2) #=> "11000000111001"
- * 12345.to_s(8) #=> "30071"
- * 12345.to_s(10) #=> "12345"
- * 12345.to_s(16) #=> "3039"
- * 12345.to_s(36) #=> "9ix"
- *
- */
-static VALUE
-fix_to_s(argc, argv, x)
- int argc;
- VALUE *argv;
- VALUE x;
-{
- VALUE b;
- int base;
-
- rb_scan_args(argc, argv, "01", &b);
- if (argc == 0) base = 10;
- else base = NUM2INT(b);
-
- if (base == 2) {
- /* rb_fix2str() does not handle binary */
- return rb_big2str(rb_int2big(FIX2INT(x)), 2);
- }
- return rb_fix2str(x, base);
-}
-
-/*
- * call-seq:
- * fix + numeric => numeric_result
- *
- * Performs addition: the class of the resulting object depends on
- * the class of <code>numeric</code> and on the magnitude of the
- * result.
- */
-
-static VALUE
-fix_plus(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- long a, b, c;
- VALUE r;
-
- a = FIX2LONG(x);
- b = FIX2LONG(y);
- c = a + b;
- r = LONG2FIX(c);
-
- if (FIX2LONG(r) != c) {
- r = rb_big_plus(rb_int2big(a), rb_int2big(b));
- }
- return r;
- }
- if (TYPE(y) == T_FLOAT) {
- return rb_float_new((double)FIX2LONG(x) + RFLOAT(y)->value);
- }
- return rb_num_coerce_bin(x, y);
-}
-
-/*
- * call-seq:
- * fix - numeric => numeric_result
- *
- * Performs subtraction: the class of the resulting object depends on
- * the class of <code>numeric</code> and on the magnitude of the
- * result.
- */
-
-static VALUE
-fix_minus(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- long a, b, c;
- VALUE r;
-
- a = FIX2LONG(x);
- b = FIX2LONG(y);
- c = a - b;
- r = LONG2FIX(c);
-
- if (FIX2LONG(r) != c) {
- r = rb_big_minus(rb_int2big(a), rb_int2big(b));
- }
- return r;
- }
- if (TYPE(y) == T_FLOAT) {
- return rb_float_new((double)FIX2LONG(x) - RFLOAT(y)->value);
- }
- return rb_num_coerce_bin(x, y);
-}
-
-/*
- * call-seq:
- * fix * numeric => numeric_result
- *
- * Performs multiplication: the class of the resulting object depends on
- * the class of <code>numeric</code> and on the magnitude of the
- * result.
- */
-
-static VALUE
-fix_mul(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- long a, b, c;
- VALUE r;
-
- a = FIX2LONG(x);
- if (a == 0) return x;
-
- b = FIX2LONG(y);
- c = a * b;
- r = LONG2FIX(c);
-
- if (FIX2LONG(r) != c || c/a != b) {
- r = rb_big_mul(rb_int2big(a), rb_int2big(b));
- }
- return r;
- }
- if (TYPE(y) == T_FLOAT) {
- return rb_float_new((double)FIX2LONG(x) * RFLOAT(y)->value);
- }
- return rb_num_coerce_bin(x, y);
-}
-
-static void
-fixdivmod(x, y, divp, modp)
- long x, y;
- long *divp, *modp;
-{
- long div, mod;
-
- if (y == 0) rb_num_zerodiv();
- if (y < 0) {
- if (x < 0)
- div = -x / -y;
- else
- div = - (x / -y);
- }
- else {
- if (x < 0)
- div = - (-x / y);
- else
- div = x / y;
- }
- mod = x - div*y;
- if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
- mod += y;
- div -= 1;
- }
- if (divp) *divp = div;
- if (modp) *modp = mod;
-}
-
-/*
- * call-seq:
- * fix.quo(numeric) => float
- *
- * Returns the floating point result of dividing <i>fix</i> by
- * <i>numeric</i>.
- *
- * 654321.quo(13731) #=> 47.6528293642124
- * 654321.quo(13731.24) #=> 47.6519964693647
- *
- */
-
-static VALUE
-fix_quo(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- return rb_float_new((double)FIX2LONG(x) / (double)FIX2LONG(y));
- }
- return rb_num_coerce_bin(x, y);
-}
-
-/*
- * call-seq:
- * fix / numeric => numeric_result
- * fix.div(numeric) => numeric_result
- *
- * Performs division: the class of the resulting object depends on
- * the class of <code>numeric</code> and on the magnitude of the
- * result.
- */
-
-static VALUE
-fix_div(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- long div;
-
- fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, 0);
- return LONG2NUM(div);
- }
- return rb_num_coerce_bin(x, y);
-}
-
-/*
- * call-seq:
- * fix % other => Numeric
- * fix.modulo(other) => Numeric
- *
- * Returns <code>fix</code> modulo <code>other</code>.
- * See <code>Numeric.divmod</code> for more information.
- */
-
-static VALUE
-fix_mod(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- long mod;
-
- fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
- return LONG2NUM(mod);
- }
- return rb_num_coerce_bin(x, y);
-}
-
-/*
- * call-seq:
- * fix.divmod(numeric) => array
- *
- * See <code>Numeric#divmod</code>.
- */
-static VALUE
-fix_divmod(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- long div, mod;
-
- fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, &mod);
-
- return rb_assoc_new(LONG2NUM(div), LONG2NUM(mod));
- }
- return rb_num_coerce_bin(x, y);
-}
-
-/*
- * call-seq:
- * fix ** other => Numeric
- *
- * Raises <code>fix</code> to the <code>other</code> power, which may
- * be negative or fractional.
- *
- * 2 ** 3 #=> 8
- * 2 ** -1 #=> 0.5
- * 2 ** 0.5 #=> 1.4142135623731
- */
-
-static VALUE
-fix_pow(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- long a, b;
-
- b = FIX2LONG(y);
- if (b == 0) return INT2FIX(1);
- if (b == 1) return x;
- a = FIX2LONG(x);
- if (b > 0) {
- return rb_big_pow(rb_int2big(a), y);
- }
- return rb_float_new(pow((double)a, (double)b));
- }
- return rb_num_coerce_bin(x, y);
-}
-
-/*
- * call-seq:
- * fix == other
- *
- * Return <code>true</code> if <code>fix</code> equals <code>other</code>
- * numerically.
- *
- * 1 == 2 #=> false
- * 1 == 1.0 #=> true
- */
-
-static VALUE
-fix_equal(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- return (FIX2LONG(x) == FIX2LONG(y))?Qtrue:Qfalse;
- }
- else {
- return num_equal(x, y);
- }
-}
-
-/*
- * call-seq:
- * fix <=> numeric => -1, 0, +1
- *
- * Comparison---Returns -1, 0, or +1 depending on whether <i>fix</i> is
- * less than, equal to, or greater than <i>numeric</i>. This is the
- * basis for the tests in <code>Comparable</code>.
- */
-
-static VALUE
-fix_cmp(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- long a = FIX2LONG(x), b = FIX2LONG(y);
-
- if (a == b) return INT2FIX(0);
- if (a > b) return INT2FIX(1);
- return INT2FIX(-1);
- }
- else {
- return rb_num_coerce_cmp(x, y);
- }
-}
-
-/*
- * call-seq:
- * fix > other => true or false
- *
- * Returns <code>true</code> if the value of <code>fix</code> is
- * greater than that of <code>other</code>.
- */
-
-static VALUE
-fix_gt(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- long a = FIX2LONG(x), b = FIX2LONG(y);
-
- if (a > b) return Qtrue;
- return Qfalse;
- }
- else {
- return rb_num_coerce_relop(x, y);
- }
-}
-
-/*
- * call-seq:
- * fix >= other => true or false
- *
- * Returns <code>true</code> if the value of <code>fix</code> is
- * greater than or equal to that of <code>other</code>.
- */
-
-static VALUE
-fix_ge(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- long a = FIX2LONG(x), b = FIX2LONG(y);
-
- if (a >= b) return Qtrue;
- return Qfalse;
- }
- else {
- return rb_num_coerce_relop(x, y);
- }
-}
-
-/*
- * call-seq:
- * fix < other => true or false
- *
- * Returns <code>true</code> if the value of <code>fix</code> is
- * less than that of <code>other</code>.
- */
-
-static VALUE
-fix_lt(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- long a = FIX2LONG(x), b = FIX2LONG(y);
-
- if (a < b) return Qtrue;
- return Qfalse;
- }
- else {
- return rb_num_coerce_relop(x, y);
- }
-}
-
-/*
- * call-seq:
- * fix <= other => true or false
- *
- * Returns <code>true</code> if the value of <code>fix</code> is
- * less thanor equal to that of <code>other</code>.
- */
-
-static VALUE
-fix_le(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- long a = FIX2LONG(x), b = FIX2LONG(y);
-
- if (a <= b) return Qtrue;
- return Qfalse;
- }
- else {
- return rb_num_coerce_relop(x, y);
- }
-}
-
-/*
- * call-seq:
- * ~fix => integer
- *
- * One's complement: returns a number where each bit is flipped.
- */
-
-static VALUE
-fix_rev(num)
- VALUE num;
-{
- long val = FIX2LONG(num);
-
- val = ~val;
- return LONG2NUM(val);
-}
-
-/*
- * call-seq:
- * fix & other => integer
- *
- * Bitwise AND.
- */
-
-static VALUE
-fix_and(x, y)
- VALUE x, y;
-{
- long val;
-
- if (TYPE(y) == T_BIGNUM) {
- return rb_big_and(y, x);
- }
- val = FIX2LONG(x) & NUM2LONG(y);
- return LONG2NUM(val);
-}
-
-/*
- * call-seq:
- * fix | other => integer
- *
- * Bitwise OR.
- */
-
-static VALUE
-fix_or(x, y)
- VALUE x, y;
-{
- long val;
-
- if (TYPE(y) == T_BIGNUM) {
- return rb_big_or(y, x);
- }
- val = FIX2LONG(x) | NUM2LONG(y);
- return LONG2NUM(val);
-}
-
-/*
- * call-seq:
- * fix ^ other => integer
- *
- * Bitwise EXCLUSIVE OR.
- */
-
-static VALUE
-fix_xor(x, y)
- VALUE x, y;
-{
- long val;
-
- if (TYPE(y) == T_BIGNUM) {
- return rb_big_xor(y, x);
- }
- val = FIX2LONG(x) ^ NUM2LONG(y);
- return LONG2NUM(val);
-}
-
-static VALUE fix_rshift _((VALUE, VALUE));
-
-/*
- * call-seq:
- * fix << count => integer
- *
- * Shifts _fix_ left _count_ positions (right if _count_ is negative).
- */
-
-static VALUE
-fix_lshift(x, y)
- VALUE x, y;
-{
- long val, width;
-
- val = NUM2LONG(x);
- width = NUM2LONG(y);
- if (width < 0)
- return fix_rshift(x, LONG2FIX(-width));
- if (width > (sizeof(VALUE)*CHAR_BIT-1)
- || ((unsigned long)val)>>(sizeof(VALUE)*CHAR_BIT-1-width) > 0) {
- return rb_big_lshift(rb_int2big(val), y);
- }
- val = val << width;
- return LONG2NUM(val);
-}
-
-/*
- * call-seq:
- * fix >> count => integer
- *
- * Shifts _fix_ left _count_ positions (right if _count_ is negative).
- */
-
-static VALUE
-fix_rshift(x, y)
- VALUE x, y;
-{
- long i, val;
-
- i = NUM2LONG(y);
- if (i < 0)
- return fix_lshift(x, LONG2FIX(-i));
- if (i == 0) return x;
- val = FIX2LONG(x);
- if (i >= sizeof(long)*CHAR_BIT-1) {
- if (val < 0) return INT2FIX(-1);
- return INT2FIX(0);
- }
- val = RSHIFT(val, i);
- return LONG2FIX(val);
-}
-
-/*
- * call-seq:
- * fix[n] => 0, 1
- *
- * Bit Reference---Returns the <em>n</em>th bit in the binary
- * representation of <i>fix</i>, where <i>fix</i>[0] is the least
- * significant bit.
- *
- * a = 0b11001100101010
- * 30.downto(0) do |n| print a[n] end
- *
- * <em>produces:</em>
- *
- * 0000000000000000011001100101010
- */
-
-static VALUE
-fix_aref(fix, idx)
- VALUE fix, idx;
-{
- long val = FIX2LONG(fix);
- long i;
-
- if (TYPE(idx) == T_BIGNUM) {
- idx = rb_big_norm(idx);
- if (!FIXNUM_P(idx)) {
- if (!RBIGNUM(idx)->sign || val >= 0)
- return INT2FIX(0);
- return INT2FIX(1);
- }
- }
- i = NUM2LONG(idx);
-
- if (i < 0) return INT2FIX(0);
- if (sizeof(VALUE)*CHAR_BIT-1 < i) {
- if (val < 0) return INT2FIX(1);
- return INT2FIX(0);
- }
- if (val & (1L<<i))
- return INT2FIX(1);
- return INT2FIX(0);
-}
-
-/*
- * call-seq:
- * fix.to_f -> float
- *
- * Converts <i>fix</i> to a <code>Float</code>.
- *
- */
-
-static VALUE
-fix_to_f(num)
- VALUE num;
-{
- double val;
-
- val = (double)FIX2LONG(num);
-
- return rb_float_new(val);
-}
-
-/*
- * call-seq:
- * fix.abs -> aFixnum
- *
- * Returns the absolute value of <i>fix</i>.
- *
- * -12345.abs #=> 12345
- * 12345.abs #=> 12345
- *
- */
-
-static VALUE
-fix_abs(fix)
- VALUE fix;
-{
- long i = FIX2LONG(fix);
-
- if (i < 0) i = -i;
-
- return LONG2NUM(i);
-}
-
-/*
- * call-seq:
- * fix.id2name -> string or nil
- *
- * Returns the name of the object whose symbol id is <i>fix</i>. If
- * there is no symbol in the symbol table with this value, returns
- * <code>nil</code>. <code>id2name</code> has nothing to do with the
- * <code>Object.id</code> method. See also <code>Fixnum#to_sym</code>,
- * <code>String#intern</code>, and class <code>Symbol</code>.
- *
- * symbol = :@inst_var #=> :@inst_var
- * id = symbol.to_i #=> 9818
- * id.id2name #=> "@inst_var"
- */
-
-static VALUE
-fix_id2name(fix)
- VALUE fix;
-{
- char *name = rb_id2name(FIX2UINT(fix));
- if (name) return rb_str_new2(name);
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * fix.to_sym -> aSymbol
- *
- * Returns the symbol whose integer value is <i>fix</i>. See also
- * <code>Fixnum#id2name</code>.
- *
- * fred = :fred.to_i
- * fred.id2name #=> "fred"
- * fred.to_sym #=> :fred
- */
-
-static VALUE
-fix_to_sym(fix)
- VALUE fix;
-{
- ID id = FIX2UINT(fix);
-
- if (rb_id2name(id)) {
- return ID2SYM(id);
- }
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * fix.size -> fixnum
- *
- * Returns the number of <em>bytes</em> in the machine representation
- * of a <code>Fixnum</code>.
- *
- * 1.size #=> 4
- * -1.size #=> 4
- * 2147483647.size #=> 4
- */
-
-static VALUE
-fix_size(fix)
- VALUE fix;
-{
- return INT2FIX(sizeof(long));
-}
-
-/*
- * call-seq:
- * int.upto(limit) {|i| block } => int
- *
- * Iterates <em>block</em>, passing in integer values from <i>int</i>
- * up to and including <i>limit</i>.
- *
- * 5.upto(10) { |i| print i, " " }
- *
- * <em>produces:</em>
- *
- * 5 6 7 8 9 10
- */
-
-static VALUE
-int_upto(from, to)
- VALUE from, to;
-{
- if (FIXNUM_P(from) && FIXNUM_P(to)) {
- long i, end;
-
- end = FIX2LONG(to);
- for (i = FIX2LONG(from); i <= end; i++) {
- rb_yield(LONG2FIX(i));
- }
- }
- else {
- VALUE i = from, c;
-
- while (!(c = rb_funcall(i, '>', 1, to))) {
- rb_yield(i);
- i = rb_funcall(i, '+', 1, INT2FIX(1));
- }
- if (NIL_P(c)) rb_cmperr(i, to);
- }
- return from;
-}
-
-/*
- * call-seq:
- * int.downto(limit) {|i| block } => int
- *
- * Iterates <em>block</em>, passing decreasing values from <i>int</i>
- * down to and including <i>limit</i>.
- *
- * 5.downto(1) { |n| print n, ".. " }
- * print " Liftoff!\n"
- *
- * <em>produces:</em>
- *
- * 5.. 4.. 3.. 2.. 1.. Liftoff!
- */
-
-static VALUE
-int_downto(from, to)
- VALUE from, to;
-{
- if (FIXNUM_P(from) && FIXNUM_P(to)) {
- long i, end;
-
- end = FIX2LONG(to);
- for (i=FIX2LONG(from); i >= end; i--) {
- rb_yield(LONG2FIX(i));
- }
- }
- else {
- VALUE i = from, c;
-
- while (!(c = rb_funcall(i, '<', 1, to))) {
- rb_yield(i);
- i = rb_funcall(i, '-', 1, INT2FIX(1));
- }
- if (NIL_P(c)) rb_cmperr(i, to);
- }
- return from;
-}
-
-/*
- * call-seq:
- * int.times {|i| block } => int
- *
- * Iterates block <i>int</i> times, passing in values from zero to
- * <i>int</i> - 1.
- *
- * 5.times do |i|
- * print i, " "
- * end
- *
- * <em>produces:</em>
- *
- * 0 1 2 3 4
- */
-
-static VALUE
-int_dotimes(num)
- VALUE num;
-{
- if (FIXNUM_P(num)) {
- long i, end;
-
- end = FIX2LONG(num);
- for (i=0; i<end; i++) {
- rb_yield(LONG2FIX(i));
- }
- }
- else {
- VALUE i = INT2FIX(0);
-
- for (;;) {
- if (!RTEST(rb_funcall(i, '<', 1, num))) break;
- rb_yield(i);
- i = rb_funcall(i, '+', 1, INT2FIX(1));
- }
- }
- return num;
-}
-
-/*
- * call-seq:
- * fix.zero? => true or false
- *
- * Returns <code>true</code> if <i>fix</i> is zero.
- *
- */
-
-static VALUE
-fix_zero_p(num)
- VALUE num;
-{
- if (FIX2LONG(num) == 0) {
- return Qtrue;
- }
- return Qfalse;
-}
-
-void
-Init_Numeric()
-{
-#if defined(__FreeBSD__) && __FreeBSD__ < 4
- /* allow divide by zero -- Inf */
- fpsetmask(fpgetmask() & ~(FP_X_DZ|FP_X_INV|FP_X_OFL));
-#elif defined(_UNICOSMP)
- /* Turn off floating point exceptions for divide by zero, etc. */
- _set_Creg(0, 0);
-#elif defined(__BORLANDC__)
- /* Turn off floating point exceptions for overflow, etc. */
- _control87(MCW_EM, MCW_EM);
-#endif
- id_coerce = rb_intern("coerce");
- id_to_i = rb_intern("to_i");
- id_eq = rb_intern("==");
-
- rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError);
- rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eRangeError);
- rb_cNumeric = rb_define_class("Numeric", rb_cObject);
-
- rb_define_method(rb_cNumeric, "singleton_method_added", num_sadded, 1);
- rb_include_module(rb_cNumeric, rb_mComparable);
- rb_define_method(rb_cNumeric, "initialize_copy", num_init_copy, 1);
- rb_define_method(rb_cNumeric, "coerce", num_coerce, 1);
-
- rb_define_method(rb_cNumeric, "+@", num_uplus, 0);
- rb_define_method(rb_cNumeric, "-@", num_uminus, 0);
- rb_define_method(rb_cNumeric, "<=>", num_cmp, 1);
- rb_define_method(rb_cNumeric, "eql?", num_eql, 1);
- rb_define_method(rb_cNumeric, "quo", num_quo, 1);
- rb_define_method(rb_cNumeric, "div", num_div, 1);
- rb_define_method(rb_cNumeric, "divmod", num_divmod, 1);
- rb_define_method(rb_cNumeric, "modulo", num_modulo, 1);
- rb_define_method(rb_cNumeric, "remainder", num_remainder, 1);
- rb_define_method(rb_cNumeric, "abs", num_abs, 0);
- rb_define_method(rb_cNumeric, "to_int", num_to_int, 0);
-
- rb_define_method(rb_cNumeric, "integer?", num_int_p, 0);
- rb_define_method(rb_cNumeric, "zero?", num_zero_p, 0);
- rb_define_method(rb_cNumeric, "nonzero?", num_nonzero_p, 0);
-
- rb_define_method(rb_cNumeric, "floor", num_floor, 0);
- rb_define_method(rb_cNumeric, "ceil", num_ceil, 0);
- rb_define_method(rb_cNumeric, "round", num_round, 0);
- rb_define_method(rb_cNumeric, "truncate", num_truncate, 0);
- rb_define_method(rb_cNumeric, "step", num_step, -1);
-
- rb_cInteger = rb_define_class("Integer", rb_cNumeric);
- rb_undef_alloc_func(rb_cInteger);
- rb_undef_method(CLASS_OF(rb_cInteger), "new");
-
- rb_define_method(rb_cInteger, "integer?", int_int_p, 0);
- rb_define_method(rb_cInteger, "upto", int_upto, 1);
- rb_define_method(rb_cInteger, "downto", int_downto, 1);
- rb_define_method(rb_cInteger, "times", int_dotimes, 0);
- rb_include_module(rb_cInteger, rb_mPrecision);
- rb_define_method(rb_cInteger, "succ", int_succ, 0);
- rb_define_method(rb_cInteger, "next", int_succ, 0);
- rb_define_method(rb_cInteger, "chr", int_chr, 0);
- rb_define_method(rb_cInteger, "to_i", int_to_i, 0);
- rb_define_method(rb_cInteger, "to_int", int_to_i, 0);
- rb_define_method(rb_cInteger, "floor", int_to_i, 0);
- rb_define_method(rb_cInteger, "ceil", int_to_i, 0);
- rb_define_method(rb_cInteger, "round", int_to_i, 0);
- rb_define_method(rb_cInteger, "truncate", int_to_i, 0);
-
- rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
- rb_include_module(rb_cFixnum, rb_mPrecision);
- rb_define_singleton_method(rb_cFixnum, "induced_from", rb_fix_induced_from, 1);
- rb_define_singleton_method(rb_cInteger, "induced_from", rb_int_induced_from, 1);
-
- rb_define_method(rb_cFixnum, "to_s", fix_to_s, -1);
-
- rb_define_method(rb_cFixnum, "id2name", fix_id2name, 0);
- rb_define_method(rb_cFixnum, "to_sym", fix_to_sym, 0);
-
- rb_define_method(rb_cFixnum, "-@", fix_uminus, 0);
- rb_define_method(rb_cFixnum, "+", fix_plus, 1);
- rb_define_method(rb_cFixnum, "-", fix_minus, 1);
- rb_define_method(rb_cFixnum, "*", fix_mul, 1);
- rb_define_method(rb_cFixnum, "/", fix_div, 1);
- rb_define_method(rb_cFixnum, "div", fix_div, 1);
- rb_define_method(rb_cFixnum, "%", fix_mod, 1);
- rb_define_method(rb_cFixnum, "modulo", fix_mod, 1);
- rb_define_method(rb_cFixnum, "divmod", fix_divmod, 1);
- rb_define_method(rb_cFixnum, "quo", fix_quo, 1);
- rb_define_method(rb_cFixnum, "**", fix_pow, 1);
-
- rb_define_method(rb_cFixnum, "abs", fix_abs, 0);
-
- rb_define_method(rb_cFixnum, "==", fix_equal, 1);
- rb_define_method(rb_cFixnum, "<=>", fix_cmp, 1);
- rb_define_method(rb_cFixnum, ">", fix_gt, 1);
- rb_define_method(rb_cFixnum, ">=", fix_ge, 1);
- rb_define_method(rb_cFixnum, "<", fix_lt, 1);
- rb_define_method(rb_cFixnum, "<=", fix_le, 1);
-
- rb_define_method(rb_cFixnum, "~", fix_rev, 0);
- rb_define_method(rb_cFixnum, "&", fix_and, 1);
- rb_define_method(rb_cFixnum, "|", fix_or, 1);
- rb_define_method(rb_cFixnum, "^", fix_xor, 1);
- rb_define_method(rb_cFixnum, "[]", fix_aref, 1);
-
- rb_define_method(rb_cFixnum, "<<", fix_lshift, 1);
- rb_define_method(rb_cFixnum, ">>", fix_rshift, 1);
-
- rb_define_method(rb_cFixnum, "to_f", fix_to_f, 0);
- rb_define_method(rb_cFixnum, "size", fix_size, 0);
- rb_define_method(rb_cFixnum, "zero?", fix_zero_p, 0);
-
- rb_cFloat = rb_define_class("Float", rb_cNumeric);
-
- rb_undef_alloc_func(rb_cFloat);
- rb_undef_method(CLASS_OF(rb_cFloat), "new");
-
- rb_define_singleton_method(rb_cFloat, "induced_from", rb_flo_induced_from, 1);
- rb_include_module(rb_cFloat, rb_mPrecision);
-
- rb_define_const(rb_cFloat, "ROUNDS", INT2FIX(FLT_ROUNDS));
- rb_define_const(rb_cFloat, "RADIX", INT2FIX(FLT_RADIX));
- rb_define_const(rb_cFloat, "MANT_DIG", INT2FIX(DBL_MANT_DIG));
- rb_define_const(rb_cFloat, "DIG", INT2FIX(DBL_DIG));
- rb_define_const(rb_cFloat, "MIN_EXP", INT2FIX(DBL_MIN_EXP));
- rb_define_const(rb_cFloat, "MAX_EXP", INT2FIX(DBL_MAX_EXP));
- rb_define_const(rb_cFloat, "MIN_10_EXP", INT2FIX(DBL_MIN_10_EXP));
- rb_define_const(rb_cFloat, "MAX_10_EXP", INT2FIX(DBL_MAX_10_EXP));
- rb_define_const(rb_cFloat, "MIN", rb_float_new(DBL_MIN));
- rb_define_const(rb_cFloat, "MAX", rb_float_new(DBL_MAX));
- rb_define_const(rb_cFloat, "EPSILON", rb_float_new(DBL_EPSILON));
-
- rb_define_method(rb_cFloat, "to_s", flo_to_s, 0);
- rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
- rb_define_method(rb_cFloat, "-@", flo_uminus, 0);
- rb_define_method(rb_cFloat, "+", flo_plus, 1);
- rb_define_method(rb_cFloat, "-", flo_minus, 1);
- rb_define_method(rb_cFloat, "*", flo_mul, 1);
- rb_define_method(rb_cFloat, "/", flo_div, 1);
- rb_define_method(rb_cFloat, "%", flo_mod, 1);
- rb_define_method(rb_cFloat, "modulo", flo_mod, 1);
- rb_define_method(rb_cFloat, "divmod", flo_divmod, 1);
- rb_define_method(rb_cFloat, "**", flo_pow, 1);
- rb_define_method(rb_cFloat, "==", flo_eq, 1);
- rb_define_method(rb_cFloat, "<=>", flo_cmp, 1);
- rb_define_method(rb_cFloat, ">", flo_gt, 1);
- rb_define_method(rb_cFloat, ">=", flo_ge, 1);
- rb_define_method(rb_cFloat, "<", flo_lt, 1);
- rb_define_method(rb_cFloat, "<=", flo_le, 1);
- rb_define_method(rb_cFloat, "eql?", flo_eql, 1);
- rb_define_method(rb_cFloat, "hash", flo_hash, 0);
- rb_define_method(rb_cFloat, "to_f", flo_to_f, 0);
- rb_define_method(rb_cFloat, "abs", flo_abs, 0);
- rb_define_method(rb_cFloat, "zero?", flo_zero_p, 0);
-
- rb_define_method(rb_cFloat, "to_i", flo_truncate, 0);
- rb_define_method(rb_cFloat, "to_int", flo_truncate, 0);
- rb_define_method(rb_cFloat, "floor", flo_floor, 0);
- rb_define_method(rb_cFloat, "ceil", flo_ceil, 0);
- rb_define_method(rb_cFloat, "round", flo_round, 0);
- rb_define_method(rb_cFloat, "truncate", flo_truncate, 0);
-
- rb_define_method(rb_cFloat, "nan?", flo_is_nan_p, 0);
- rb_define_method(rb_cFloat, "infinite?", flo_is_infinite_p, 0);
- rb_define_method(rb_cFloat, "finite?", flo_is_finite_p, 0);
-}
-/**********************************************************************
-
- object.c -
-
- $Author: matz $
- $Date: 2005/03/16 09:25:44 $
- created at: Thu Jul 15 12:01:24 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 "st.h"
-#include "util.h"
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
-#include <math.h>
-
-VALUE rb_mKernel;
-VALUE rb_cObject;
-VALUE rb_cModule;
-VALUE rb_cClass;
-VALUE rb_cData;
-
-VALUE rb_cNilClass;
-VALUE rb_cTrueClass;
-VALUE rb_cFalseClass;
-VALUE rb_cSymbol;
-
-static ID id_eq, id_eql, id_inspect, id_init_copy;
-
-/*
- * call-seq:
- * obj === other => true or false
- *
- * Case Equality---For class <code>Object</code>, effectively the same
- * as calling <code>#==</code>, but typically overridden by descendents
- * to provide meaningful semantics in <code>case</code> statements.
- */
-
-VALUE
-rb_equal(obj1, obj2)
- VALUE obj1, obj2;
-{
- VALUE result;
-
- if (obj1 == obj2) return Qtrue;
- result = rb_funcall(obj1, id_eq, 1, obj2);
- if (RTEST(result)) return Qtrue;
- return Qfalse;
-}
-
-int
-rb_eql(obj1, obj2)
- VALUE obj1, obj2;
-{
- return RTEST(rb_funcall(obj1, id_eql, 1, obj2));
-}
-
-/*
- * call-seq:
- * obj == other => true or false
- * obj.equal?(other) => true or false
- * obj.eql?(other) => true or false
- *
- * Equality---At the <code>Object</code> level, <code>==</code> returns
- * <code>true</code> only if <i>obj</i> and <i>other</i> are the
- * same object. Typically, this method is overridden in descendent
- * classes to provide class-specific meaning.
- *
- * Unlike <code>==</code>, the <code>equal?</code> method should never be
- * overridden by subclasses: it is used to determine object identity
- * (that is, <code>a.equal?(b)</code> iff <code>a</code> is the same
- * object as <code>b</code>).
- *
- * The <code>eql?</code> method returns <code>true</code> if
- <i>obj</i> and <i>anObject</i> have the
- * same value. Used by <code>Hash</code> to test members for equality.
- * For objects of class <code>Object</code>, <code>eql?</code> is
- * synonymous with <code>==</code>. Subclasses normally continue this
- * tradition, but there are exceptions. <code>Numeric</code> types, for
- * example, perform type conversion across <code>==</code>, but not
- * across <code>eql?</code>, so:
- *
- * 1 == 1.0 #=> true
- * 1.eql? 1.0 #=> false
- */
-
-static VALUE
-rb_obj_equal(obj1, obj2)
- VALUE obj1, obj2;
-{
- if (obj1 == obj2) return Qtrue;
- return Qfalse;
-}
-
-
-/*
- * Document-method: __id__
- * Document-method: object_id
- *
- * call-seq:
- * obj.__id__ => fixnum
- * obj.object_id => fixnum
- *
- * Returns an integer identifier for <i>obj</i>. The same number will
- * be returned on all calls to <code>id</code> for a given object, and
- * no two active objects will share an id.
- * <code>Object#object_id</code> is a different concept from the
- * <code>:name</code> notation, which returns the symbol id of
- * <code>name</code>. Replaces the deprecated <code>Object#id</code>.
- */
-
-
-
-/*
- * call-seq:
- * obj.hash => fixnum
- *
- * Generates a <code>Fixnum</code> hash value for this object. This
- * function must have the property that <code>a.eql?(b)</code> implies
- * <code>a.hash == b.hash</code>. The hash value is used by class
- * <code>Hash</code>. Any hash value that exceeds the capacity of a
- * <code>Fixnum</code> will be truncated before being used.
- */
-
-VALUE
-rb_obj_id(obj)
- VALUE obj;
-{
- if (SPECIAL_CONST_P(obj)) {
- return LONG2NUM((long)obj);
- }
- return (VALUE)((long)obj|FIXNUM_FLAG);
-}
-
-VALUE
-rb_class_real(cl)
- VALUE cl;
-{
- while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) {
- cl = RCLASS(cl)->super;
- }
- return cl;
-}
-
-/*
- * call-seq:
- * obj.class => class
- *
- * Returns the class of <i>obj</i>, now preferred over
- * <code>Object#type</code>, as an object's type in Ruby is only
- * loosely tied to that object's class. This method must always be
- * called with an explicit receiver, as <code>class</code> is also a
- * reserved word in Ruby.
- *
- * 1.class #=> Fixnum
- * self.class #=> Object
- */
-
-VALUE
-rb_obj_class(obj)
- VALUE obj;
-{
- return rb_class_real(CLASS_OF(obj));
-}
-
-static void
-init_copy(dest, obj)
- VALUE dest, obj;
-{
- if (OBJ_FROZEN(dest)) {
- rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
- }
- RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR);
- RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR|FL_TAINT);
- rb_copy_generic_ivar(dest, obj);
- rb_gc_copy_finalizer(dest, obj);
- switch (TYPE(obj)) {
- case T_OBJECT:
- case T_CLASS:
- case T_MODULE:
- if (ROBJECT(dest)->iv_tbl) {
- st_free_table(ROBJECT(dest)->iv_tbl);
- ROBJECT(dest)->iv_tbl = 0;
- }
- if (ROBJECT(obj)->iv_tbl) {
- ROBJECT(dest)->iv_tbl = st_copy(ROBJECT(obj)->iv_tbl);
- }
- }
- rb_funcall(dest, id_init_copy, 1, obj);
-}
-
-/*
- * call-seq:
- * obj.clone -> an_object
- *
- * Produces a shallow copy of <i>obj</i>---the instance variables of
- * <i>obj</i> are copied, but not the objects they reference. Copies
- * the frozen and tainted state of <i>obj</i>. See also the discussion
- * under <code>Object#dup</code>.
- *
- * class Klass
- * attr_accessor :str
- * end
- * s1 = Klass.new #=> #<Klass:0x401b3a38>
- * s1.str = "Hello" #=> "Hello"
- * s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
- * s2.str[1,4] = "i" #=> "i"
- * s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
- * s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
- *
- * This method may have class-specific behavior. If so, that
- * behavior will be documented under the #+initialize_copy+ method of
- * the class.
- */
-
-VALUE
-rb_obj_clone(obj)
- VALUE obj;
-{
- VALUE clone;
-
- if (rb_special_const_p(obj)) {
- rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj));
- }
- clone = rb_obj_alloc(rb_obj_class(obj));
- RBASIC(clone)->klass = rb_singleton_class_clone(obj);
- RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT)) & ~(FL_FREEZE|FL_FINALIZE);
- init_copy(clone, obj);
- RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
-
- return clone;
-}
-
-/*
- * call-seq:
- * obj.dup -> an_object
- *
- * Produces a shallow copy of <i>obj</i>---the instance variables of
- * <i>obj</i> are copied, but not the objects they reference.
- * <code>dup</code> copies the tainted state of <i>obj</i>. See also
- * the discussion under <code>Object#clone</code>. In general,
- * <code>clone</code> and <code>dup</code> may have different semantics
- * in descendent classes. While <code>clone</code> is used to duplicate
- * an object, including its internal state, <code>dup</code> typically
- * uses the class of the descendent object to create the new instance.
- *
- * This method may have class-specific behavior. If so, that
- * behavior will be documented under the #+initialize_copy+ method of
- * the class.
- */
-
-VALUE
-rb_obj_dup(obj)
- VALUE obj;
-{
- VALUE dup;
-
- if (rb_special_const_p(obj)) {
- rb_raise(rb_eTypeError, "can't dup %s", rb_obj_classname(obj));
- }
- dup = rb_obj_alloc(rb_obj_class(obj));
- init_copy(dup, obj);
-
- return dup;
-}
-
-/* :nodoc: */
-VALUE
-rb_obj_init_copy(obj, orig)
- VALUE obj, orig;
-{
- if (obj == orig) return obj;
- rb_check_frozen(obj);
- if (TYPE(obj) != TYPE(orig) || rb_obj_class(obj) != rb_obj_class(orig)) {
- rb_raise(rb_eTypeError, "initialize_copy should take same class object");
- }
- return obj;
-}
-
-/*
- * call-seq:
- * obj.to_s => string
- *
- * Returns a string representing <i>obj</i>. The default
- * <code>to_s</code> prints the object's class and an encoding of the
- * object id. As a special case, the top-level object that is the
- * initial execution context of Ruby programs returns ``main.''
- */
-
-VALUE
-rb_any_to_s(obj)
- VALUE obj;
-{
- char *cname = rb_obj_classname(obj);
- VALUE str;
-
- str = rb_str_new(0, strlen(cname)+6+16+1); /* 6:tags 16:addr 1:nul */
- sprintf(RSTRING(str)->ptr, "#<%s:0x%lx>", cname, obj);
- RSTRING(str)->len = strlen(RSTRING(str)->ptr);
- if (OBJ_TAINTED(obj)) OBJ_TAINT(str);
-
- return str;
-}
-
-VALUE
-rb_inspect(obj)
- VALUE obj;
-{
- return rb_obj_as_string(rb_funcall(obj, id_inspect, 0, 0));
-}
-
-static int
-inspect_i(id, value, str)
- ID id;
- VALUE value;
- VALUE str;
-{
- VALUE str2;
- char *ivname;
-
- /* need not to show internal data */
- if (CLASS_OF(value) == 0) return ST_CONTINUE;
- if (!rb_is_instance_id(id)) return ST_CONTINUE;
- if (RSTRING(str)->ptr[0] == '-') { /* first element */
- RSTRING(str)->ptr[0] = '#';
- rb_str_cat2(str, " ");
- }
- else {
- rb_str_cat2(str, ", ");
- }
- ivname = rb_id2name(id);
- rb_str_cat2(str, ivname);
- rb_str_cat2(str, "=");
- str2 = rb_inspect(value);
- rb_str_append(str, str2);
- OBJ_INFECT(str, str2);
-
- return ST_CONTINUE;
-}
-
-static VALUE
-inspect_obj(obj, str, recur)
- VALUE obj, str;
- int recur;
-{
- if (recur) {
- rb_str_cat2(str, " ...");
- }
- else {
- st_foreach_safe(ROBJECT(obj)->iv_tbl, inspect_i, str);
- }
- rb_str_cat2(str, ">");
- RSTRING(str)->ptr[0] = '#';
- OBJ_INFECT(str, obj);
-
- return str;
-}
-
-/*
- * call-seq:
- * obj.inspect => string
- *
- * Returns a string containing a human-readable representation of
- * <i>obj</i>. If not overridden, uses the <code>to_s</code> method to
- * generate the string.
- *
- * [ 1, 2, 3..4, 'five' ].inspect #=> "[1, 2, 3..4, \"five\"]"
- * Time.new.inspect #=> "Wed Apr 09 08:54:39 CDT 2003"
- */
-
-
-static VALUE
-rb_obj_inspect(obj)
- VALUE obj;
-{
- if (TYPE(obj) == T_OBJECT
- && ROBJECT(obj)->iv_tbl
- && ROBJECT(obj)->iv_tbl->num_entries > 0) {
- VALUE str;
- char *c;
-
- c = rb_obj_classname(obj);
- str = rb_str_new(0, strlen(c)+10+16+1); /* 10:tags 16:addr 1:nul */
- sprintf(RSTRING(str)->ptr, "-<%s:0x%lx", c, obj);
- RSTRING(str)->len = strlen(RSTRING(str)->ptr);
- return rb_exec_recursive(inspect_obj, obj, str);
- }
- return rb_funcall(obj, rb_intern("to_s"), 0, 0);
-}
-
-
-/*
- * call-seq:
- * obj.instance_of?(class) => true or false
- *
- * Returns <code>true</code> if <i>obj</i> is an instance of the given
- * class. See also <code>Object#kind_of?</code>.
- */
-
-VALUE
-rb_obj_is_instance_of(obj, c)
- VALUE obj, c;
-{
- switch (TYPE(c)) {
- case T_MODULE:
- case T_CLASS:
- case T_ICLASS:
- break;
- default:
- rb_raise(rb_eTypeError, "class or module required");
- }
-
- if (rb_obj_class(obj) == c) return Qtrue;
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * obj.is_a?(class) => true or false
- * obj.kind_of?(class) => true or false
- *
- * Returns <code>true</code> if <i>class</i> is the class of
- * <i>obj</i>, or if <i>class</i> is one of the superclasses of
- * <i>obj</i> or modules included in <i>obj</i>.
- *
- * module M; end
- * class A
- * include M
- * end
- * class B < A; end
- * class C < B; end
- * b = B.new
- * b.instance_of? A #=> false
- * b.instance_of? B #=> true
- * b.instance_of? C #=> false
- * b.instance_of? M #=> false
- * b.kind_of? A #=> true
- * b.kind_of? B #=> true
- * b.kind_of? C #=> false
- * b.kind_of? M #=> true
- */
-
-VALUE
-rb_obj_is_kind_of(obj, c)
- VALUE obj, c;
-{
- VALUE cl = CLASS_OF(obj);
-
- switch (TYPE(c)) {
- case T_MODULE:
- case T_CLASS:
- case T_ICLASS:
- break;
-
- default:
- rb_raise(rb_eTypeError, "class or module required");
- }
-
- while (cl) {
- if (cl == c || RCLASS(cl)->m_tbl == RCLASS(c)->m_tbl)
- return Qtrue;
- cl = RCLASS(cl)->super;
- }
- return Qfalse;
-}
-
-
-/*
- * Document-method: singleton_method_added
- *
- * call-seq:
- * singleton_method_added(symbol)
- *
- * Invoked as a callback whenever a singleton method is added to the
- * receiver.
- *
- * module Chatty
- * def Chatty.singleton_method_added(id)
- * puts "Adding #{id.id2name}"
- * end
- * def self.one() end
- * def two() end
- * def Chatty.three() end
- * end
- *
- * <em>produces:</em>
- *
- * Adding singleton_method_added
- * Adding one
- * Adding three
- *
- */
-
-/*
- * Document-method: singleton_method_removed
- *
- * call-seq:
- * singleton_method_removed(symbol)
- *
- * Invoked as a callback whenever a singleton method is removed from
- * the receiver.
- *
- * module Chatty
- * def Chatty.singleton_method_removed(id)
- * puts "Removing #{id.id2name}"
- * end
- * def self.one() end
- * def two() end
- * def Chatty.three() end
- * class <<self
- * remove_method :three
- * remove_method :one
- * end
- * end
- *
- * <em>produces:</em>
- *
- * Removing three
- * Removing one
- */
-
-/*
- * Document-method: singleton_method_undefined
- *
- * call-seq:
- * singleton_method_undefined(symbol)
- *
- * Invoked as a callback whenever a singleton method is undefined in
- * the receiver.
- *
- * module Chatty
- * def Chatty.singleton_method_undefined(id)
- * puts "Undefining #{id.id2name}"
- * end
- * def Chatty.one() end
- * class << self
- * undef_method(:one)
- * end
- * end
- *
- * <em>produces:</em>
- *
- * Undefining one
- */
-
-
-/*
- * Document-method: included
- *
- * call-seq:
- * included( othermod )
- *
- * Callback invoked whenever the receiver is included in another
- * module or class. This should be used in preference to
- * <tt>Module.append_features</tt> if your code wants to perform some
- * action when a module is included in another.
- *
- * module A
- * def A.included(mod)
- * puts "#{self} included in #{mod}"
- * end
- * end
- * module Enumerable
- * include A
- * end
- */
-
-
-/*
- * Not documented
- */
-
-static VALUE
-rb_obj_dummy()
-{
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * obj.tainted? => true or false
- *
- * Returns <code>true</code> if the object is tainted.
- */
-
-VALUE
-rb_obj_tainted(obj)
- VALUE obj;
-{
- if (OBJ_TAINTED(obj))
- return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * obj.taint -> obj
- *
- * Marks <i>obj</i> as tainted---if the <code>$SAFE</code> level is
- * set appropriately, many method calls which might alter the running
- * programs environment will refuse to accept tainted strings.
- */
-
-VALUE
-rb_obj_taint(obj)
- VALUE obj;
-{
- rb_secure(4);
- if (!OBJ_TAINTED(obj)) {
- if (OBJ_FROZEN(obj)) {
- rb_error_frozen("object");
- }
- OBJ_TAINT(obj);
- }
- return obj;
-}
-
-
-/*
- * call-seq:
- * obj.untaint => obj
- *
- * Removes the taint from <i>obj</i>.
- */
-
-VALUE
-rb_obj_untaint(obj)
- VALUE obj;
-{
- rb_secure(3);
- if (OBJ_TAINTED(obj)) {
- if (OBJ_FROZEN(obj)) {
- rb_error_frozen("object");
- }
- FL_UNSET(obj, FL_TAINT);
- }
- return obj;
-}
-
-void
-rb_obj_infect(obj1, obj2)
- VALUE obj1, obj2;
-{
- OBJ_INFECT(obj1, obj2);
-}
-
-
-/*
- * call-seq:
- * obj.freeze => obj
- *
- * Prevents further modifications to <i>obj</i>. A
- * <code>TypeError</code> will be raised if modification is attempted.
- * There is no way to unfreeze a frozen object. See also
- * <code>Object#frozen?</code>.
- *
- * a = [ "a", "b", "c" ]
- * a.freeze
- * a << "z"
- *
- * <em>produces:</em>
- *
- * prog.rb:3:in `<<': can't modify frozen array (TypeError)
- * from prog.rb:3
- */
-
-VALUE
-rb_obj_freeze(obj)
- VALUE obj;
-{
- if (!OBJ_FROZEN(obj)) {
- if (rb_safe_level() >= 4 && !OBJ_TAINTED(obj)) {
- rb_raise(rb_eSecurityError, "Insecure: can't freeze object");
- }
- OBJ_FREEZE(obj);
- }
- return obj;
-}
-
-/*
- * call-seq:
- * obj.frozen? => true or false
- *
- * Returns the freeze status of <i>obj</i>.
- *
- * a = [ "a", "b", "c" ]
- * a.freeze #=> ["a", "b", "c"]
- * a.frozen? #=> true
- */
-
-static VALUE
-rb_obj_frozen_p(obj)
- VALUE obj;
-{
- if (OBJ_FROZEN(obj)) return Qtrue;
- return Qfalse;
-}
-
-
-/*
- * Document-class: NilClass
- *
- * The class of the singleton object <code>nil</code>.
- */
-
-/*
- * call-seq:
- * nil.to_i => 0
- *
- * Always returns zero.
- *
- * nil.to_i #=> 0
- */
-
-
-static VALUE
-nil_to_i(obj)
- VALUE obj;
-{
- return INT2FIX(0);
-}
-
-/*
- * call-seq:
- * nil.to_f => 0.0
- *
- * Always returns zero.
- *
- * nil.to_f #=> 0.0
- */
-
-static VALUE
-nil_to_f(obj)
- VALUE obj;
-{
- return rb_float_new(0.0);
-}
-
-/*
- * call-seq:
- * nil.to_s => ""
- *
- * Always returns the empty string.
- *
- * nil.to_s #=> ""
- */
-
-static VALUE
-nil_to_s(obj)
- VALUE obj;
-{
- return rb_str_new2("");
-}
-
-/*
- * call-seq:
- * nil.to_a => []
- *
- * Always returns an empty array.
- *
- * nil.to_a #=> []
- */
-
-static VALUE
-nil_to_a(obj)
- VALUE obj;
-{
- return rb_ary_new2(0);
-}
-
-/*
- * call-seq:
- * nil.inspect => "nil"
- *
- * Always returns the string "nil".
- */
-
-static VALUE
-nil_inspect(obj)
- VALUE obj;
-{
- return rb_str_new2("nil");
-}
-
-#ifdef NIL_PLUS
-static VALUE
-nil_plus(x, y)
- VALUE x, y;
-{
- switch (TYPE(y)) {
- case T_NIL:
- case T_FIXNUM:
- case T_FLOAT:
- case T_BIGNUM:
- case T_STRING:
- case T_ARRAY:
- return y;
- default:
- rb_raise(rb_eTypeError, "tried to add %s(%s) to nil",
- RSTRING(rb_inspect(y))->ptr,
- rb_obj_classname(y));
- }
- /* not reached */
-}
-#endif
-
-static VALUE
-main_to_s(obj)
- VALUE obj;
-{
- return rb_str_new2("main");
-}
-
-
-/***********************************************************************
- * Document-class: TrueClass
- *
- * The global value <code>true</code> is the only instance of class
- * <code>TrueClass</code> and represents a logically true value in
- * boolean expressions. The class provides operators allowing
- * <code>true</code> to be used in logical expressions.
- */
-
-
-/*
- * call-seq:
- * true.to_s => "true"
- *
- * The string representation of <code>true</code> is "true".
- */
-
-static VALUE
-true_to_s(obj)
- VALUE obj;
-{
- return rb_str_new2("true");
-}
-
-
-/*
- * call-seq:
- * true & obj => true or false
- *
- * And---Returns <code>false</code> if <i>obj</i> is
- * <code>nil</code> or <code>false</code>, <code>true</code> otherwise.
- */
-
-static VALUE
-true_and(obj, obj2)
- VALUE obj, obj2;
-{
- return RTEST(obj2)?Qtrue:Qfalse;
-}
-
-/*
- * call-seq:
- * true | obj => true
- *
- * Or---Returns <code>true</code>. As <i>anObject</i> is an argument to
- * a method call, it is always evaluated; there is no short-circuit
- * evaluation in this case.
- *
- * true | puts("or")
- * true || puts("logical or")
- *
- * <em>produces:</em>
- *
- * or
- */
-
-static VALUE
-true_or(obj, obj2)
- VALUE obj, obj2;
-{
- return Qtrue;
-}
-
-
-/*
- * call-seq:
- * true ^ obj => !obj
- *
- * Exclusive Or---Returns <code>true</code> if <i>obj</i> is
- * <code>nil</code> or <code>false</code>, <code>false</code>
- * otherwise.
- */
-
-static VALUE
-true_xor(obj, obj2)
- VALUE obj, obj2;
-{
- return RTEST(obj2)?Qfalse:Qtrue;
-}
-
-
-/*
- * Document-class: FalseClass
- *
- * The global value <code>false</code> is the only instance of class
- * <code>FalseClass</code> and represents a logically false value in
- * boolean expressions. The class provides operators allowing
- * <code>false</code> to participate correctly in logical expressions.
- *
- */
-
-/*
- * call-seq:
- * false.to_s => "false"
- *
- * 'nuf said...
- */
-
-static VALUE
-false_to_s(obj)
- VALUE obj;
-{
- return rb_str_new2("false");
-}
-
-/*
- * call-seq:
- * false & obj => false
- * nil & obj => false
- *
- * And---Returns <code>false</code>. <i>obj</i> is always
- * evaluated as it is the argument to a method call---there is no
- * short-circuit evaluation in this case.
- */
-
-static VALUE
-false_and(obj, obj2)
- VALUE obj, obj2;
-{
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * false | obj => true or false
- * nil | obj => true or false
- *
- * Or---Returns <code>false</code> if <i>obj</i> is
- * <code>nil</code> or <code>false</code>; <code>true</code> otherwise.
- */
-
-static VALUE
-false_or(obj, obj2)
- VALUE obj, obj2;
-{
- return RTEST(obj2)?Qtrue:Qfalse;
-}
-
-
-
-/*
- * call-seq:
- * false ^ obj => true or false
- * nil ^ obj => true or false
- *
- * Exclusive Or---If <i>obj</i> is <code>nil</code> or
- * <code>false</code>, returns <code>false</code>; otherwise, returns
- * <code>true</code>.
- *
- */
-
-static VALUE
-false_xor(obj, obj2)
- VALUE obj, obj2;
-{
- return RTEST(obj2)?Qtrue:Qfalse;
-}
-
-/*
- * call_seq:
- * nil.nil? => true
- *
- * Only the object <i>nil</i> responds <code>true</code> to <code>nil?</code>.
- */
-
-static VALUE
-rb_true(obj)
- VALUE obj;
-{
- return Qtrue;
-}
-
-/*
- * call_seq:
- * nil.nil? => true
- * <anything_else>.nil? => false
- *
- * Only the object <i>nil</i> responds <code>true</code> to <code>nil?</code>.
- */
-
-
-static VALUE
-rb_false(obj)
- VALUE obj;
-{
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * obj =~ other => false
- *
- * Pattern Match---Overridden by descendents (notably
- * <code>Regexp</code> and <code>String</code>) to provide meaningful
- * pattern-match semantics.
- */
-
-static VALUE
-rb_obj_pattern_match(obj1, obj2)
- VALUE obj1, obj2;
-{
- return Qfalse;
-}
-
-/**********************************************************************
- * Document-class: Symbol
- *
- * <code>Symbol</code> objects represent names and some strings
- * inside the Ruby
- * interpreter. They are generated using the <code>:name</code> and
- * <code>:"string"</code> literals
- * syntax, and by the various <code>to_sym</code> methods. The same
- * <code>Symbol</code> object will be created for a given name or string
- * for the duration of a program's execution, regardless of the context
- * or meaning of that name. Thus if <code>Fred</code> is a constant in
- * one context, a method in another, and a class in a third, the
- * <code>Symbol</code> <code>:Fred</code> will be the same object in
- * all three contexts.
- *
- * module One
- * class Fred
- * end
- * $f1 = :Fred
- * end
- * module Two
- * Fred = 1
- * $f2 = :Fred
- * end
- * def Fred()
- * end
- * $f3 = :Fred
- * $f1.id #=> 2514190
- * $f2.id #=> 2514190
- * $f3.id #=> 2514190
- *
- */
-
-/*
- * call-seq:
- * sym.to_i => fixnum
- *
- * Returns an integer that is unique for each symbol within a
- * particular execution of a program.
- *
- * :fred.to_i #=> 9809
- * "fred".to_sym.to_i #=> 9809
- */
-
-static VALUE
-sym_to_i(sym)
- VALUE sym;
-{
- ID id = SYM2ID(sym);
-
- return LONG2FIX(id);
-}
-
-
-/*
- * call-seq:
- * sym.inspect => string
- *
- * Returns the representation of <i>sym</i> as a symbol literal.
- *
- * :fred.inspect #=> ":fred"
- */
-
-static VALUE
-sym_inspect(sym)
- VALUE sym;
-{
- VALUE str;
- char *name;
- ID id = SYM2ID(sym);
-
- name = rb_id2name(id);
- str = rb_str_new(0, strlen(name)+1);
- RSTRING(str)->ptr[0] = ':';
- strcpy(RSTRING(str)->ptr+1, name);
- if (rb_is_junk_id(id)) {
- str = rb_str_dump(str);
- strncpy(RSTRING(str)->ptr, ":\"", 2);
- }
- return str;
-}
-
-
-/*
- * call-seq:
- * sym.id2name => string
- * sym.to_s => string
- *
- * Returns the name or string corresponding to <i>sym</i>.
- *
- * :fred.id2name #=> "fred"
- */
-
-
-static VALUE
-sym_to_s(sym)
- VALUE sym;
-{
- return rb_str_new2(rb_id2name(SYM2ID(sym)));
-}
-
-
-/*
- * call-seq:
- * sym.to_sym => sym
- *
- * In general, <code>to_sym</code> returns the <code>Symbol</code> corresponding
- * to an object. As <i>sym</i> is already a symbol, <code>self</code> is returned
- * in this case.
- */
-
-static VALUE
-sym_to_sym(sym)
- VALUE sym;
-{
- return sym;
-}
-
-
-/***********************************************************************
- *
- * Document-class: Module
- *
- * A <code>Module</code> is a collection of methods and constants. The
- * methods in a module may be instance methods or module methods.
- * Instance methods appear as methods in a class when the module is
- * included, module methods do not. Conversely, module methods may be
- * called without creating an encapsulating object, while instance
- * methods may not. (See <code>Module#module_function</code>)
- *
- * In the descriptions that follow, the parameter <i>syml</i> refers
- * to a symbol, which is either a quoted string or a
- * <code>Symbol</code> (such as <code>:name</code>).
- *
- * module Mod
- * include Math
- * CONST = 1
- * def meth
- * # ...
- * end
- * end
- * Mod.class #=> Module
- * Mod.constants #=> ["E", "PI", "CONST"]
- * Mod.instance_methods #=> ["meth"]
- *
- */
-
-/*
- * call-seq:
- * mod.to_s => string
- *
- * Return a string representing this module or class. For basic
- * classes and modules, this is the name. For singletons, we
- * show information on the thing we're attached to as well.
- */
-
-static VALUE
-rb_mod_to_s(klass)
- VALUE klass;
-
-{
- if (FL_TEST(klass, FL_SINGLETON)) {
- VALUE s = rb_str_new2("#<");
- VALUE v = rb_iv_get(klass, "__attached__");
-
- rb_str_cat2(s, "Class:");
- switch (TYPE(v)) {
- case T_CLASS: case T_MODULE:
- rb_str_append(s, rb_inspect(v));
- break;
- default:
- rb_str_append(s, rb_any_to_s(v));
- break;
- }
- rb_str_cat2(s, ">");
-
- return s;
- }
- return rb_str_dup(rb_class_name(klass));
-}
-
-/*
- * call-seq:
- * mod.freeze
- *
- * Prevents further modifications to <i>mod</i>.
- */
-
-static VALUE
-rb_mod_freeze(mod)
- VALUE mod;
-{
- rb_mod_to_s(mod);
- return rb_obj_freeze(mod);
-}
-
-/*
- * call-seq:
- * mod === obj => true or false
- *
- * Case Equality---Returns <code>true</code> if <i>anObject</i> is an
- * instance of <i>mod</i> or one of <i>mod</i>'s descendents. Of
- * limited use for modules, but can be used in <code>case</code>
- * statements to classify objects by class.
- */
-
-static VALUE
-rb_mod_eqq(mod, arg)
- VALUE mod, arg;
-{
- return rb_obj_is_kind_of(arg, mod);
-}
-
-/*
- * call-seq:
- * mod <= other => true, false, or nil
- *
- * Returns true if <i>mod</i> is a subclass of <i>other</i> or
- * is the same as <i>other</i>. Returns
- * <code>nil</code> if there's no relationship between the two.
- * (Think of the relationship in terms of the class definition:
- * "class A<B" implies "A<B").
- *
- */
-
-VALUE
-rb_class_inherited_p(mod, arg)
- VALUE mod, arg;
-{
- VALUE start = mod;
-
- if (mod == arg) return Qtrue;
- switch (TYPE(arg)) {
- case T_MODULE:
- case T_CLASS:
- break;
- default:
- rb_raise(rb_eTypeError, "compared with non class/module");
- }
- while (mod) {
- if (RCLASS(mod)->m_tbl == RCLASS(arg)->m_tbl)
- return Qtrue;
- mod = RCLASS(mod)->super;
- }
- /* not mod < arg; check if mod > arg */
- while (arg) {
- if (RCLASS(arg)->m_tbl == RCLASS(start)->m_tbl)
- return Qfalse;
- arg = RCLASS(arg)->super;
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * mod < other => true, false, or nil
- *
- * Returns true if <i>mod</i> is a subclass of <i>other</i>. Returns
- * <code>nil</code> if there's no relationship between the two.
- * (Think of the relationship in terms of the class definition:
- * "class A<B" implies "A<B").
- *
- */
-
-static VALUE
-rb_mod_lt(mod, arg)
- VALUE mod, arg;
-{
- if (mod == arg) return Qfalse;
- return rb_class_inherited_p(mod, arg);
-}
-
-
-/*
- * call-seq:
- * mod >= other => true, false, or nil
- *
- * Returns true if <i>mod</i> is an ancestor of <i>other</i>, or the
- * two modules are the same. Returns
- * <code>nil</code> if there's no relationship between the two.
- * (Think of the relationship in terms of the class definition:
- * "class A<B" implies "B>A").
- *
- */
-
-static VALUE
-rb_mod_ge(mod, arg)
- VALUE mod, arg;
-{
- switch (TYPE(arg)) {
- case T_MODULE:
- case T_CLASS:
- break;
- default:
- rb_raise(rb_eTypeError, "compared with non class/module");
- }
-
- return rb_class_inherited_p(arg, mod);
-}
-
-/*
- * call-seq:
- * mod > other => true, false, or nil
- *
- * Returns true if <i>mod</i> is an ancestor of <i>other</i>. Returns
- * <code>nil</code> if there's no relationship between the two.
- * (Think of the relationship in terms of the class definition:
- * "class A<B" implies "B>A").
- *
- */
-
-static VALUE
-rb_mod_gt(mod, arg)
- VALUE mod, arg;
-{
- if (mod == arg) return Qfalse;
- return rb_mod_ge(mod, arg);
-}
-
-/*
- * call-seq:
- * mod <=> other_mod => -1, 0, +1, or nil
- *
- * Comparison---Returns -1 if <i>mod</i> includes <i>other_mod</i>, 0 if
- * <i>mod</i> is the same as <i>other_mod</i>, and +1 if <i>mod</i> is
- * included by <i>other_mod</i> or if <i>mod</i> has no relationship with
- * <i>other_mod</i>. Returns <code>nil</code> if <i>other_mod</i> is
- * not a module.
- */
-
-static VALUE
-rb_mod_cmp(mod, arg)
- VALUE mod, arg;
-{
- VALUE cmp;
-
- if (mod == arg) return INT2FIX(0);
- switch (TYPE(arg)) {
- case T_MODULE:
- case T_CLASS:
- break;
- default:
- return Qnil;
- }
-
- cmp = rb_class_inherited_p(mod, arg);
- if (NIL_P(cmp)) return Qnil;
- if (cmp) {
- return INT2FIX(-1);
- }
- return INT2FIX(1);
-}
-
-static VALUE rb_module_s_alloc _((VALUE));
-static VALUE
-rb_module_s_alloc(klass)
- VALUE klass;
-{
- VALUE mod = rb_module_new();
-
- RBASIC(mod)->klass = klass;
- return mod;
-}
-
-static VALUE rb_class_s_alloc _((VALUE));
-static VALUE
-rb_class_s_alloc(klass)
- VALUE klass;
-{
- return rb_class_boot(0);
-}
-
-/*
- * call-seq:
- * Module.new => mod
- * Module.new {|mod| block } => mod
- *
- * Creates a new anonymous module. If a block is given, it is passed
- * the module object, and the block is evaluated in the context of this
- * module using <code>module_eval</code>.
- *
- * Fred = Module.new do
- * def meth1
- * "hello"
- * end
- * def meth2
- * "bye"
- * end
- * end
- * a = "my string"
- * a.extend(Fred) #=> "my string"
- * a.meth1 #=> "hello"
- * a.meth2 #=> "bye"
- */
-
-static VALUE
-rb_mod_initialize(module)
- VALUE module;
-{
- if (rb_block_given_p()) {
- rb_mod_module_eval(0, 0, module);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * Class.new(super_class=Object) => a_class
- *
- * Creates a new anonymous (unnamed) class with the given superclass
- * (or <code>Object</code> if no parameter is given). You can give a
- * class a name by assigning the class object to a constant.
- *
- */
-
-static VALUE
-rb_class_initialize(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE super;
-
- if (RCLASS(klass)->super != 0) {
- rb_raise(rb_eTypeError, "already initialized class");
- }
- if (rb_scan_args(argc, argv, "01", &super) == 0) {
- super = rb_cObject;
- }
- else {
- rb_check_inheritable(super);
- }
- RCLASS(klass)->super = super;
- rb_make_metaclass(klass, RBASIC(super)->klass);
- rb_class_inherited(super, klass);
- rb_mod_initialize(klass);
-
- return klass;
-}
-
-/*
- * call-seq:
- * class.allocate() => obj
- *
- * Allocates space for a new object of <i>class</i>'s class. The
- * returned object must be an instance of <i>class</i>.
- *
- */
-
-VALUE
-rb_obj_alloc(klass)
- VALUE klass;
-{
- VALUE obj;
-
- if (RCLASS(klass)->super == 0) {
- rb_raise(rb_eTypeError, "can't instantiate uninitialized class");
- }
- if (FL_TEST(klass, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "can't create instance of singleton class");
- }
- obj = rb_funcall(klass, ID_ALLOCATOR, 0, 0);
- if (rb_obj_class(obj) != rb_class_real(klass)) {
- rb_raise(rb_eTypeError, "wrong instance allocation");
- }
- return obj;
-}
-
-static VALUE rb_class_allocate_instance _((VALUE));
-static VALUE
-rb_class_allocate_instance(klass)
- VALUE klass;
-{
- NEWOBJ(obj, struct RObject);
- OBJSETUP(obj, klass, T_OBJECT);
- return (VALUE)obj;
-}
-
-/*
- * call-seq:
- * class.new(args, ...) => obj
- *
- * Calls <code>allocate</code> to create a new object of
- * <i>class</i>'s class, then invokes that object's
- * <code>initialize</code> method, passing it <i>args</i>.
- * This is the method that ends up getting called whenever
- * an object is constructed using .new.
- *
- */
-
-VALUE
-rb_class_new_instance(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE obj;
-
- obj = rb_obj_alloc(klass);
- rb_obj_call_init(obj, argc, argv);
-
- return obj;
-}
-
-/*
- * call-seq:
- * class.superclass -> a_super_class or nil
- *
- * Returns the superclass of <i>class</i>, or <code>nil</code>.
- *
- * File.superclass #=> IO
- * IO.superclass #=> Object
- * Object.superclass #=> nil
- *
- */
-
-static VALUE
-rb_class_superclass(klass)
- VALUE klass;
-{
- VALUE super = RCLASS(klass)->super;
-
- if (!super) {
- rb_raise(rb_eTypeError, "uninitialized class");
- }
- while (TYPE(super) == T_ICLASS) {
- super = RCLASS(super)->super;
- }
- if (!super) {
- return Qnil;
- }
- return super;
-}
-
-static ID
-str_to_id(str)
- VALUE str;
-{
- if (!RSTRING(str)->ptr || RSTRING(str)->len == 0) {
- rb_raise(rb_eArgError, "empty symbol string");
- }
- if (RSTRING(str)->len != strlen(RSTRING(str)->ptr)) {
- rb_raise(rb_eArgError, "Symbols should not contain NUL (\\0)");
- }
- return rb_intern(RSTRING(str)->ptr);
-}
-
-ID
-rb_to_id(name)
- VALUE name;
-{
- VALUE tmp;
- ID id;
-
- switch (TYPE(name)) {
- case T_STRING:
- return str_to_id(name);
- case T_FIXNUM:
- rb_warn("do not use Fixnums as Symbols");
- id = FIX2LONG(name);
- if (!rb_id2name(id)) {
- rb_raise(rb_eArgError, "%ld is not a symbol", id);
- }
- break;
- case T_SYMBOL:
- id = SYM2ID(name);
- break;
- default:
- tmp = rb_check_string_type(name);
- if (!NIL_P(tmp)) {
- return str_to_id(tmp);
- }
- rb_raise(rb_eTypeError, "%s is not a symbol", RSTRING(rb_inspect(name))->ptr);
- }
- return id;
-}
-
-/*
- * call-seq:
- * attr(symbol, writable=false) => nil
- *
- * Defines a named attribute for this module, where the name is
- * <i>symbol.</i><code>id2name</code>, creating an instance variable
- * (<code>@name</code>) and a corresponding access method to read it.
- * If the optional <i>writable</i> argument is <code>true</code>, also
- * creates a method called <code>name=</code> to set the attribute.
- *
- * module Mod
- * attr :size, true
- * end
- *
- * <em>is equivalent to:</em>
- *
- * module Mod
- * def size
- * @size
- * end
- * def size=(val)
- * @size = val
- * end
- * end
- */
-
-static VALUE
-rb_mod_attr(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE name, pub;
-
- rb_scan_args(argc, argv, "11", &name, &pub);
- rb_attr(klass, rb_to_id(name), 1, RTEST(pub), Qtrue);
- return Qnil;
-}
-
-/*
- * call-seq:
- * attr_reader(symbol, ...) => nil
- *
- * Creates instance variables and corresponding methods that return the
- * value of each instance variable. Equivalent to calling
- * ``<code>attr</code><i>:name</i>'' on each name in turn.
- */
-
-static VALUE
-rb_mod_attr_reader(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- int i;
-
- for (i=0; i<argc; i++) {
- rb_attr(klass, rb_to_id(argv[i]), 1, 0, Qtrue);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * attr_writer(symbol, ...) => nil
- *
- * Creates an accessor method to allow assignment to the attribute
- * <i>aSymbol</i><code>.id2name</code>.
- */
-
-static VALUE
-rb_mod_attr_writer(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- int i;
-
- for (i=0; i<argc; i++) {
- rb_attr(klass, rb_to_id(argv[i]), 0, 1, Qtrue);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * attr_accessor(symbol, ...) => nil
- *
- * Equivalent to calling ``<code>attr</code><i>symbol</i><code>,
- * true</code>'' on each <i>symbol</i> in turn.
- *
- * module Mod
- * attr_accessor(:one, :two)
- * end
- * Mod.instance_methods.sort #=> ["one", "one=", "two", "two="]
- */
-
-static VALUE
-rb_mod_attr_accessor(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- int i;
-
- for (i=0; i<argc; i++) {
- rb_attr(klass, rb_to_id(argv[i]), 1, 1, Qtrue);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * mod.const_get(sym) => obj
- *
- * Returns the value of the named constant in <i>mod</i>.
- *
- * Math.const_get(:PI) #=> 3.14159265358979
- */
-
-static VALUE
-rb_mod_const_get(mod, name)
- VALUE mod, name;
-{
- ID id = rb_to_id(name);
-
- if (!rb_is_const_id(id)) {
- rb_name_error(id, "wrong constant name %s", rb_id2name(id));
- }
- return rb_const_get(mod, id);
-}
-
-/*
- * call-seq:
- * mod.const_set(sym, obj) => obj
- *
- * Sets the named constant to the given object, returning that object.
- * Creates a new constant if no constant with the given name previously
- * existed.
- *
- * Math.const_set("HIGH_SCHOOL_PI", 22.0/7.0) #=> 3.14285714285714
- * Math::HIGH_SCHOOL_PI - Math::PI #=> 0.00126448926734968
- */
-
-static VALUE
-rb_mod_const_set(mod, name, value)
- VALUE mod, name, value;
-{
- ID id = rb_to_id(name);
-
- if (!rb_is_const_id(id)) {
- rb_name_error(id, "wrong constant name %s", rb_id2name(id));
- }
- rb_const_set(mod, id, value);
- return value;
-}
-
-/*
- * call-seq:
- * mod.const_defined?(sym) => true or false
- *
- * Returns <code>true</code> if a constant with the given name is
- * defined by <i>mod</i>.
- *
- * Math.const_defined? "PI" #=> true
- */
-
-static VALUE
-rb_mod_const_defined(mod, name)
- VALUE mod, name;
-{
- ID id = rb_to_id(name);
-
- if (!rb_is_const_id(id)) {
- rb_name_error(id, "wrong constant name %s", rb_id2name(id));
- }
- return rb_const_defined_at(mod, id);
-}
-
-/*
- * call-seq:
- * obj.methods => array
- *
- * Returns a list of the names of methods publicly accessible in
- * <i>obj</i>. This will include all the methods accessible in
- * <i>obj</i>'s ancestors.
- *
- * class Klass
- * def kMethod()
- * end
- * end
- * k = Klass.new
- * k.methods[0..9] #=> ["kMethod", "freeze", "nil?", "is_a?",
- * "class", "instance_variable_set",
- * "methods", "extend", "__send__", "instance_eval"]
- * k.methods.length #=> 42
- */
-
-
-static VALUE
-rb_obj_methods(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- retry:
- if (argc == 0) {
- VALUE args[1];
-
- args[0] = Qtrue;
- return rb_class_instance_methods(1, args, CLASS_OF(obj));
- }
- else {
- VALUE recur;
-
- rb_scan_args(argc, argv, "1", &recur);
- if (RTEST(recur)) {
- argc = 0;
- goto retry;
- }
- return rb_obj_singleton_methods(argc, argv, obj);
- }
-}
-
-/*
- * call-seq:
- * obj.protected_methods(all=true) => array
- *
- * Returns the list of protected methods accessible to <i>obj</i>. If
- * the <i>all</i> parameter is set to <code>false</code>, only those methods
- * in the receiver will be listed.
- */
-
-static VALUE
-rb_obj_protected_methods(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- if (argc == 0) { /* hack to stop warning */
- VALUE args[1];
-
- args[0] = Qtrue;
- return rb_class_protected_instance_methods(1, args, CLASS_OF(obj));
- }
- return rb_class_protected_instance_methods(argc, argv, CLASS_OF(obj));
-}
-
-/*
- * call-seq:
- * obj.private_methods(all=true) => array
- *
- * Returns the list of private methods accessible to <i>obj</i>. If
- * the <i>all</i> parameter is set to <code>false</code>, only those methods
- * in the receiver will be listed.
- */
-
-static VALUE
-rb_obj_private_methods(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- if (argc == 0) { /* hack to stop warning */
- VALUE args[1];
-
- args[0] = Qtrue;
- return rb_class_private_instance_methods(1, args, CLASS_OF(obj));
- }
- return rb_class_private_instance_methods(argc, argv, CLASS_OF(obj));
-}
-
-/*
- * call-seq:
- * obj.public_methods(all=true) => array
- *
- * Returns the list of public methods accessible to <i>obj</i>. If
- * the <i>all</i> parameter is set to <code>false</code>, only those methods
- * in the receiver will be listed.
- */
-
-static VALUE
-rb_obj_public_methods(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- if (argc == 0) { /* hack to stop warning */
- VALUE args[1];
-
- args[0] = Qtrue;
- return rb_class_public_instance_methods(1, args, CLASS_OF(obj));
- }
- return rb_class_public_instance_methods(argc, argv, CLASS_OF(obj));
-}
-
-/*
- * call-seq:
- * obj.instance_variable_get(symbol) => obj
- *
- * Returns the value of the given instance variable (or throws a
- * <code>NameError</code> exception). The <code>@</code> part of the
- * variable name should be included for regular instance variables
- *
- * class Fred
- * def initialize(p1, p2)
- * @a, @b = p1, p2
- * end
- * end
- * fred = Fred.new('cat', 99)
- * fred.instance_variable_get(:@a) #=> "cat"
- * fred.instance_variable_get("@b") #=> 99
- */
-
-static VALUE
-rb_obj_ivar_get(obj, iv)
- VALUE obj, iv;
-{
- ID id = rb_to_id(iv);
-
- if (!rb_is_instance_id(id)) {
- rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
- }
- return rb_ivar_get(obj, id);
-}
-
-
-/*
- * call-seq:
- * obj.instance_variable_set(symbol, obj) => obj
- *
- * Sets the instance variable names by <i>symbol</i> to
- * <i>object</i>, thereby frustrating the efforts of the class's
- * author to attempt to provide proper encapsulation. The variable
- * did not have to exist prior to this call.
- *
- * class Fred
- * def initialize(p1, p2)
- * @a, @b = p1, p2
- * end
- * end
- * fred = Fred.new('cat', 99)
- * fred.instance_variable_set(:@a, 'dog') #=> "dog"
- * fred.instance_variable_set(:@c, 'cat') #=> "cat"
- * fred.inspect #=> "#<Fred:0x401b3da8 @a=\"dog\", @b=99, @c=\"cat\">"
- */
-
-static VALUE
-rb_obj_ivar_set(obj, iv, val)
- VALUE obj, iv, val;
-{
- ID id = rb_to_id(iv);
-
- if (!rb_is_instance_id(id)) {
- rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
- }
- return rb_ivar_set(obj, id, val);
-}
-
-/*
- * call-seq:
- * mod.class_variable_get(symbol) => obj
- *
- * Returns the value of the given class variable (or throws a
- * <code>NameError</code> exception). The <code>@@</code> part of the
- * variable name should be included for regular class variables
- *
- * class Fred
- * @@foo = 99
- * end
- * Fred.class_variable_get(:@foo) #=> 99
- */
-
-static VALUE
-rb_mod_cvar_get(obj, iv)
- VALUE obj, iv;
-{
- ID id = rb_to_id(iv);
-
- if (!rb_is_class_id(id)) {
- rb_name_error(id, "`%s' is not allowed as an class variable name", rb_id2name(id));
- }
- return rb_cvar_get(obj, id);
-}
-
-
-/*
- * call-seq:
- * obj.class_variable_set(symbol, obj) => obj
- *
- * Sets the class variable names by <i>symbol</i> to
- * <i>object</i>.
- *
- * class Fred
- * @@foo = 99
- * def foo
- * @@foo
- * end
- * end
- * Fred.class_variable_set(:@foo, 101) #=> 101
- * Fred.new.foo #=> 101
- */
-
-static VALUE
-rb_mod_cvar_set(obj, iv, val)
- VALUE obj, iv, val;
-{
- ID id = rb_to_id(iv);
-
- if (!rb_is_class_id(id)) {
- rb_name_error(id, "`%s' is not allowed as an class variable name", rb_id2name(id));
- }
- rb_cvar_set(obj, id, val, Qfalse);
- return val;
-}
-
-static VALUE
-convert_type(val, tname, method, raise)
- VALUE val;
- const char *tname, *method;
- int raise;
-{
- ID m;
-
- m = rb_intern(method);
- if (!rb_respond_to(val, m)) {
- if (raise) {
- rb_raise(rb_eTypeError, "can't convert %s into %s",
- NIL_P(val) ? "nil" :
- val == Qtrue ? "true" :
- val == Qfalse ? "false" :
- rb_obj_classname(val),
- tname);
- }
- else {
- return Qnil;
- }
- }
- return rb_funcall(val, m, 0);
-}
-
-VALUE
-rb_convert_type(val, type, tname, method)
- VALUE val;
- int type;
- const char *tname, *method;
-{
- VALUE v;
-
- if (TYPE(val) == type) return val;
- v = convert_type(val, tname, method, Qtrue);
- if (TYPE(v) != type) {
- char *cname = rb_obj_classname(val);
- rb_raise(rb_eTypeError, "can't convert %s to %s (%s#%s gives %s)",
- cname, tname, cname, method, rb_obj_classname(v));
- }
- return v;
-}
-
-VALUE
-rb_check_convert_type(val, type, tname, method)
- VALUE val;
- int type;
- const char *tname, *method;
-{
- VALUE v;
-
- /* always convert T_DATA */
- if (TYPE(val) == type && type != T_DATA) return val;
- v = convert_type(val, tname, method, Qfalse);
- if (NIL_P(v)) return Qnil;
- if (TYPE(v) != type) {
- char *cname = rb_obj_classname(val);
- rb_raise(rb_eTypeError, "can't convert %s to %s (%s#%s gives %s)",
- cname, tname, cname, method, rb_obj_classname(v));
- }
- return v;
-}
-
-
-static VALUE
-rb_to_integer(val, method)
- VALUE val;
- char *method;
-{
- VALUE v = convert_type(val, "Integer", method, Qtrue);
- if (!rb_obj_is_kind_of(v, rb_cInteger)) {
- char *cname = rb_obj_classname(val);
- rb_raise(rb_eTypeError, "can't convert %s to Integer (%s#%s gives %s)",
- cname, cname, method, rb_obj_classname(v));
- }
- return v;
-}
-
-VALUE
-rb_to_int(val)
- VALUE val;
-{
- return rb_to_integer(val, "to_int");
-}
-
-VALUE
-rb_Integer(val)
- VALUE val;
-{
- VALUE tmp;
-
- switch (TYPE(val)) {
- case T_FLOAT:
- if (RFLOAT(val)->value <= (double)FIXNUM_MAX
- && RFLOAT(val)->value >= (double)FIXNUM_MIN) {
- break;
- }
- return rb_dbl2big(RFLOAT(val)->value);
-
- case T_FIXNUM:
- case T_BIGNUM:
- return val;
-
- case T_STRING:
- return rb_str_to_inum(val, 0, Qtrue);
-
- default:
- break;
- }
- tmp = convert_type(val, "Integer", "to_int", Qfalse);
- if (NIL_P(tmp)) {
- return rb_to_integer(val, "to_i");
- }
- return tmp;
-}
-
-/*
- * call-seq:
- * Integer(arg) => integer
- *
- * Converts <i>arg</i> to a <code>Fixnum</code> or <code>Bignum</code>.
- * Numeric types are converted directly (with floating point numbers
- * being truncated). If <i>arg</i> is a <code>String</code>, leading
- * radix indicators (<code>0</code>, <code>0b</code>, and
- * <code>0x</code>) are honored. Others are converted using
- * <code>to_int</code> and <code>to_i</code>. This behavior is
- * different from that of <code>String#to_i</code>.
- *
- * Integer(123.999) #=> 123
- * Integer("0x1a") #=> 26
- * Integer(Time.new) #=> 1049896590
- */
-
-static VALUE
-rb_f_integer(obj, arg)
- VALUE obj, arg;
-{
- return rb_Integer(arg);
-}
-
-double
-rb_cstr_to_dbl(p, badcheck)
- const char *p;
- int badcheck;
-{
- const char *q;
- char *end;
- double d;
-
- if (!p) return 0.0;
- q = p;
- if (badcheck) {
- while (ISSPACE(*p)) p++;
- }
- else {
- while (ISSPACE(*p) || *p == '_') p++;
- }
- d = strtod(p, &end);
- if (errno == ERANGE) {
- rb_warn("Float %*s out of range", end-p, p);
- errno = 0;
- }
- if (p == end) {
- if (badcheck) {
- bad:
- rb_invalid_str(q, "Float()");
- }
- return d;
- }
- if (*end) {
- char *buf = ALLOCA_N(char, strlen(p)+1);
- char *n = buf;
-
- while (p < end) *n++ = *p++;
- while (*p) {
- if (*p == '_') {
- /* remove underscores between digits */
- if (badcheck) {
- if (n == buf || !ISDIGIT(n[-1])) goto bad;
- ++p;
- if (!ISDIGIT(*p)) goto bad;
- }
- else {
- while (*++p == '_');
- continue;
- }
- }
- *n++ = *p++;
- }
- *n = '\0';
- p = buf;
- d = strtod(p, &end);
- if (errno == ERANGE) {
- rb_warn("Float %*s out of range", end-p, p);
- errno = 0;
- }
- if (badcheck) {
- if (p == end) goto bad;
- while (*end && ISSPACE(*end)) end++;
- if (*end) goto bad;
- }
- }
- if (errno == ERANGE) {
- errno = 0;
- rb_raise(rb_eArgError, "Float %s out of range", q);
- }
- return d;
-}
-
-double
-rb_str_to_dbl(str, badcheck)
- VALUE str;
- int badcheck;
-{
- char *s;
- long len;
-
- StringValue(str);
- s = RSTRING(str)->ptr;
- len = RSTRING(str)->len;
- if (s) {
- if (s[len]) { /* no sentinel somehow */
- char *p = ALLOCA_N(char, len+1);
-
- MEMCPY(p, s, char, len);
- p[len] = '\0';
- s = p;
- }
- if (badcheck && len != strlen(s)) {
- rb_raise(rb_eArgError, "string for Float contains null byte");
- }
- }
- return rb_cstr_to_dbl(s, badcheck);
-}
-
-VALUE
-rb_Float(val)
- VALUE val;
-{
- switch (TYPE(val)) {
- case T_FIXNUM:
- return rb_float_new((double)FIX2LONG(val));
-
- case T_FLOAT:
- return val;
-
- case T_BIGNUM:
- return rb_float_new(rb_big2dbl(val));
-
- case T_STRING:
- return rb_float_new(rb_str_to_dbl(val, Qtrue));
-
- case T_NIL:
- rb_raise(rb_eTypeError, "can't convert nil into Float");
- break;
-
- default:
- {
- VALUE f = rb_convert_type(val, T_FLOAT, "Float", "to_f");
- if (isnan(RFLOAT(f)->value)) {
- rb_raise(rb_eArgError, "invalid value for Float()");
- }
- return f;
- }
- }
-}
-
-/*
- * call-seq:
- * Float(arg) => float
- *
- * Returns <i>arg</i> converted to a float. Numeric types are converted
- * directly, the rest are converted using <i>arg</i>.to_f. As of Ruby
- * 1.8, converting <code>nil</code> generates a <code>TypeError</code>.
- *
- * Float(1) #=> 1.0
- * Float("123.456") #=> 123.456
- */
-
-static VALUE
-rb_f_float(obj, arg)
- VALUE obj, arg;
-{
- return rb_Float(arg);
-}
-
-double
-rb_num2dbl(val)
- VALUE val;
-{
- switch (TYPE(val)) {
- case T_FLOAT:
- return RFLOAT(val)->value;
-
- case T_STRING:
- rb_raise(rb_eTypeError, "no implicit conversion to float from string");
- break;
-
- case T_NIL:
- rb_raise(rb_eTypeError, "no implicit conversion to float from nil");
- break;
-
- default:
- break;
- }
-
- return RFLOAT(rb_Float(val))->value;
-}
-
-char*
-rb_str2cstr(str, len)
- VALUE str;
- long *len;
-{
- StringValue(str);
- if (len) *len = RSTRING(str)->len;
- else if (RTEST(ruby_verbose) && RSTRING(str)->len != strlen(RSTRING(str)->ptr)) {
- rb_warn("string contains \\0 character");
- }
- return RSTRING(str)->ptr;
-}
-
-VALUE
-rb_String(val)
- VALUE val;
-{
- return rb_convert_type(val, T_STRING, "String", "to_s");
-}
-
-
-/*
- * call-seq:
- * String(arg) => string
- *
- * Converts <i>arg</i> to a <code>String</code> by calling its
- * <code>to_s</code> method.
- *
- * String(self) #=> "main"
- * String(self.class #=> "Object"
- * String(123456) #=> "123456"
- */
-
-static VALUE
-rb_f_string(obj, arg)
- VALUE obj, arg;
-{
- return rb_String(arg);
-}
-
-VALUE
-rb_Array(val)
- VALUE val;
-{
- VALUE tmp = rb_check_array_type(val);
-
- if (NIL_P(tmp)) {
- tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_a");
- if (NIL_P(tmp)) {
- return rb_ary_new3(1, val);
- }
- }
- return tmp;
-}
-
-/*
- * call-seq:
- * Array(arg) => array
- *
- * Returns <i>arg</i> as an <code>Array</code>. First tries to call
- * <i>arg</i><code>.to_ary</code>, then <i>arg</i><code>.to_a</code>.
- * If both fail, creates a single element array containing <i>arg</i>
- * (unless <i>arg</i> is <code>nil</code>).
- *
- * Array(1..5) #=> [1, 2, 3, 4, 5]
- */
-
-static VALUE
-rb_f_array(obj, arg)
- VALUE obj, arg;
-{
- return rb_Array(arg);
-}
-
-static VALUE
-boot_defclass(name, super)
- char *name;
- VALUE super;
-{
- extern st_table *rb_class_tbl;
- VALUE obj = rb_class_boot(super);
- ID id = rb_intern(name);
-
- rb_name_class(obj, id);
- st_add_direct(rb_class_tbl, id, obj);
- rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
- return obj;
-}
-
-VALUE ruby_top_self;
-
-/*
- * Document-class: Class
- *
- * Classes in Ruby are first-class objects---each is an instance of
- * class <code>Class</code>.
- *
- * When a new class is created (typically using <code>class Name ...
- * end</code>), an object of type <code>Class</code> is created and
- * assigned to a global constant (<code>Name</code> in this case). When
- * <code>Name.new</code> is called to create a new object, the
- * <code>new</code> method in <code>Class</code> is run by default.
- * This can be demonstrated by overriding <code>new</code> in
- * <code>Class</code>:
- *
- * class Class
- * alias oldNew new
- * def new(*args)
- * print "Creating a new ", self.name, "\n"
- * oldNew(*args)
- * end
- * end
- *
- *
- * class Name
- * end
- *
- *
- * n = Name.new
- *
- * <em>produces:</em>
- *
- * Creating a new Name
- *
- * Classes, modules, and objects are interrelated. In the diagram
- * that follows, the arrows represent inheritance, and the
- * parentheses meta-classes. All metaclasses are instances
- * of the class `Class'.
- *
- * +------------------+
- * | |
- * Object---->(Object) |
- * ^ ^ ^ ^ |
- * | | | | |
- * | | +-----+ +---------+ |
- * | | | | |
- * | +-----------+ | |
- * | | | | |
- * +------+ | Module--->(Module) |
- * | | ^ ^ |
- * OtherClass-->(OtherClass) | | |
- * | | |
- * Class---->(Class) |
- * ^ |
- * | |
- * +----------------+
- */
-
-
-/*
- * <code>Object</code> is the parent class of all classes in Ruby. Its
- * methods are therefore available to all objects unless explicitly
- * overridden.
- *
- * <code>Object</code> mixes in the <code>Kernel</code> module, making
- * the built-in kernel functions globally accessible. Although the
- * instance methods of <code>Object</code> are defined by the
- * <code>Kernel</code> module, we have chosen to document them here for
- * clarity.
- *
- * In the descriptions of Object's methods, the parameter <i>symbol</i> refers
- * to a symbol, which is either a quoted string or a
- * <code>Symbol</code> (such as <code>:name</code>).
- */
-
-void
-Init_Object()
-{
- VALUE metaclass;
-
- rb_cObject = boot_defclass("Object", 0);
- rb_cModule = boot_defclass("Module", rb_cObject);
- rb_cClass = boot_defclass("Class", rb_cModule);
-
- metaclass = rb_make_metaclass(rb_cObject, rb_cClass);
- metaclass = rb_make_metaclass(rb_cModule, metaclass);
- metaclass = rb_make_metaclass(rb_cClass, metaclass);
-
- rb_mKernel = rb_define_module("Kernel");
- rb_include_module(rb_cObject, rb_mKernel);
- rb_define_alloc_func(rb_cObject, rb_class_allocate_instance);
- rb_define_private_method(rb_cObject, "initialize", rb_obj_dummy, 0);
- rb_define_private_method(rb_cClass, "inherited", rb_obj_dummy, 1);
- rb_define_private_method(rb_cModule, "included", rb_obj_dummy, 1);
- rb_define_private_method(rb_cModule, "extended", rb_obj_dummy, 1);
- rb_define_private_method(rb_cModule, "method_added", rb_obj_dummy, 1);
- rb_define_private_method(rb_cModule, "method_removed", rb_obj_dummy, 1);
- rb_define_private_method(rb_cModule, "method_undefined", rb_obj_dummy, 1);
-
-
- rb_define_method(rb_mKernel, "nil?", rb_false, 0);
- rb_define_method(rb_mKernel, "==", rb_obj_equal, 1);
- rb_define_method(rb_mKernel, "equal?", rb_obj_equal, 1);
- rb_define_method(rb_mKernel, "===", rb_equal, 1);
- rb_define_method(rb_mKernel, "=~", rb_obj_pattern_match, 1);
-
- rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);
-
- rb_define_method(rb_mKernel, "hash", rb_obj_id, 0);
- rb_define_method(rb_mKernel, "__id__", rb_obj_id, 0);
- rb_define_method(rb_mKernel, "object_id", rb_obj_id, 0);
- rb_define_method(rb_mKernel, "class", rb_obj_class, 0);
-
- rb_define_method(rb_mKernel, "clone", rb_obj_clone, 0);
- rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
- rb_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1);
-
- rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0);
- rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0);
- rb_define_method(rb_mKernel, "untaint", rb_obj_untaint, 0);
- rb_define_method(rb_mKernel, "freeze", rb_obj_freeze, 0);
- rb_define_method(rb_mKernel, "frozen?", rb_obj_frozen_p, 0);
-
- rb_define_method(rb_mKernel, "to_s", rb_any_to_s, 0);
- rb_define_method(rb_mKernel, "inspect", rb_obj_inspect, 0);
- rb_define_method(rb_mKernel, "methods", rb_obj_methods, -1);
- rb_define_method(rb_mKernel, "singleton_methods", rb_obj_singleton_methods, -1); /* in class.c */
- rb_define_method(rb_mKernel, "protected_methods", rb_obj_protected_methods, -1);
- rb_define_method(rb_mKernel, "private_methods", rb_obj_private_methods, -1);
- rb_define_method(rb_mKernel, "public_methods", rb_obj_public_methods, -1);
- rb_define_method(rb_mKernel, "instance_variables", rb_obj_instance_variables, 0); /* in variable.c */
- rb_define_method(rb_mKernel, "instance_variable_get", rb_obj_ivar_get, 1);
- rb_define_method(rb_mKernel, "instance_variable_set", rb_obj_ivar_set, 2);
- rb_define_private_method(rb_mKernel, "remove_instance_variable",
- rb_obj_remove_instance_variable, 1); /* in variable.c */
-
- rb_define_method(rb_mKernel, "instance_of?", rb_obj_is_instance_of, 1);
- rb_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of, 1);
- rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);
-
- rb_define_private_method(rb_mKernel, "singleton_method_added", rb_obj_dummy, 1);
- rb_define_private_method(rb_mKernel, "singleton_method_removed", rb_obj_dummy, 1);
- rb_define_private_method(rb_mKernel, "singleton_method_undefined", rb_obj_dummy, 1);
-
- rb_define_global_function("sprintf", rb_f_sprintf, -1); /* in sprintf.c */
- rb_define_global_function("format", rb_f_sprintf, -1); /* in sprintf.c */
-
- rb_define_global_function("Integer", rb_f_integer, 1);
- rb_define_global_function("Float", rb_f_float, 1);
-
- rb_define_global_function("String", rb_f_string, 1);
- rb_define_global_function("Array", rb_f_array, 1);
-
- rb_cNilClass = rb_define_class("NilClass", rb_cObject);
- rb_define_method(rb_cNilClass, "to_i", nil_to_i, 0);
- rb_define_method(rb_cNilClass, "to_f", nil_to_f, 0);
- rb_define_method(rb_cNilClass, "to_s", nil_to_s, 0);
- rb_define_method(rb_cNilClass, "to_a", nil_to_a, 0);
- rb_define_method(rb_cNilClass, "inspect", nil_inspect, 0);
- rb_define_method(rb_cNilClass, "&", false_and, 1);
- rb_define_method(rb_cNilClass, "|", false_or, 1);
- rb_define_method(rb_cNilClass, "^", false_xor, 1);
-
- rb_define_method(rb_cNilClass, "nil?", rb_true, 0);
- rb_undef_alloc_func(rb_cNilClass);
- rb_undef_method(CLASS_OF(rb_cNilClass), "new");
- rb_define_global_const("NIL", Qnil);
-
- rb_cSymbol = rb_define_class("Symbol", rb_cObject);
- rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0); /* in parse.y */
- rb_undef_alloc_func(rb_cSymbol);
- rb_undef_method(CLASS_OF(rb_cSymbol), "new");
-
- rb_define_method(rb_cSymbol, "to_i", sym_to_i, 0);
- rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
- rb_define_method(rb_cSymbol, "to_s", sym_to_s, 0);
- rb_define_method(rb_cSymbol, "id2name", sym_to_s, 0);
- rb_define_method(rb_cSymbol, "to_sym", sym_to_sym, 0);
- rb_define_method(rb_cSymbol, "===", rb_obj_equal, 1);
-
- rb_define_method(rb_cModule, "freeze", rb_mod_freeze, 0);
- rb_define_method(rb_cModule, "===", rb_mod_eqq, 1);
- rb_define_method(rb_cModule, "==", rb_obj_equal, 1);
- rb_define_method(rb_cModule, "<=>", rb_mod_cmp, 1);
- rb_define_method(rb_cModule, "<", rb_mod_lt, 1);
- rb_define_method(rb_cModule, "<=", rb_class_inherited_p, 1);
- rb_define_method(rb_cModule, ">", rb_mod_gt, 1);
- rb_define_method(rb_cModule, ">=", rb_mod_ge, 1);
- rb_define_method(rb_cModule, "initialize_copy", rb_mod_init_copy, 1); /* in class.c */
- rb_define_method(rb_cModule, "to_s", rb_mod_to_s, 0);
- rb_define_method(rb_cModule, "included_modules", rb_mod_included_modules, 0); /* in class.c */
- rb_define_method(rb_cModule, "include?", rb_mod_include_p, 1); /* in class.c */
- rb_define_method(rb_cModule, "name", rb_mod_name, 0); /* in variable.c */
- rb_define_method(rb_cModule, "ancestors", rb_mod_ancestors, 0); /* in class.c */
-
- rb_define_private_method(rb_cModule, "attr", rb_mod_attr, -1);
- rb_define_private_method(rb_cModule, "attr_reader", rb_mod_attr_reader, -1);
- rb_define_private_method(rb_cModule, "attr_writer", rb_mod_attr_writer, -1);
- rb_define_private_method(rb_cModule, "attr_accessor", rb_mod_attr_accessor, -1);
-
- rb_define_alloc_func(rb_cModule, rb_module_s_alloc);
- rb_define_method(rb_cModule, "initialize", rb_mod_initialize, 0);
- rb_define_method(rb_cModule, "instance_methods", rb_class_instance_methods, -1); /* in class.c */
- rb_define_method(rb_cModule, "public_instance_methods",
- rb_class_public_instance_methods, -1); /* in class.c */
- rb_define_method(rb_cModule, "protected_instance_methods",
- rb_class_protected_instance_methods, -1); /* in class.c */
- rb_define_method(rb_cModule, "private_instance_methods",
- rb_class_private_instance_methods, -1); /* in class.c */
-
- rb_define_method(rb_cModule, "constants", rb_mod_constants, 0); /* in variable.c */
- rb_define_method(rb_cModule, "const_get", rb_mod_const_get, 1);
- rb_define_method(rb_cModule, "const_set", rb_mod_const_set, 2);
- rb_define_method(rb_cModule, "const_defined?", rb_mod_const_defined, 1);
- rb_define_private_method(rb_cModule, "remove_const",
- rb_mod_remove_const, 1); /* in variable.c */
- rb_define_method(rb_cModule, "const_missing",
- rb_mod_const_missing, 1); /* in variable.c */
- rb_define_method(rb_cModule, "class_variables",
- rb_mod_class_variables, 0); /* in variable.c */
- rb_define_private_method(rb_cModule, "remove_class_variable",
- rb_mod_remove_cvar, 1); /* in variable.c */
- rb_define_private_method(rb_cModule, "class_variable_get", rb_mod_cvar_get, 1);
- rb_define_private_method(rb_cModule, "class_variable_set", rb_mod_cvar_set, 2);
-
- rb_define_method(rb_cClass, "allocate", rb_obj_alloc, 0);
- rb_define_method(rb_cClass, "new", rb_class_new_instance, -1);
- rb_define_method(rb_cClass, "initialize", rb_class_initialize, -1);
- rb_define_method(rb_cClass, "initialize_copy", rb_class_init_copy, 1); /* in class.c */
- rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0);
- rb_define_alloc_func(rb_cClass, rb_class_s_alloc);
- rb_undef_method(rb_cClass, "extend_object");
- rb_undef_method(rb_cClass, "append_features");
-
- rb_cData = rb_define_class("Data", rb_cObject);
- rb_undef_alloc_func(rb_cData);
-
- ruby_top_self = rb_obj_alloc(rb_cObject);
- rb_global_variable(&ruby_top_self);
- rb_define_singleton_method(ruby_top_self, "to_s", main_to_s, 0);
-
- rb_cTrueClass = rb_define_class("TrueClass", rb_cObject);
- rb_define_method(rb_cTrueClass, "to_s", true_to_s, 0);
- rb_define_method(rb_cTrueClass, "&", true_and, 1);
- rb_define_method(rb_cTrueClass, "|", true_or, 1);
- rb_define_method(rb_cTrueClass, "^", true_xor, 1);
- rb_undef_alloc_func(rb_cTrueClass);
- rb_undef_method(CLASS_OF(rb_cTrueClass), "new");
- rb_define_global_const("TRUE", Qtrue);
-
- rb_cFalseClass = rb_define_class("FalseClass", rb_cObject);
- rb_define_method(rb_cFalseClass, "to_s", false_to_s, 0);
- rb_define_method(rb_cFalseClass, "&", false_and, 1);
- rb_define_method(rb_cFalseClass, "|", false_or, 1);
- rb_define_method(rb_cFalseClass, "^", false_xor, 1);
- rb_undef_alloc_func(rb_cFalseClass);
- rb_undef_method(CLASS_OF(rb_cFalseClass), "new");
- rb_define_global_const("FALSE", Qfalse);
-
- id_eq = rb_intern("==");
- id_eql = rb_intern("eql?");
- id_inspect = rb_intern("inspect");
- id_init_copy = rb_intern("initialize_copy");
-}
-/**********************************************************************
-
- pack.c -
-
- $Author: matz $
- $Date: 2005/03/04 06:47:42 $
- created at: Thu Feb 10 15:17:05 JST 1994
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include <sys/types.h>
-#include <ctype.h>
-
-#define SIZE16 2
-#define SIZE32 4
-
-#if SIZEOF_SHORT != 2 || SIZEOF_LONG != 4
-# define NATINT_PACK
-#endif
-
-#ifdef NATINT_PACK
-# define OFF16B(p) ((char*)(p) + (natint?0:(sizeof(short) - SIZE16)))
-# define OFF32B(p) ((char*)(p) + (natint?0:(sizeof(long) - SIZE32)))
-# define NATINT_LEN(type,len) (natint?sizeof(type):(len))
-# ifdef WORDS_BIGENDIAN
-# define OFF16(p) OFF16B(p)
-# define OFF32(p) OFF32B(p)
-# endif
-# define NATINT_HTOVS(x) (natint?htovs(x):htov16(x))
-# define NATINT_HTOVL(x) (natint?htovl(x):htov32(x))
-# define NATINT_HTONS(x) (natint?htons(x):hton16(x))
-# define NATINT_HTONL(x) (natint?htonl(x):hton32(x))
-#else
-# define NATINT_LEN(type,len) sizeof(type)
-# define NATINT_HTOVS(x) htovs(x)
-# define NATINT_HTOVL(x) htovl(x)
-# define NATINT_HTONS(x) htons(x)
-# define NATINT_HTONL(x) htonl(x)
-#endif
-
-#ifndef OFF16
-# define OFF16(p) (char*)(p)
-# define OFF32(p) (char*)(p)
-#endif
-#ifndef OFF16B
-# define OFF16B(p) (char*)(p)
-# define OFF32B(p) (char*)(p)
-#endif
-
-#define define_swapx(x, xtype) \
-static xtype \
-TOKEN_PASTE(swap,x)(z) \
- xtype z; \
-{ \
- xtype r; \
- xtype *zp; \
- unsigned char *s, *t; \
- int i; \
- \
- zp = malloc(sizeof(xtype)); \
- *zp = z; \
- s = (unsigned char*)zp; \
- t = malloc(sizeof(xtype)); \
- for (i=0; i<sizeof(xtype); i++) { \
- t[sizeof(xtype)-i-1] = s[i]; \
- } \
- r = *(xtype *)t; \
- free(t); \
- free(zp); \
- return r; \
-}
-
-#ifndef swap16
-#define swap16(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
-#endif
-#if SIZEOF_SHORT == 2
-#define swaps(x) swap16(x)
-#else
-#if SIZEOF_SHORT == 4
-#define swaps(x) ((((x)&0xFF)<<24) \
- |(((x)>>24)&0xFF) \
- |(((x)&0x0000FF00)<<8) \
- |(((x)&0x00FF0000)>>8) )
-#else
-define_swapx(s,short)
-#endif
-#endif
-
-#ifndef swap32
-#define swap32(x) ((((x)&0xFF)<<24) \
- |(((x)>>24)&0xFF) \
- |(((x)&0x0000FF00)<<8) \
- |(((x)&0x00FF0000)>>8) )
-#endif
-#if SIZEOF_LONG == 4
-#define swapl(x) swap32(x)
-#else
-#if SIZEOF_LONG == 8
-#define swapl(x) ((((x)&0x00000000000000FF)<<56) \
- |(((x)&0xFF00000000000000)>>56) \
- |(((x)&0x000000000000FF00)<<40) \
- |(((x)&0x00FF000000000000)>>40) \
- |(((x)&0x0000000000FF0000)<<24) \
- |(((x)&0x0000FF0000000000)>>24) \
- |(((x)&0x00000000FF000000)<<8) \
- |(((x)&0x000000FF00000000)>>8))
-#else
-define_swapx(l,long)
-#endif
-#endif
-
-#if SIZEOF_FLOAT == 4
-#if SIZEOF_LONG == 4 /* SIZEOF_FLOAT == 4 == SIZEOF_LONG */
-#define swapf(x) swapl(x)
-#define FLOAT_SWAPPER unsigned long
-#else
-#if SIZEOF_SHORT == 4 /* SIZEOF_FLOAT == 4 == SIZEOF_SHORT */
-#define swapf(x) swaps(x)
-#define FLOAT_SWAPPER unsigned short
-#else /* SIZEOF_FLOAT == 4 but undivide by known size of int */
-define_swapx(f,float)
-#endif /* #if SIZEOF_SHORT == 4 */
-#endif /* #if SIZEOF_LONG == 4 */
-#else /* SIZEOF_FLOAT != 4 */
-define_swapx(f,float)
-#endif /* #if SIZEOF_FLOAT == 4 */
-
-#if SIZEOF_DOUBLE == 8
-#if SIZEOF_LONG == 8 /* SIZEOF_DOUBLE == 8 == SIZEOF_LONG */
-#define swapd(x) swapl(x)
-#define DOUBLE_SWAPPER unsigned long
-#else
-#if SIZEOF_LONG == 4 /* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_LONG */
-static double
-swapd(d)
- const double d;
-{
- double dtmp = d;
- unsigned long utmp[2];
- unsigned long utmp0;
-
- utmp[0] = 0; utmp[1] = 0;
- memcpy(utmp,&dtmp,sizeof(double));
- utmp0 = utmp[0];
- utmp[0] = swapl(utmp[1]);
- utmp[1] = swapl(utmp0);
- memcpy(&dtmp,utmp,sizeof(double));
- return dtmp;
-}
-#else
-#if SIZEOF_SHORT == 4 /* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_SHORT */
-static double
-swapd(d)
- const double d;
-{
- double dtmp = d;
- unsigned short utmp[2];
- unsigned short utmp0;
-
- utmp[0] = 0; utmp[1] = 0;
- memcpy(utmp,&dtmp,sizeof(double));
- utmp0 = utmp[0];
- utmp[0] = swaps(utmp[1]);
- utmp[1] = swaps(utmp0);
- memcpy(&dtmp,utmp,sizeof(double));
- return dtmp;
-}
-#else /* SIZEOF_DOUBLE == 8 but undivied by known size of int */
-define_swapx(d, double)
-#endif /* #if SIZEOF_SHORT == 4 */
-#endif /* #if SIZEOF_LONG == 4 */
-#endif /* #if SIZEOF_LONG == 8 */
-#else /* SIZEOF_DOUBLE != 8 */
-define_swapx(d, double)
-#endif /* #if SIZEOF_DOUBLE == 8 */
-
-#undef define_swapx
-
-#ifdef DYNAMIC_ENDIAN
-#ifdef ntohs
-#undef ntohs
-#undef ntohl
-#undef htons
-#undef htonl
-#endif
-static int
-endian()
-{
- static int init = 0;
- static int endian_value;
- char *p;
-
- if (init) return endian_value;
- init = 1;
- p = (char*)&init;
- return endian_value = p[0]?0:1;
-}
-
-#define ntohs(x) (endian()?(x):swaps(x))
-#define ntohl(x) (endian()?(x):swapl(x))
-#define ntohf(x) (endian()?(x):swapf(x))
-#define ntohd(x) (endian()?(x):swapd(x))
-#define htons(x) (endian()?(x):swaps(x))
-#define htonl(x) (endian()?(x):swapl(x))
-#define htonf(x) (endian()?(x):swapf(x))
-#define htond(x) (endian()?(x):swapd(x))
-#define htovs(x) (endian()?swaps(x):(x))
-#define htovl(x) (endian()?swapl(x):(x))
-#define htovf(x) (endian()?swapf(x):(x))
-#define htovd(x) (endian()?swapd(x):(x))
-#define vtohs(x) (endian()?swaps(x):(x))
-#define vtohl(x) (endian()?swapl(x):(x))
-#define vtohf(x) (endian()?swapf(x):(x))
-#define vtohd(x) (endian()?swapd(x):(x))
-# ifdef NATINT_PACK
-#define htov16(x) (endian()?swap16(x):(x))
-#define htov32(x) (endian()?swap32(x):(x))
-#define hton16(x) (endian()?(x):swap16(x))
-#define hton32(x) (endian()?(x):swap32(x))
-# endif
-#else
-#ifdef WORDS_BIGENDIAN
-#ifndef ntohs
-#define ntohs(x) (x)
-#define ntohl(x) (x)
-#define htons(x) (x)
-#define htonl(x) (x)
-#endif
-#define ntohf(x) (x)
-#define ntohd(x) (x)
-#define htonf(x) (x)
-#define htond(x) (x)
-#define htovs(x) swaps(x)
-#define htovl(x) swapl(x)
-#define htovf(x) swapf(x)
-#define htovd(x) swapd(x)
-#define vtohs(x) swaps(x)
-#define vtohl(x) swapl(x)
-#define vtohf(x) swapf(x)
-#define vtohd(x) swapd(x)
-# ifdef NATINT_PACK
-#define htov16(x) swap16(x)
-#define htov32(x) swap32(x)
-#define hton16(x) (x)
-#define hton32(x) (x)
-# endif
-#else /* LITTLE ENDIAN */
-#ifdef ntohs
-#undef ntohs
-#undef ntohl
-#undef htons
-#undef htonl
-#endif
-#define ntohs(x) swaps(x)
-#define ntohl(x) swapl(x)
-#define htons(x) swaps(x)
-#define htonl(x) swapl(x)
-#define ntohf(x) swapf(x)
-#define ntohd(x) swapd(x)
-#define htonf(x) swapf(x)
-#define htond(x) swapd(x)
-#define htovs(x) (x)
-#define htovl(x) (x)
-#define htovf(x) (x)
-#define htovd(x) (x)
-#define vtohs(x) (x)
-#define vtohl(x) (x)
-#define vtohf(x) (x)
-#define vtohd(x) (x)
-# ifdef NATINT_PACK
-#define htov16(x) (x)
-#define htov32(x) (x)
-#define hton16(x) swap16(x)
-#define hton32(x) swap32(x)
-# endif
-#endif
-#endif
-
-#ifdef FLOAT_SWAPPER
-#define FLOAT_CONVWITH(y) FLOAT_SWAPPER y;
-#define HTONF(x,y) (memcpy(&y,&x,sizeof(float)), \
- y = htonf((FLOAT_SWAPPER)y), \
- memcpy(&x,&y,sizeof(float)), \
- x)
-#define HTOVF(x,y) (memcpy(&y,&x,sizeof(float)), \
- y = htovf((FLOAT_SWAPPER)y), \
- memcpy(&x,&y,sizeof(float)), \
- x)
-#define NTOHF(x,y) (memcpy(&y,&x,sizeof(float)), \
- y = ntohf((FLOAT_SWAPPER)y), \
- memcpy(&x,&y,sizeof(float)), \
- x)
-#define VTOHF(x,y) (memcpy(&y,&x,sizeof(float)), \
- y = vtohf((FLOAT_SWAPPER)y), \
- memcpy(&x,&y,sizeof(float)), \
- x)
-#else
-#define FLOAT_CONVWITH(y)
-#define HTONF(x,y) htonf(x)
-#define HTOVF(x,y) htovf(x)
-#define NTOHF(x,y) ntohf(x)
-#define VTOHF(x,y) vtohf(x)
-#endif
-
-#ifdef DOUBLE_SWAPPER
-#define DOUBLE_CONVWITH(y) DOUBLE_SWAPPER y;
-#define HTOND(x,y) (memcpy(&y,&x,sizeof(double)), \
- y = htond((DOUBLE_SWAPPER)y), \
- memcpy(&x,&y,sizeof(double)), \
- x)
-#define HTOVD(x,y) (memcpy(&y,&x,sizeof(double)), \
- y = htovd((DOUBLE_SWAPPER)y), \
- memcpy(&x,&y,sizeof(double)), \
- x)
-#define NTOHD(x,y) (memcpy(&y,&x,sizeof(double)), \
- y = ntohd((DOUBLE_SWAPPER)y), \
- memcpy(&x,&y,sizeof(double)), \
- x)
-#define VTOHD(x,y) (memcpy(&y,&x,sizeof(double)), \
- y = vtohd((DOUBLE_SWAPPER)y), \
- memcpy(&x,&y,sizeof(double)), \
- x)
-#else
-#define DOUBLE_CONVWITH(y)
-#define HTOND(x,y) htond(x)
-#define HTOVD(x,y) htovd(x)
-#define NTOHD(x,y) ntohd(x)
-#define VTOHD(x,y) vtohd(x)
-#endif
-
-unsigned long rb_big2ulong_pack _((VALUE x));
-
-static unsigned long
-num2i32(x)
- VALUE x;
-{
- x = rb_to_int(x); /* is nil OK? (should not) */
-
- if (FIXNUM_P(x)) return FIX2LONG(x);
- if (TYPE(x) == T_BIGNUM) {
- return rb_big2ulong_pack(x);
- }
- rb_raise(rb_eTypeError, "can't convert %s to `integer'", rb_obj_classname(x));
- return 0; /* not reached */
-}
-
-#if SIZEOF_LONG == SIZE32 || SIZEOF_INT == SIZE32
-# define EXTEND32(x)
-#else
-/* invariant in modulo 1<<31 */
-# define EXTEND32(x) do {if (!natint) {(x) = (I32)(((1<<31)-1-(x))^~(~0<<31))}} while(0)
-#endif
-#if SIZEOF_SHORT == SIZE16
-# define EXTEND16(x)
-#else
-# define EXTEND16(x) do { if (!natint) {(x) = (short)(((1<<15)-1-(x))^~(~0<<15))}} while(0)
-#endif
-
-#ifdef HAVE_LONG_LONG
-# define QUAD_SIZE sizeof(LONG_LONG)
-#else
-# define QUAD_SIZE 8
-#endif
-static char *toofew = "too few arguments";
-
-static void encodes _((VALUE,char*,long,int));
-static void qpencode _((VALUE,VALUE,long));
-
-static int uv_to_utf8 _((char*,unsigned long));
-static unsigned long utf8_to_uv _((char*,long*));
-
-/*
- * call-seq:
- * arr.pack ( aTemplateString ) -> aBinaryString
- *
- * Packs the contents of <i>arr</i> into a binary sequence according to
- * the directives in <i>aTemplateString</i> (see the table below)
- * Directives ``A,'' ``a,'' and ``Z'' may be followed by a count,
- * which gives the width of the resulting field. The remaining
- * directives also may take a count, indicating the number of array
- * elements to convert. If the count is an asterisk
- * (``<code>*</code>''), all remaining array elements will be
- * converted. Any of the directives ``<code>sSiIlL</code>'' may be
- * followed by an underscore (``<code>_</code>'') to use the underlying
- * platform's native size for the specified type; otherwise, they use a
- * platform-independent size. Spaces are ignored in the template
- * string. See also <code>String#unpack</code>.
- *
- * a = [ "a", "b", "c" ]
- * n = [ 65, 66, 67 ]
- * a.pack("A3A3A3") #=> "a b c "
- * a.pack("a3a3a3") #=> "a\000\000b\000\000c\000\000"
- * n.pack("ccc") #=> "ABC"
- *
- * Directives for +pack+.
- *
- * Directive Meaning
- * ---------------------------------------------------------------
- * @ | Moves to absolute position
- * A | ASCII string (space padded, count is width)
- * a | ASCII string (null padded, count is width)
- * B | Bit string (descending bit order)
- * b | Bit string (ascending bit order)
- * C | Unsigned char
- * c | Char
- * D, d | Double-precision float, native format
- * E | Double-precision float, little-endian byte order
- * e | Single-precision float, little-endian byte order
- * F, f | Single-precision float, native format
- * G | Double-precision float, network (big-endian) byte order
- * g | Single-precision float, network (big-endian) byte order
- * H | Hex string (high nibble first)
- * h | Hex string (low nibble first)
- * I | Unsigned integer
- * i | Integer
- * L | Unsigned long
- * l | Long
- * M | Quoted printable, MIME encoding (see RFC2045)
- * m | Base64 encoded string
- * N | Long, network (big-endian) byte order
- * n | Short, network (big-endian) byte-order
- * P | Pointer to a structure (fixed-length string)
- * p | Pointer to a null-terminated string
- * Q, q | 64-bit number
- * S | Unsigned short
- * s | Short
- * U | UTF-8
- * u | UU-encoded string
- * V | Long, little-endian byte order
- * v | Short, little-endian byte order
- * w | BER-compressed integer\fnm
- * X | Back up a byte
- * x | Null byte
- * Z | Same as ``a'', except that null is added with *
- */
-
-static VALUE
-pack_pack(ary, fmt)
- VALUE ary, fmt;
-{
- static char *nul10 = "\0\0\0\0\0\0\0\0\0\0";
- static char *spc10 = " ";
- char *p, *pend;
- VALUE res, from, associates = 0;
- char type;
- long items, len, idx, plen;
- char *ptr;
-#ifdef NATINT_PACK
- int natint; /* native integer */
-#endif
-
- StringValue(fmt);
- p = RSTRING(fmt)->ptr;
- pend = p + RSTRING(fmt)->len;
- res = rb_str_buf_new(0);
-
- items = RARRAY(ary)->len;
- idx = 0;
-
-#define THISFROM RARRAY(ary)->ptr[idx]
-#define NEXTFROM (items-- > 0 ? RARRAY(ary)->ptr[idx++] : (rb_raise(rb_eArgError, toofew),0))
-
- while (p < pend) {
- if (RSTRING(fmt)->ptr + RSTRING(fmt)->len != pend) {
- rb_raise(rb_eRuntimeError, "format string modified");
- }
- type = *p++; /* get data type */
-#ifdef NATINT_PACK
- natint = 0;
-#endif
-
- if (ISSPACE(type)) continue;
- if (type == '#') {
- while ((p < pend) && (*p != '\n')) {
- p++;
- }
- continue;
- }
- if (*p == '_' || *p == '!') {
- const char *natstr = "sSiIlL";
-
- if (strchr(natstr, type)) {
-#ifdef NATINT_PACK
- natint = 1;
-#endif
- p++;
- }
- else {
- rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
- }
- }
- if (*p == '*') { /* set data length */
- len = strchr("@Xxu", type) ? 0 : items;
- p++;
- }
- else if (ISDIGIT(*p)) {
- len = strtoul(p, (char**)&p, 10);
- }
- else {
- len = 1;
- }
-
- switch (type) {
- case 'A': case 'a': case 'Z':
- case 'B': case 'b':
- case 'H': case 'h':
- from = NEXTFROM;
- if (NIL_P(from)) {
- ptr = "";
- plen = 0;
- }
- else {
- StringValue(from);
- ptr = RSTRING(from)->ptr;
- plen = RSTRING(from)->len;
- OBJ_INFECT(res, from);
- }
-
- if (p[-1] == '*')
- len = plen;
-
- switch (type) {
- case 'a': /* arbitrary binary string (null padded) */
- case 'A': /* ASCII string (space padded) */
- case 'Z': /* null terminated ASCII string */
- if (plen >= len) {
- rb_str_buf_cat(res, ptr, len);
- if (p[-1] == '*' && type == 'Z')
- rb_str_buf_cat(res, nul10, 1);
- }
- else {
- rb_str_buf_cat(res, ptr, plen);
- len -= plen;
- while (len >= 10) {
- rb_str_buf_cat(res, (type == 'A')?spc10:nul10, 10);
- len -= 10;
- }
- rb_str_buf_cat(res, (type == 'A')?spc10:nul10, len);
- }
- break;
-
- case 'b': /* bit string (ascending) */
- {
- int byte = 0;
- long i, j = 0;
-
- if (len > plen) {
- j = (len - plen + 1)/2;
- len = plen;
- }
- for (i=0; i++ < len; ptr++) {
- if (*ptr & 1)
- byte |= 128;
- if (i & 7)
- byte >>= 1;
- else {
- char c = byte & 0xff;
- rb_str_buf_cat(res, &c, 1);
- byte = 0;
- }
- }
- if (len & 7) {
- char c;
- byte >>= 7 - (len & 7);
- c = byte & 0xff;
- rb_str_buf_cat(res, &c, 1);
- }
- len = j;
- goto grow;
- }
- break;
-
- case 'B': /* bit string (descending) */
- {
- int byte = 0;
- long i, j = 0;
-
- if (len > plen) {
- j = (len - plen + 1)/2;
- len = plen;
- }
- for (i=0; i++ < len; ptr++) {
- byte |= *ptr & 1;
- if (i & 7)
- byte <<= 1;
- else {
- char c = byte & 0xff;
- rb_str_buf_cat(res, &c, 1);
- byte = 0;
- }
- }
- if (len & 7) {
- char c;
- byte <<= 7 - (len & 7);
- c = byte & 0xff;
- rb_str_buf_cat(res, &c, 1);
- }
- len = j;
- goto grow;
- }
- break;
-
- case 'h': /* hex string (low nibble first) */
- {
- int byte = 0;
- long i, j = 0;
-
- if (len > plen) {
- j = (len - plen + 1)/2;
- len = plen;
- }
- for (i=0; i++ < len; ptr++) {
- if (ISALPHA(*ptr))
- byte |= (((*ptr & 15) + 9) & 15) << 4;
- else
- byte |= (*ptr & 15) << 4;
- if (i & 1)
- byte >>= 4;
- else {
- char c = byte & 0xff;
- rb_str_buf_cat(res, &c, 1);
- byte = 0;
- }
- }
- if (len & 1) {
- char c = byte & 0xff;
- rb_str_buf_cat(res, &c, 1);
- }
- len = j;
- goto grow;
- }
- break;
-
- case 'H': /* hex string (high nibble first) */
- {
- int byte = 0;
- long i, j = 0;
-
- if (len > plen) {
- j = (len - plen + 1)/2;
- len = plen;
- }
- for (i=0; i++ < len; ptr++) {
- if (ISALPHA(*ptr))
- byte |= ((*ptr & 15) + 9) & 15;
- else
- byte |= *ptr & 15;
- if (i & 1)
- byte <<= 4;
- else {
- char c = byte & 0xff;
- rb_str_buf_cat(res, &c, 1);
- byte = 0;
- }
- }
- if (len & 1) {
- char c = byte & 0xff;
- rb_str_buf_cat(res, &c, 1);
- }
- len = j;
- goto grow;
- }
- break;
- }
- break;
-
- case 'c': /* signed char */
- case 'C': /* unsigned char */
- while (len-- > 0) {
- char c;
-
- from = NEXTFROM;
- c = num2i32(from);
- rb_str_buf_cat(res, &c, sizeof(char));
- }
- break;
-
- case 's': /* signed short */
- case 'S': /* unsigned short */
- while (len-- > 0) {
- short s;
-
- from = NEXTFROM;
- s = num2i32(from);
- rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
- }
- break;
-
- case 'i': /* signed int */
- case 'I': /* unsigned int */
- while (len-- > 0) {
- long i;
-
- from = NEXTFROM;
- i = num2i32(from);
- rb_str_buf_cat(res, OFF32(&i), NATINT_LEN(int,4));
- }
- break;
-
- case 'l': /* signed long */
- case 'L': /* unsigned long */
- while (len-- > 0) {
- long l;
-
- from = NEXTFROM;
- l = num2i32(from);
- rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
- }
- break;
-
- case 'q': /* signed quad (64bit) int */
- case 'Q': /* unsigned quad (64bit) int */
- while (len-- > 0) {
- char tmp[QUAD_SIZE];
-
- from = NEXTFROM;
- rb_quad_pack(tmp, from);
- rb_str_buf_cat(res, (char*)&tmp, QUAD_SIZE);
- }
- break;
-
- case 'n': /* unsigned short (network byte-order) */
- while (len-- > 0) {
- unsigned short s;
-
- from = NEXTFROM;
- s = num2i32(from);
- s = NATINT_HTONS(s);
- rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
- }
- break;
-
- case 'N': /* unsigned long (network byte-order) */
- while (len-- > 0) {
- unsigned long l;
-
- from = NEXTFROM;
- l = num2i32(from);
- l = NATINT_HTONL(l);
- rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
- }
- break;
-
- case 'v': /* unsigned short (VAX byte-order) */
- while (len-- > 0) {
- unsigned short s;
-
- from = NEXTFROM;
- s = num2i32(from);
- s = NATINT_HTOVS(s);
- rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
- }
- break;
-
- case 'V': /* unsigned long (VAX byte-order) */
- while (len-- > 0) {
- unsigned long l;
-
- from = NEXTFROM;
- l = num2i32(from);
- l = NATINT_HTOVL(l);
- rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
- }
- break;
-
- case 'f': /* single precision float in native format */
- case 'F': /* ditto */
- while (len-- > 0) {
- float f;
-
- from = NEXTFROM;
- f = RFLOAT(rb_Float(from))->value;
- rb_str_buf_cat(res, (char*)&f, sizeof(float));
- }
- break;
-
- case 'e': /* single precision float in VAX byte-order */
- while (len-- > 0) {
- float f;
- FLOAT_CONVWITH(ftmp);
-
- from = NEXTFROM;
- f = RFLOAT(rb_Float(from))->value;
- f = HTOVF(f,ftmp);
- rb_str_buf_cat(res, (char*)&f, sizeof(float));
- }
- break;
-
- case 'E': /* double precision float in VAX byte-order */
- while (len-- > 0) {
- double d;
- DOUBLE_CONVWITH(dtmp);
-
- from = NEXTFROM;
- d = RFLOAT(rb_Float(from))->value;
- d = HTOVD(d,dtmp);
- rb_str_buf_cat(res, (char*)&d, sizeof(double));
- }
- break;
-
- case 'd': /* double precision float in native format */
- case 'D': /* ditto */
- while (len-- > 0) {
- double d;
-
- from = NEXTFROM;
- d = RFLOAT(rb_Float(from))->value;
- rb_str_buf_cat(res, (char*)&d, sizeof(double));
- }
- break;
-
- case 'g': /* single precision float in network byte-order */
- while (len-- > 0) {
- float f;
- FLOAT_CONVWITH(ftmp);
-
- from = NEXTFROM;
- f = RFLOAT(rb_Float(from))->value;
- f = HTONF(f,ftmp);
- rb_str_buf_cat(res, (char*)&f, sizeof(float));
- }
- break;
-
- case 'G': /* double precision float in network byte-order */
- while (len-- > 0) {
- double d;
- DOUBLE_CONVWITH(dtmp);
-
- from = NEXTFROM;
- d = RFLOAT(rb_Float(from))->value;
- d = HTOND(d,dtmp);
- rb_str_buf_cat(res, (char*)&d, sizeof(double));
- }
- break;
-
- case 'x': /* null byte */
- grow:
- while (len >= 10) {
- rb_str_buf_cat(res, nul10, 10);
- len -= 10;
- }
- rb_str_buf_cat(res, nul10, len);
- break;
-
- case 'X': /* back up byte */
- shrink:
- plen = RSTRING(res)->len;
- if (plen < len)
- rb_raise(rb_eArgError, "X outside of string");
- RSTRING(res)->len = plen - len;
- RSTRING(res)->ptr[plen - len] = '\0';
- break;
-
- case '@': /* null fill to absolute position */
- len -= RSTRING(res)->len;
- if (len > 0) goto grow;
- len = -len;
- if (len > 0) goto shrink;
- break;
-
- case '%':
- rb_raise(rb_eArgError, "%% is not supported");
- break;
-
- case 'U': /* Unicode character */
- while (len-- > 0) {
- long l;
- char buf[8];
- int le;
-
- from = NEXTFROM;
- from = rb_to_int(from);
- l = NUM2INT(from);
- if (l < 0) {
- rb_raise(rb_eRangeError, "pack(U): value out of range");
- }
- le = uv_to_utf8(buf, l);
- rb_str_buf_cat(res, (char*)buf, le);
- }
- break;
-
- case 'u': /* uuencoded string */
- case 'm': /* base64 encoded string */
- from = NEXTFROM;
- StringValue(from);
- ptr = RSTRING(from)->ptr;
- plen = RSTRING(from)->len;
-
- if (len <= 2)
- len = 45;
- else
- len = len / 3 * 3;
- while (plen > 0) {
- long todo;
-
- if (plen > len)
- todo = len;
- else
- todo = plen;
- encodes(res, ptr, todo, type);
- plen -= todo;
- ptr += todo;
- }
- break;
-
- case 'M': /* quoted-printable encoded string */
- from = rb_obj_as_string(NEXTFROM);
- if (len <= 1)
- len = 72;
- qpencode(res, from, len);
- break;
-
- case 'P': /* pointer to packed byte string */
- from = THISFROM;
- if (!NIL_P(from)) {
- StringValue(from);
- if (RSTRING(from)->len < len) {
- rb_raise(rb_eArgError, "too short buffer for P(%ld for %ld)",
- RSTRING(from)->len, len);
- }
- }
- len = 1;
- /* FALL THROUGH */
- case 'p': /* pointer to string */
- while (len-- > 0) {
- char *t;
- from = NEXTFROM;
- if (NIL_P(from)) {
- t = 0;
- }
- else {
- t = StringValuePtr(from);
- }
- if (!associates) {
- associates = rb_ary_new();
- }
- rb_ary_push(associates, from);
- rb_str_buf_cat(res, (char*)&t, sizeof(char*));
- }
- break;
-
- case 'w': /* BER compressed integer */
- while (len-- > 0) {
- unsigned long ul;
- VALUE buf = rb_str_new(0, 0);
- char c, *bufs, *bufe;
-
- from = NEXTFROM;
- if (TYPE(from) == T_BIGNUM) {
- VALUE big128 = rb_uint2big(128);
- while (TYPE(from) == T_BIGNUM) {
- from = rb_big_divmod(from, big128);
- c = NUM2INT(RARRAY(from)->ptr[1]) | 0x80; /* mod */
- rb_str_buf_cat(buf, &c, sizeof(char));
- from = RARRAY(from)->ptr[0]; /* div */
- }
- }
-
- {
- long l = NUM2LONG(from);
- if (l < 0) {
- rb_raise(rb_eArgError, "can't compress negative numbers");
- }
- ul = l;
- }
-
- while (ul) {
- c = ((ul & 0x7f) | 0x80);
- rb_str_buf_cat(buf, &c, sizeof(char));
- ul >>= 7;
- }
-
- if (RSTRING(buf)->len) {
- bufs = RSTRING(buf)->ptr;
- bufe = bufs + RSTRING(buf)->len - 1;
- *bufs &= 0x7f; /* clear continue bit */
- while (bufs < bufe) { /* reverse */
- c = *bufs;
- *bufs++ = *bufe;
- *bufe-- = c;
- }
- rb_str_buf_cat(res, RSTRING(buf)->ptr, RSTRING(buf)->len);
- }
- else {
- c = 0;
- rb_str_buf_cat(res, &c, sizeof(char));
- }
- }
- break;
-
- default:
- break;
- }
- }
-
- if (associates) {
- rb_str_associate(res, associates);
- }
- return res;
-}
-
-static char uu_table[] =
-"`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
-static char b64_table[] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static void
-encodes(str, s, len, type)
- VALUE str;
- char *s;
- long len;
- int type;
-{
- char *buff = ALLOCA_N(char, len * 4 / 3 + 6);
- long i = 0;
- char *trans = type == 'u' ? uu_table : b64_table;
- int padding;
-
- if (type == 'u') {
- buff[i++] = len + ' ';
- padding = '`';
- }
- else {
- padding = '=';
- }
- while (len >= 3) {
- buff[i++] = trans[077 & (*s >> 2)];
- buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
- buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))];
- buff[i++] = trans[077 & s[2]];
- s += 3;
- len -= 3;
- }
- if (len == 2) {
- buff[i++] = trans[077 & (*s >> 2)];
- buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
- buff[i++] = trans[077 & (((s[1] << 2) & 074) | (('\0' >> 6) & 03))];
- buff[i++] = padding;
- }
- else if (len == 1) {
- buff[i++] = trans[077 & (*s >> 2)];
- buff[i++] = trans[077 & (((*s << 4) & 060) | (('\0' >> 4) & 017))];
- buff[i++] = padding;
- buff[i++] = padding;
- }
- buff[i++] = '\n';
- rb_str_buf_cat(str, buff, i);
-}
-
-static char hex_table[] = "0123456789ABCDEF";
-
-static void
-qpencode(str, from, len)
- VALUE str, from;
- long len;
-{
- char buff[1024];
- long i = 0, n = 0, prev = EOF;
- unsigned char *s = (unsigned char*)RSTRING(from)->ptr;
- unsigned char *send = s + RSTRING(from)->len;
-
- while (s < send) {
- if ((*s > 126) ||
- (*s < 32 && *s != '\n' && *s != '\t') ||
- (*s == '=')) {
- buff[i++] = '=';
- buff[i++] = hex_table[*s >> 4];
- buff[i++] = hex_table[*s & 0x0f];
- n += 3;
- prev = EOF;
- }
- else if (*s == '\n') {
- if (prev == ' ' || prev == '\t') {
- buff[i++] = '=';
- buff[i++] = *s;
- }
- buff[i++] = *s;
- n = 0;
- prev = *s;
- }
- else {
- buff[i++] = *s;
- n++;
- prev = *s;
- }
- if (n > len) {
- buff[i++] = '=';
- buff[i++] = '\n';
- n = 0;
- prev = '\n';
- }
- if (i > 1024 - 5) {
- rb_str_buf_cat(str, buff, i);
- i = 0;
- }
- s++;
- }
- if (n > 0) {
- buff[i++] = '=';
- buff[i++] = '\n';
- }
- if (i > 0) {
- rb_str_buf_cat(str, buff, i);
- }
-}
-
-static inline int
-hex2num(c)
- char c;
-{
- switch (c) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- return c - '0';
- case 'a': case 'b': case 'c':
- case 'd': case 'e': case 'f':
- return c - 'a' + 10;
- case 'A': case 'B': case 'C':
- case 'D': case 'E': case 'F':
- return c - 'A' + 10;
- default:
- return -1;
- }
-}
-
-#define PACK_LENGTH_ADJUST_SIZE(sz) do { \
- tmp = 0; \
- if (len > (send-s)/sz) { \
- if (!star) { \
- tmp = len-(send-s)/sz; \
- } \
- len = (send-s)/sz; \
- } \
-} while (0)
-
-#ifdef NATINT_PACK
-#define PACK_LENGTH_ADJUST(type,sz) do { \
- int t__len = NATINT_LEN(type,(sz)); \
- PACK_LENGTH_ADJUST_SIZE(t__len); \
-} while (0)
-#else
-#define PACK_LENGTH_ADJUST(type,sz) \
- PACK_LENGTH_ADJUST_SIZE(sizeof(type))
-#endif
-
-#define PACK_ITEM_ADJUST() while (tmp--) rb_ary_push(ary, Qnil)
-
-static VALUE
-infected_str_new(ptr, len, str)
- const char *ptr;
- long len;
- VALUE str;
-{
- VALUE s = rb_str_new(ptr, len);
-
- OBJ_INFECT(s, str);
- return s;
-}
-
-/*
- * call-seq:
- * str.unpack(format) => anArray
- *
- * Decodes <i>str</i> (which may contain binary data) according to the
- * format string, returning an array of each value extracted. The
- * format string consists of a sequence of single-character directives,
- * summarized in the table at the end of this entry.
- * Each directive may be followed
- * by a number, indicating the number of times to repeat with this
- * directive. An asterisk (``<code>*</code>'') will use up all
- * remaining elements. The directives <code>sSiIlL</code> may each be
- * followed by an underscore (``<code>_</code>'') to use the underlying
- * platform's native size for the specified type; otherwise, it uses a
- * platform-independent consistent size. Spaces are ignored in the
- * format string. See also <code>Array#pack</code>.
- *
- * "abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
- * "abc \0\0".unpack('a3a3') #=> ["abc", " \000\000"]
- * "abc \0abc \0".unpack('Z*Z*') #=> ["abc ", "abc "]
- * "aa".unpack('b8B8') #=> ["10000110", "01100001"]
- * "aaa".unpack('h2H2c') #=> ["16", "61", 97]
- * "\xfe\xff\xfe\xff".unpack('sS') #=> [-2, 65534]
- * "now=20is".unpack('M*') #=> ["now is"]
- * "whole".unpack('xax2aX2aX1aX2a') #=> ["h", "e", "l", "l", "o"]
- *
- * This table summarizes the various formats and the Ruby classes
- * returned by each.
- *
- * Format | Returns | Function
- * -------+---------+-----------------------------------------
- * A | String | with trailing nulls and spaces removed
- * -------+---------+-----------------------------------------
- * a | String | string
- * -------+---------+-----------------------------------------
- * B | String | extract bits from each character (msb first)
- * -------+---------+-----------------------------------------
- * b | String | extract bits from each character (lsb first)
- * -------+---------+-----------------------------------------
- * C | Fixnum | extract a character as an unsigned integer
- * -------+---------+-----------------------------------------
- * c | Fixnum | extract a character as an integer
- * -------+---------+-----------------------------------------
- * d,D | Float | treat sizeof(double) characters as
- * | | a native double
- * -------+---------+-----------------------------------------
- * E | Float | treat sizeof(double) characters as
- * | | a double in little-endian byte order
- * -------+---------+-----------------------------------------
- * e | Float | treat sizeof(float) characters as
- * | | a float in little-endian byte order
- * -------+---------+-----------------------------------------
- * f,F | Float | treat sizeof(float) characters as
- * | | a native float
- * -------+---------+-----------------------------------------
- * G | Float | treat sizeof(double) characters as
- * | | a double in network byte order
- * -------+---------+-----------------------------------------
- * g | Float | treat sizeof(float) characters as a
- * | | float in network byte order
- * -------+---------+-----------------------------------------
- * H | String | extract hex nibbles from each character
- * | | (most significant first)
- * -------+---------+-----------------------------------------
- * h | String | extract hex nibbles from each character
- * | | (least significant first)
- * -------+---------+-----------------------------------------
- * I | Integer | treat sizeof(int) (modified by _)
- * | | successive characters as an unsigned
- * | | native integer
- * -------+---------+-----------------------------------------
- * i | Integer | treat sizeof(int) (modified by _)
- * | | successive characters as a signed
- * | | native integer
- * -------+---------+-----------------------------------------
- * L | Integer | treat four (modified by _) successive
- * | | characters as an unsigned native
- * | | long integer
- * -------+---------+-----------------------------------------
- * l | Integer | treat four (modified by _) successive
- * | | characters as a signed native
- * | | long integer
- * -------+---------+-----------------------------------------
- * M | String | quoted-printable
- * -------+---------+-----------------------------------------
- * m | String | base64-encoded
- * -------+---------+-----------------------------------------
- * N | Integer | treat four characters as an unsigned
- * | | long in network byte order
- * -------+---------+-----------------------------------------
- * n | Fixnum | treat two characters as an unsigned
- * | | short in network byte order
- * -------+---------+-----------------------------------------
- * P | String | treat sizeof(char *) characters as a
- * | | pointer, and return \emph{len} characters
- * | | from the referenced location
- * -------+---------+-----------------------------------------
- * p | String | treat sizeof(char *) characters as a
- * | | pointer to a null-terminated string
- * -------+---------+-----------------------------------------
- * Q | Integer | treat 8 characters as an unsigned
- * | | quad word (64 bits)
- * -------+---------+-----------------------------------------
- * q | Integer | treat 8 characters as a signed
- * | | quad word (64 bits)
- * -------+---------+-----------------------------------------
- * S | Fixnum | treat two (different if _ used)
- * | | successive characters as an unsigned
- * | | short in native byte order
- * -------+---------+-----------------------------------------
- * s | Fixnum | Treat two (different if _ used)
- * | | successive characters as a signed short
- * | | in native byte order
- * -------+---------+-----------------------------------------
- * U | Integer | UTF-8 characters as unsigned integers
- * -------+---------+-----------------------------------------
- * u | String | UU-encoded
- * -------+---------+-----------------------------------------
- * V | Fixnum | treat four characters as an unsigned
- * | | long in little-endian byte order
- * -------+---------+-----------------------------------------
- * v | Fixnum | treat two characters as an unsigned
- * | | short in little-endian byte order
- * -------+---------+-----------------------------------------
- * w | Integer | BER-compressed integer (see Array.pack)
- * -------+---------+-----------------------------------------
- * X | --- | skip backward one character
- * -------+---------+-----------------------------------------
- * x | --- | skip forward one character
- * -------+---------+-----------------------------------------
- * Z | String | with trailing nulls removed
- * | | upto first null with *
- * -------+---------+-----------------------------------------
- * @ | --- | skip to the offset given by the
- * | | length argument
- * -------+---------+-----------------------------------------
- */
-
-static VALUE
-pack_unpack(str, fmt)
- VALUE str, fmt;
-{
- static char *hexdigits = "0123456789abcdef0123456789ABCDEFx";
- char *s, *send;
- char *p, *pend;
- VALUE ary;
- char type;
- long len;
- int tmp, star;
-#ifdef NATINT_PACK
- int natint; /* native integer */
-#endif
-
- StringValue(str);
- StringValue(fmt);
- s = RSTRING(str)->ptr;
- send = s + RSTRING(str)->len;
- p = RSTRING(fmt)->ptr;
- pend = p + RSTRING(fmt)->len;
-
- ary = rb_ary_new();
- while (p < pend) {
- type = *p++;
-#ifdef NATINT_PACK
- natint = 0;
-#endif
-
- if (ISSPACE(type)) continue;
- if (type == '#') {
- while ((p < pend) && (*p != '\n')) {
- p++;
- }
- continue;
- }
- star = 0;
- if (*p == '_' || *p == '!') {
- char *natstr = "sSiIlL";
-
- if (strchr(natstr, type)) {
-#ifdef NATINT_PACK
- natint = 1;
-#endif
- p++;
- }
- else {
- rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
- }
- }
- if (p >= pend)
- len = 1;
- else if (*p == '*') {
- star = 1;
- len = send - s;
- p++;
- }
- else if (ISDIGIT(*p)) {
- len = strtoul(p, (char**)&p, 10);
- }
- else {
- len = (type != '@');
- }
-
- switch (type) {
- case '%':
- rb_raise(rb_eArgError, "%% is not supported");
- break;
-
- case 'A':
- if (len > send - s) len = send - s;
- {
- long end = len;
- char *t = s + len - 1;
-
- while (t >= s) {
- if (*t != ' ' && *t != '\0') break;
- t--; len--;
- }
- rb_ary_push(ary, infected_str_new(s, len, str));
- s += end;
- }
- break;
-
- case 'Z':
- {
- char *t = s;
-
- if (len > send-s) len = send-s;
- while (t < s+len && *t) t++;
- rb_ary_push(ary, infected_str_new(s, t-s, str));
- if (t < send) t++;
- s = star ? t : s+len;
- }
- break;
-
- case 'a':
- if (len > send - s) len = send - s;
- rb_ary_push(ary, infected_str_new(s, len, str));
- s += len;
- break;
-
-
- case 'b':
- {
- VALUE bitstr;
- char *t;
- int bits;
- long i;
-
- if (p[-1] == '*' || len > (send - s) * 8)
- len = (send - s) * 8;
- bits = 0;
- rb_ary_push(ary, bitstr = rb_str_new(0, len));
- t = RSTRING(bitstr)->ptr;
- for (i=0; i<len; i++) {
- if (i & 7) bits >>= 1;
- else bits = *s++;
- *t++ = (bits & 1) ? '1' : '0';
- }
- }
- break;
-
- case 'B':
- {
- VALUE bitstr;
- char *t;
- int bits;
- long i;
-
- if (p[-1] == '*' || len > (send - s) * 8)
- len = (send - s) * 8;
- bits = 0;
- rb_ary_push(ary, bitstr = rb_str_new(0, len));
- t = RSTRING(bitstr)->ptr;
- for (i=0; i<len; i++) {
- if (i & 7) bits <<= 1;
- else bits = *s++;
- *t++ = (bits & 128) ? '1' : '0';
- }
- }
- break;
-
- case 'h':
- {
- VALUE bitstr;
- char *t;
- int bits;
- long i;
-
- if (p[-1] == '*' || len > (send - s) * 2)
- len = (send - s) * 2;
- bits = 0;
- rb_ary_push(ary, bitstr = rb_str_new(0, len));
- t = RSTRING(bitstr)->ptr;
- for (i=0; i<len; i++) {
- if (i & 1)
- bits >>= 4;
- else
- bits = *s++;
- *t++ = hexdigits[bits & 15];
- }
- }
- break;
-
- case 'H':
- {
- VALUE bitstr;
- char *t;
- int bits;
- long i;
-
- if (p[-1] == '*' || len > (send - s) * 2)
- len = (send - s) * 2;
- bits = 0;
- rb_ary_push(ary, bitstr = rb_str_new(0, len));
- t = RSTRING(bitstr)->ptr;
- for (i=0; i<len; i++) {
- if (i & 1)
- bits <<= 4;
- else
- bits = *s++;
- *t++ = hexdigits[(bits >> 4) & 15];
- }
- }
- break;
-
- case 'c':
- PACK_LENGTH_ADJUST(char,sizeof(char));
- while (len-- > 0) {
- int c = *s++;
- if (c > (char)127) c-=256;
- rb_ary_push(ary, INT2FIX(c));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'C':
- PACK_LENGTH_ADJUST(unsigned char,sizeof(unsigned char));
- while (len-- > 0) {
- unsigned char c = *s++;
- rb_ary_push(ary, INT2FIX(c));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 's':
- PACK_LENGTH_ADJUST(short,2);
- while (len-- > 0) {
- short tmp = 0;
- memcpy(OFF16(&tmp), s, NATINT_LEN(short,2));
- EXTEND16(tmp);
- s += NATINT_LEN(short,2);
- rb_ary_push(ary, INT2FIX(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'S':
- PACK_LENGTH_ADJUST(unsigned short,2);
- while (len-- > 0) {
- unsigned short tmp = 0;
- memcpy(OFF16(&tmp), s, NATINT_LEN(unsigned short,2));
- s += NATINT_LEN(unsigned short,2);
- rb_ary_push(ary, INT2FIX(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'i':
- PACK_LENGTH_ADJUST(int,sizeof(int));
- while (len-- > 0) {
- int tmp;
- memcpy(&tmp, s, sizeof(int));
- s += sizeof(int);
- rb_ary_push(ary, INT2NUM(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'I':
- PACK_LENGTH_ADJUST(unsigned int,sizeof(unsigned int));
- while (len-- > 0) {
- unsigned int tmp;
- memcpy(&tmp, s, sizeof(unsigned int));
- s += sizeof(unsigned int);
- rb_ary_push(ary, UINT2NUM(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'l':
- PACK_LENGTH_ADJUST(long,4);
- while (len-- > 0) {
- long tmp = 0;
- memcpy(OFF32(&tmp), s, NATINT_LEN(long,4));
- EXTEND32(tmp);
- s += NATINT_LEN(long,4);
- rb_ary_push(ary, LONG2NUM(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
- case 'L':
- PACK_LENGTH_ADJUST(unsigned long,4);
- while (len-- > 0) {
- unsigned long tmp = 0;
- memcpy(OFF32(&tmp), s, NATINT_LEN(unsigned long,4));
- s += NATINT_LEN(unsigned long,4);
- rb_ary_push(ary, ULONG2NUM(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'q':
- PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE);
- while (len-- > 0) {
- char *tmp = (char*)s;
- s += QUAD_SIZE;
- rb_ary_push(ary, rb_quad_unpack(tmp, 1));
- }
- PACK_ITEM_ADJUST();
- break;
- case 'Q':
- PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE);
- while (len-- > 0) {
- char *tmp = (char*)s;
- s += QUAD_SIZE;
- rb_ary_push(ary, rb_quad_unpack(tmp, 0));
- }
- break;
-
- case 'n':
- PACK_LENGTH_ADJUST(unsigned short,2);
- while (len-- > 0) {
- unsigned short tmp = 0;
- memcpy(OFF16B(&tmp), s, NATINT_LEN(unsigned short,2));
- s += NATINT_LEN(unsigned short,2);
- rb_ary_push(ary, UINT2NUM(ntohs(tmp)));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'N':
- PACK_LENGTH_ADJUST(unsigned long,4);
- while (len-- > 0) {
- unsigned long tmp = 0;
- memcpy(OFF32B(&tmp), s, NATINT_LEN(unsigned long,4));
- s += NATINT_LEN(unsigned long,4);
- rb_ary_push(ary, ULONG2NUM(ntohl(tmp)));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'v':
- PACK_LENGTH_ADJUST(unsigned short,2);
- while (len-- > 0) {
- unsigned short tmp = 0;
- memcpy(OFF16(&tmp), s, NATINT_LEN(unsigned short,2));
- s += NATINT_LEN(unsigned short,2);
- rb_ary_push(ary, UINT2NUM(vtohs(tmp)));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'V':
- PACK_LENGTH_ADJUST(unsigned long,4);
- while (len-- > 0) {
- unsigned long tmp = 0;
- memcpy(OFF32(&tmp), s, NATINT_LEN(long,4));
- s += NATINT_LEN(long,4);
- rb_ary_push(ary, ULONG2NUM(vtohl(tmp)));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'f':
- case 'F':
- PACK_LENGTH_ADJUST(float,sizeof(float));
- while (len-- > 0) {
- float tmp;
- memcpy(&tmp, s, sizeof(float));
- s += sizeof(float);
- rb_ary_push(ary, rb_float_new((double)tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'e':
- PACK_LENGTH_ADJUST(float,sizeof(float));
- while (len-- > 0) {
- float tmp;
- FLOAT_CONVWITH(ftmp);
-
- memcpy(&tmp, s, sizeof(float));
- s += sizeof(float);
- tmp = VTOHF(tmp,ftmp);
- rb_ary_push(ary, rb_float_new((double)tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'E':
- PACK_LENGTH_ADJUST(double,sizeof(double));
- while (len-- > 0) {
- double tmp;
- DOUBLE_CONVWITH(dtmp);
-
- memcpy(&tmp, s, sizeof(double));
- s += sizeof(double);
- tmp = VTOHD(tmp,dtmp);
- rb_ary_push(ary, rb_float_new(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'D':
- case 'd':
- PACK_LENGTH_ADJUST(double,sizeof(double));
- while (len-- > 0) {
- double tmp;
- memcpy(&tmp, s, sizeof(double));
- s += sizeof(double);
- rb_ary_push(ary, rb_float_new(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'g':
- PACK_LENGTH_ADJUST(float,sizeof(float));
- while (len-- > 0) {
- float tmp;
- FLOAT_CONVWITH(ftmp;)
-
- memcpy(&tmp, s, sizeof(float));
- s += sizeof(float);
- tmp = NTOHF(tmp,ftmp);
- rb_ary_push(ary, rb_float_new((double)tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'G':
- PACK_LENGTH_ADJUST(double,sizeof(double));
- while (len-- > 0) {
- double tmp;
- DOUBLE_CONVWITH(dtmp);
-
- memcpy(&tmp, s, sizeof(double));
- s += sizeof(double);
- tmp = NTOHD(tmp,dtmp);
- rb_ary_push(ary, rb_float_new(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'U':
- if (len > send - s) len = send - s;
- while (len > 0 && s < send) {
- long alen = send - s;
- unsigned long l;
-
- l = utf8_to_uv(s, &alen);
- s += alen; len--;
- rb_ary_push(ary, ULONG2NUM(l));
- }
- break;
-
- case 'u':
- {
- VALUE buf = infected_str_new(0, (send - s)*3/4, str);
- char *ptr = RSTRING(buf)->ptr;
- long total = 0;
-
- while (s < send && *s > ' ' && *s < 'a') {
- long a,b,c,d;
- char hunk[4];
-
- hunk[3] = '\0';
- len = (*s++ - ' ') & 077;
- total += len;
- if (total > RSTRING(buf)->len) {
- len -= total - RSTRING(buf)->len;
- total = RSTRING(buf)->len;
- }
-
- while (len > 0) {
- long mlen = len > 3 ? 3 : len;
-
- if (s < send && *s >= ' ')
- a = (*s++ - ' ') & 077;
- else
- a = 0;
- if (s < send && *s >= ' ')
- b = (*s++ - ' ') & 077;
- else
- b = 0;
- if (s < send && *s >= ' ')
- c = (*s++ - ' ') & 077;
- else
- c = 0;
- if (s < send && *s >= ' ')
- d = (*s++ - ' ') & 077;
- else
- d = 0;
- hunk[0] = a << 2 | b >> 4;
- hunk[1] = b << 4 | c >> 2;
- hunk[2] = c << 6 | d;
- memcpy(ptr, hunk, mlen);
- ptr += mlen;
- len -= mlen;
- }
- if (*s == '\r') s++;
- if (*s == '\n') s++;
- else if (s < send && (s+1 == send || s[1] == '\n'))
- s += 2; /* possible checksum byte */
- }
-
- RSTRING(buf)->ptr[total] = '\0';
- RSTRING(buf)->len = total;
- rb_ary_push(ary, buf);
- }
- break;
-
- case 'm':
- {
- VALUE buf = infected_str_new(0, (send - s)*3/4, str);
- char *ptr = RSTRING(buf)->ptr;
- int a = -1,b = -1,c = 0,d;
- static int first = 1;
- static int b64_xtable[256];
-
- if (first) {
- int i;
- first = 0;
-
- for (i = 0; i < 256; i++) {
- b64_xtable[i] = -1;
- }
- for (i = 0; i < 64; i++) {
- b64_xtable[(int)b64_table[i]] = i;
- }
- }
- while (s < send) {
- while (s[0] == '\r' || s[0] == '\n') { s++; }
- if ((a = b64_xtable[(int)s[0]]) == -1) break;
- if ((b = b64_xtable[(int)s[1]]) == -1) break;
- if ((c = b64_xtable[(int)s[2]]) == -1) break;
- if ((d = b64_xtable[(int)s[3]]) == -1) break;
- *ptr++ = a << 2 | b >> 4;
- *ptr++ = b << 4 | c >> 2;
- *ptr++ = c << 6 | d;
- s += 4;
- }
- if (a != -1 && b != -1) {
- if (s + 2 < send && s[2] == '=')
- *ptr++ = a << 2 | b >> 4;
- if (c != -1 && s + 3 < send && s[3] == '=') {
- *ptr++ = a << 2 | b >> 4;
- *ptr++ = b << 4 | c >> 2;
- }
- }
- *ptr = '\0';
- RSTRING(buf)->len = ptr - RSTRING(buf)->ptr;
- rb_ary_push(ary, buf);
- }
- break;
-
- case 'M':
- {
- VALUE buf = infected_str_new(0, send - s, str);
- char *ptr = RSTRING(buf)->ptr;
- int c1, c2;
-
- while (s < send) {
- if (*s == '=') {
- if (++s == send) break;
- if (*s != '\n') {
- if ((c1 = hex2num(*s)) == -1) break;
- if (++s == send) break;
- if ((c2 = hex2num(*s)) == -1) break;
- *ptr++ = c1 << 4 | c2;
- }
- }
- else {
- *ptr++ = *s;
- }
- s++;
- }
- *ptr = '\0';
- RSTRING(buf)->len = ptr - RSTRING(buf)->ptr;
- rb_ary_push(ary, buf);
- }
- break;
-
- case '@':
- if (len > RSTRING(str)->len)
- rb_raise(rb_eArgError, "@ outside of string");
- s = RSTRING(str)->ptr + len;
- break;
-
- case 'X':
- if (len > s - RSTRING(str)->ptr)
- rb_raise(rb_eArgError, "X outside of string");
- s -= len;
- break;
-
- case 'x':
- if (len > send - s)
- rb_raise(rb_eArgError, "x outside of string");
- s += len;
- break;
-
- case 'P':
- if (sizeof(char *) <= send - s) {
- char *t;
- VALUE tmp;
-
- memcpy(&t, s, sizeof(char *));
- s += sizeof(char *);
-
- if (t) {
- VALUE a, *p, *pend;
-
- if (!(a = rb_str_associated(str))) {
- rb_raise(rb_eArgError, "no associated pointer");
- }
- p = RARRAY(a)->ptr;
- pend = p + RARRAY(a)->len;
- while (p < pend) {
- if (TYPE(*p) == T_STRING && RSTRING(*p)->ptr == t) {
- if (len > RSTRING(*p)->len) {
- len = RSTRING(*p)->len;
- }
- break;
- }
- p++;
- }
- if (p == pend) {
- rb_raise(rb_eArgError, "non associated pointer");
- }
- tmp = rb_tainted_str_new(t, len);
- }
- else {
- tmp = Qnil;
- }
- rb_ary_push(ary, tmp);
- }
- break;
-
- case 'p':
- if (len > (send - s) / sizeof(char *))
- len = (send - s) / sizeof(char *);
- while (len-- > 0) {
- if (send - s < sizeof(char *))
- break;
- else {
- VALUE tmp;
- char *t;
-
- memcpy(&t, s, sizeof(char *));
- s += sizeof(char *);
-
- if (t) {
- VALUE a, *p, *pend;
-
- if (!(a = rb_str_associated(str))) {
- rb_raise(rb_eArgError, "no associated pointer");
- }
- p = RARRAY(a)->ptr;
- pend = p + RARRAY(a)->len;
- while (p < pend) {
- if (TYPE(*p) == T_STRING && RSTRING(*p)->ptr == t) {
- break;
- }
- p++;
- }
- if (p == pend) {
- rb_raise(rb_eArgError, "non associated pointer");
- }
- tmp = rb_str_new2(t);
- OBJ_INFECT(tmp, str);
- }
- else {
- tmp = Qnil;
- }
- rb_ary_push(ary, tmp);
- }
- }
- break;
-
- case 'w':
- {
- unsigned long ul = 0;
- unsigned long ulmask = 0xfeL << ((sizeof(unsigned long) - 1) * 8);
-
- while (len > 0 && s < send) {
- ul <<= 7;
- ul |= (*s & 0x7f);
- if (!(*s++ & 0x80)) {
- rb_ary_push(ary, ULONG2NUM(ul));
- len--;
- ul = 0;
- }
- else if (ul & ulmask) {
- VALUE big = rb_uint2big(ul);
- VALUE big128 = rb_uint2big(128);
- while (s < send) {
- big = rb_big_mul(big, big128);
- big = rb_big_plus(big, rb_uint2big(*s & 0x7f));
- if (!(*s++ & 0x80)) {
- rb_ary_push(ary, big);
- len--;
- ul = 0;
- break;
- }
- }
- }
- }
- }
- break;
-
- default:
- break;
- }
- }
-
- return ary;
-}
-
-#define BYTEWIDTH 8
-
-static int
-uv_to_utf8(buf, uv)
- char *buf;
- unsigned long uv;
-{
- if (uv <= 0x7f) {
- buf[0] = (char)uv;
- return 1;
- }
- if (uv <= 0x7ff) {
- buf[0] = ((uv>>6)&0xff)|0xc0;
- buf[1] = (uv&0x3f)|0x80;
- return 2;
- }
- if (uv <= 0xffff) {
- buf[0] = ((uv>>12)&0xff)|0xe0;
- buf[1] = ((uv>>6)&0x3f)|0x80;
- buf[2] = (uv&0x3f)|0x80;
- return 3;
- }
- if (uv <= 0x1fffff) {
- buf[0] = ((uv>>18)&0xff)|0xf0;
- buf[1] = ((uv>>12)&0x3f)|0x80;
- buf[2] = ((uv>>6)&0x3f)|0x80;
- buf[3] = (uv&0x3f)|0x80;
- return 4;
- }
- if (uv <= 0x3ffffff) {
- buf[0] = ((uv>>24)&0xff)|0xf8;
- buf[1] = ((uv>>18)&0x3f)|0x80;
- buf[2] = ((uv>>12)&0x3f)|0x80;
- buf[3] = ((uv>>6)&0x3f)|0x80;
- buf[4] = (uv&0x3f)|0x80;
- return 5;
- }
- if (uv <= 0x7fffffff) {
- buf[0] = ((uv>>30)&0xff)|0xfc;
- buf[1] = ((uv>>24)&0x3f)|0x80;
- buf[2] = ((uv>>18)&0x3f)|0x80;
- buf[3] = ((uv>>12)&0x3f)|0x80;
- buf[4] = ((uv>>6)&0x3f)|0x80;
- buf[5] = (uv&0x3f)|0x80;
- return 6;
- }
- rb_raise(rb_eRangeError, "pack(U): value out of range");
-}
-
-static const long utf8_limits[] = {
- 0x0, /* 1 */
- 0x80, /* 2 */
- 0x800, /* 3 */
- 0x10000, /* 4 */
- 0x200000, /* 5 */
- 0x4000000, /* 6 */
- 0x80000000, /* 7 */
-};
-
-static unsigned long
-utf8_to_uv(p, lenp)
- char *p;
- long *lenp;
-{
- int c = *p++ & 0xff;
- unsigned long uv = c;
- long n;
-
- if (!(uv & 0x80)) {
- *lenp = 1;
- return uv;
- }
- if (!(uv & 0x40)) {
- *lenp = 1;
- rb_raise(rb_eArgError, "malformed UTF-8 character");
- }
-
- if (!(uv & 0x20)) { n = 2; uv &= 0x1f; }
- else if (!(uv & 0x10)) { n = 3; uv &= 0x0f; }
- else if (!(uv & 0x08)) { n = 4; uv &= 0x07; }
- else if (!(uv & 0x04)) { n = 5; uv &= 0x03; }
- else if (!(uv & 0x02)) { n = 6; uv &= 0x01; }
- else {
- *lenp = 1;
- rb_raise(rb_eArgError, "malformed UTF-8 character");
- }
- if (n > *lenp) {
- rb_raise(rb_eArgError, "malformed UTF-8 character (expected %d bytes, given %d bytes)",
- n, *lenp);
- }
- *lenp = n--;
- if (n != 0) {
- while (n--) {
- c = *p++ & 0xff;
- if ((c & 0xc0) != 0x80) {
- *lenp -= n + 1;
- rb_raise(rb_eArgError, "malformed UTF-8 character");
- }
- else {
- c &= 0x3f;
- uv = uv << 6 | c;
- }
- }
- }
- n = *lenp - 1;
- if (uv < utf8_limits[n]) {
- rb_raise(rb_eArgError, "redundant UTF-8 sequence");
- }
- return uv;
-}
-
-void
-Init_pack()
-{
- rb_define_method(rb_cArray, "pack", pack_pack, 1);
- rb_define_method(rb_cString, "unpack", pack_unpack, 1);
-}
-/**********************************************************************
-
- prec.c -
-
- $Author: nobu $
- $Date: 2004/04/14 04:06:25 $
- created at: Tue Jan 26 02:40:41 2000
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-
-VALUE rb_mPrecision;
-
-static ID prc_pr, prc_if;
-
-
-/*
- * call-seq:
- * num.prec(klass) => a_klass
- *
- * Converts _self_ into an instance of _klass_. By default,
- * +prec+ invokes
- *
- * klass.induced_from(num)
- *
- * and returns its value. So, if <code>klass.induced_from</code>
- * doesn't return an instance of _klass_, it will be necessary
- * to reimplement +prec+.
- */
-
-static VALUE
-prec_prec(x, klass)
- VALUE x, klass;
-{
- return rb_funcall(klass, prc_if, 1, x);
-}
-
-/*
- * call-seq:
- * num.prec_i => Integer
- *
- * Returns an +Integer+ converted from _num_. It is equivalent
- * to <code>prec(Integer)</code>.
- */
-
-static VALUE
-prec_prec_i(x)
- VALUE x;
-{
- VALUE klass = rb_cInteger;
-
- return rb_funcall(x, prc_pr, 1, klass);
-}
-
-/*
- * call-seq:
- * num.prec_f => Integer
- *
- * Returns an +Float+ converted from _num_. It is equivalent
- * to <code>prec(Float)</code>.
- */
-
-static VALUE
-prec_prec_f(x)
- VALUE x;
-{
- VALUE klass = rb_cFloat;
-
- return rb_funcall(x, prc_pr, 1, klass);
-}
-
-/*
- * call-seq:
- * Mod.induced_from(number) => a_mod
- *
- * Creates an instance of mod from. This method is overridden
- * by concrete +Numeric+ classes, so that (for example)
- *
- * Fixnum.induced_from(9.9) #=> 9
- *
- * Note that a use of +prec+ in a redefinition may cause
- * an infinite loop.
- */
-
-static VALUE
-prec_induced_from(module, x)
- VALUE module, x;
-{
- rb_raise(rb_eTypeError, "undefined conversion from %s into %s",
- rb_obj_classname(x), rb_class2name(module));
- return Qnil; /* not reached */
-}
-
-/*
- * call_seq:
- * included
- *
- * When the +Precision+ module is mixed-in to a class, this +included+
- * method is used to add our default +induced_from+ implementation
- * to the host class.
- */
-
-static VALUE
-prec_included(module, include)
- VALUE module, include;
-{
- switch (TYPE(include)) {
- case T_CLASS:
- case T_MODULE:
- break;
- default:
- Check_Type(include, T_CLASS);
- break;
- }
- rb_define_singleton_method(include, "induced_from", prec_induced_from, 1);
- return module;
-}
-
-/*
- * Precision is a mixin for concrete numeric classes with
- * precision. Here, `precision' means the fineness of approximation
- * of a real number, so, this module should not be included into
- * anything which is not a subset of Real (so it should not be
- * included in classes such as +Complex+ or +Matrix+).
-*/
-
-void
-Init_Precision()
-{
- rb_mPrecision = rb_define_module("Precision");
- rb_define_singleton_method(rb_mPrecision, "included", prec_included, 1);
- rb_define_method(rb_mPrecision, "prec", prec_prec, 1);
- rb_define_method(rb_mPrecision, "prec_i", prec_prec_i, 0);
- rb_define_method(rb_mPrecision, "prec_f", prec_prec_f, 0);
-
- prc_pr = rb_intern("prec");
- prc_if = rb_intern("induced_from");
-}
-/**********************************************************************
-
- process.c -
-
- $Author: matz $
- $Date: 2005/03/04 06:47:41 $
- created at: Tue Aug 10 14:30:50 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 "rubysig.h"
-#include <stdio.h>
-#include <errno.h>
-#include <signal.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef __DJGPP__
-#include <process.h>
-#endif
-
-#include <time.h>
-#include <ctype.h>
-
-#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#endif
-#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#endif
-
-struct timeval rb_time_interval _((VALUE));
-
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-#ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-#endif
-#include "st.h"
-
-#ifdef __EMX__
-#undef HAVE_GETPGRP
-#endif
-
-#ifdef HAVE_SYS_TIMES_H
-#include <sys/times.h>
-#endif
-
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-
-#if defined(HAVE_TIMES) || defined(_WIN32)
-static VALUE S_Tms;
-#endif
-
-#ifndef WIFEXITED
-#define WIFEXITED(w) (((w) & 0xff) == 0)
-#endif
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f))
-#endif
-#ifndef WIFSTOPPED
-#define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
-#endif
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(w) (((w) >> 8) & 0xff)
-#endif
-#ifndef WTERMSIG
-#define WTERMSIG(w) ((w) & 0x7f)
-#endif
-#ifndef WSTOPSIG
-#define WSTOPSIG WEXITSTATUS
-#endif
-
-#if defined(__APPLE__) && ( defined(__MACH__) || defined(__DARWIN__) ) && !defined(__MacOS_X__)
-#define __MacOS_X__ 1
-#endif
-
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
-#define HAVE_44BSD_SETUID 1
-#define HAVE_44BSD_SETGID 1
-#endif
-
-#ifdef __NetBSD__
-#undef HAVE_SETRUID
-#undef HAVE_SETRGID
-#endif
-
-#if defined(__MacOS_X__) || defined(__bsdi__)
-#define BROKEN_SETREUID 1
-#define BROKEN_SETREGID 1
-#endif
-
-#if defined(HAVE_44BSD_SETUID) || defined(__MacOS_X__)
-#if !defined(USE_SETREUID) && !defined(BROKEN_SETREUID)
-#define OBSOLETE_SETREUID 1
-#endif
-#if !defined(USE_SETREGID) && !defined(BROKEN_SETREGID)
-#define OBSOLETE_SETREGID 1
-#endif
-#endif
-
-#define preserving_errno(stmts) \
- do {int saved_errno = errno; stmts; errno = saved_errno;} while (0)
-
-
-/*
- * call-seq:
- * Process.pid => fixnum
- *
- * Returns the process id of this process. Not available on all
- * platforms.
- *
- * Process.pid #=> 27415
- */
-
-static VALUE
-get_pid()
-{
- rb_secure(2);
- return INT2FIX(getpid());
-}
-
-
-/*
- * call-seq:
- * Process.ppid => fixnum
- *
- * Returns the process id of the parent of this process. Always
- * returns 0 on NT. Not available on all platforms.
- *
- * puts "I am #{Process.pid}"
- * Process.fork { puts "Dad is #{Process.ppid}" }
- *
- * <em>produces:</em>
- *
- * I am 27417
- * Dad is 27417
- */
-
-static VALUE
-get_ppid()
-{
- rb_secure(2);
-#ifdef _WIN32
- return INT2FIX(0);
-#else
- return INT2FIX(getppid());
-#endif
-}
-
-
-/*********************************************************************
- *
- * Document-class: Process::Status
- *
- * <code>Process::Status</code> encapsulates the information on the
- * status of a running or terminated system process. The built-in
- * variable <code>$?</code> is either +nil+ or a
- * <code>Process::Status</code> object.
- *
- * fork { exit 99 } #=> 26557
- * Process.wait #=> 26557
- * $?.class #=> Process::Status
- * $?.to_i #=> 25344
- * $? >> 8 #=> 99
- * $?.stopped? #=> false
- * $?.exited? #=> true
- * $?.exitstatus #=> 99
- *
- * Posix systems record information on processes using a 16-bit
- * integer. The lower bits record the process status (stopped,
- * exited, signaled) and the upper bits possibly contain additional
- * information (for example the program's return code in the case of
- * exited processes). Pre Ruby 1.8, these bits were exposed directly
- * to the Ruby program. Ruby now encapsulates these in a
- * <code>Process::Status</code> object. To maximize compatibility,
- * however, these objects retain a bit-oriented interface. In the
- * descriptions that follow, when we talk about the integer value of
- * _stat_, we're referring to this 16 bit value.
- */
-
-static VALUE rb_cProcStatus;
-VALUE rb_last_status = Qnil;
-
-static void
-last_status_set(status, pid)
- int status, pid;
-{
- rb_last_status = rb_obj_alloc(rb_cProcStatus);
- rb_iv_set(rb_last_status, "status", INT2FIX(status));
- rb_iv_set(rb_last_status, "pid", INT2FIX(pid));
-}
-
-
-/*
- * call-seq:
- * stat.to_i => fixnum
- * stat.to_int => fixnum
- *
- * Returns the bits in _stat_ as a <code>Fixnum</code>. Poking
- * around in these bits is platform dependent.
- *
- * fork { exit 0xab } #=> 26566
- * Process.wait #=> 26566
- * sprintf('%04x', $?.to_i) #=> "ab00"
- */
-
-static VALUE
-pst_to_i(st)
- VALUE st;
-{
- return rb_iv_get(st, "status");
-}
-
-
-/*
- * call-seq:
- * stat.to_s => string
- *
- * Equivalent to _stat_<code>.to_i.to_s</code>.
- */
-
-static VALUE
-pst_to_s(st)
- VALUE st;
-{
- return rb_fix2str(pst_to_i(st), 10);
-}
-
-
-/*
- * call-seq:
- * stat.pid => fixnum
- *
- * Returns the process ID that this status object represents.
- *
- * fork { exit } #=> 26569
- * Process.wait #=> 26569
- * $?.pid #=> 26569
- */
-
-static VALUE
-pst_pid(st)
- VALUE st;
-{
- return rb_iv_get(st, "pid");
-}
-
-
-/*
- * call-seq:
- * stat.inspect => string
- *
- * Override the inspection method.
- */
-
-static VALUE
-pst_inspect(st)
- VALUE st;
-{
- VALUE pid;
- int status;
- VALUE str;
- char buf[256];
-
- pid = pst_pid(st);
- status = NUM2INT(st);
-
- snprintf(buf, sizeof(buf), "#<%s: pid=%ld", rb_class2name(CLASS_OF(st)), NUM2LONG(pid));
- str = rb_str_new2(buf);
- if (WIFSTOPPED(status)) {
- int stopsig = WSTOPSIG(status);
- const char *signame = ruby_signal_name(stopsig);
- if (signame) {
- snprintf(buf, sizeof(buf), ",stopped(SIG%s=%d)", signame, stopsig);
- }
- else {
- snprintf(buf, sizeof(buf), ",stopped(%d)", stopsig);
- }
- rb_str_cat2(str, buf);
- }
- if (WIFSIGNALED(status)) {
- int termsig = WTERMSIG(status);
- const char *signame = ruby_signal_name(termsig);
- if (signame) {
- snprintf(buf, sizeof(buf), ",signaled(SIG%s=%d)", signame, termsig);
- }
- else {
- snprintf(buf, sizeof(buf), ",signaled(%d)", termsig);
- }
- rb_str_cat2(str, buf);
- }
- if (WIFEXITED(status)) {
- snprintf(buf, sizeof(buf), ",exited(%d)", WEXITSTATUS(status));
- rb_str_cat2(str, buf);
- }
-#ifdef WCOREDUMP
- if (WCOREDUMP(status)) {
- rb_str_cat2(str, ",coredumped");
- }
-#endif
- rb_str_cat2(str, ">");
- return str;
-}
-
-
-/*
- * call-seq:
- * stat == other => true or false
- *
- * Returns +true+ if the integer value of _stat_
- * equals <em>other</em>.
- */
-
-static VALUE
-pst_equal(st1, st2)
- VALUE st1, st2;
-{
- if (st1 == st2) return Qtrue;
- return rb_equal(pst_to_i(st1), st2);
-}
-
-
-/*
- * call-seq:
- * stat & num => fixnum
- *
- * Logical AND of the bits in _stat_ with <em>num</em>.
- *
- * fork { exit 0x37 }
- * Process.wait
- * sprintf('%04x', $?.to_i) #=> "3700"
- * sprintf('%04x', $? & 0x1e00) #=> "1600"
- */
-
-static VALUE
-pst_bitand(st1, st2)
- VALUE st1, st2;
-{
- int status = NUM2INT(st1) & NUM2INT(st2);
-
- return INT2NUM(status);
-}
-
-
-/*
- * call-seq:
- * stat >> num => fixnum
- *
- * Shift the bits in _stat_ right <em>num</em> places.
- *
- * fork { exit 99 } #=> 26563
- * Process.wait #=> 26563
- * $?.to_i #=> 25344
- * $? >> 8 #=> 99
- */
-
-static VALUE
-pst_rshift(st1, st2)
- VALUE st1, st2;
-{
- int status = NUM2INT(st1) >> NUM2INT(st2);
-
- return INT2NUM(status);
-}
-
-
-/*
- * call-seq:
- * stat.stopped? => true or false
- *
- * Returns +true+ if this process is stopped. This is only
- * returned if the corresponding <code>wait</code> call had the
- * <code>WUNTRACED</code> flag set.
- */
-
-static VALUE
-pst_wifstopped(st)
- VALUE st;
-{
- int status = NUM2INT(st);
-
- if (WIFSTOPPED(status))
- return Qtrue;
- else
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * stat.stopsig => fixnum or nil
- *
- * Returns the number of the signal that caused _stat_ to stop
- * (or +nil+ if self is not stopped).
- */
-
-static VALUE
-pst_wstopsig(st)
- VALUE st;
-{
- int status = NUM2INT(st);
-
- if (WIFSTOPPED(status))
- return INT2NUM(WSTOPSIG(status));
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * stat.signaled? => true or false
- *
- * Returns +true+ if _stat_ terminated because of
- * an uncaught signal.
- */
-
-static VALUE
-pst_wifsignaled(st)
- VALUE st;
-{
- int status = NUM2INT(st);
-
- if (WIFSIGNALED(status))
- return Qtrue;
- else
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * stat.termsig => fixnum or nil
- *
- * Returns the number of the signal that caused _stat_ to
- * terminate (or +nil+ if self was not terminated by an
- * uncaught signal).
- */
-
-static VALUE
-pst_wtermsig(st)
- VALUE st;
-{
- int status = NUM2INT(st);
-
- if (WIFSIGNALED(status))
- return INT2NUM(WTERMSIG(status));
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * stat.exited? => true or false
- *
- * Returns +true+ if _stat_ exited normally (for
- * example using an <code>exit()</code> call or finishing the
- * program).
- */
-
-static VALUE
-pst_wifexited(st)
- VALUE st;
-{
- int status = NUM2INT(st);
-
- if (WIFEXITED(status))
- return Qtrue;
- else
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * stat.exitstatus => fixnum or nil
- *
- * Returns the least significant eight bits of the return code of
- * _stat_. Only available if <code>exited?</code> is
- * +true+.
- *
- * fork { } #=> 26572
- * Process.wait #=> 26572
- * $?.exited? #=> true
- * $?.exitstatus #=> 0
- *
- * fork { exit 99 } #=> 26573
- * Process.wait #=> 26573
- * $?.exited? #=> true
- * $?.exitstatus #=> 99
- */
-
-static VALUE
-pst_wexitstatus(st)
- VALUE st;
-{
- int status = NUM2INT(st);
-
- if (WIFEXITED(status))
- return INT2NUM(WEXITSTATUS(status));
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * stat.success? => true, false or nil
- *
- * Returns +true+ if _stat_ is successful, +false+ if not.
- * Returns +nil+ if <code>exited?</code> is not +true+.
- */
-
-static VALUE
-pst_success_p(st)
- VALUE st;
-{
- int status = NUM2INT(st);
-
- if (!WIFEXITED(status))
- return Qnil;
- return WEXITSTATUS(status) == EXIT_SUCCESS ? Qtrue : Qfalse;
-}
-
-
-/*
- * call-seq:
- * stat.coredump? => true or false
- *
- * Returns +true+ if _stat_ generated a coredump
- * when it terminated. Not available on all platforms.
- */
-
-static VALUE
-pst_wcoredump(st)
- VALUE st;
-{
-#ifdef WCOREDUMP
- int status = NUM2INT(st);
-
- if (WCOREDUMP(status))
- return Qtrue;
- else
- return Qfalse;
-#else
- return Qfalse;
-#endif
-}
-
-#if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4)
-#define NO_WAITPID
-static st_table *pid_tbl;
-#endif
-
-int
-rb_waitpid(pid, st, flags)
- int pid;
- int *st;
- int flags;
-{
- int result;
-#ifndef NO_WAITPID
- int oflags = flags;
- if (!rb_thread_alone()) { /* there're other threads to run */
- flags |= WNOHANG;
- }
-
- retry:
- TRAP_BEG;
-#ifdef HAVE_WAITPID
- result = waitpid(pid, st, flags);
-#else /* HAVE_WAIT4 */
- result = wait4(pid, st, flags, NULL);
-#endif
- TRAP_END;
- if (result < 0) {
- if (errno == EINTR) {
- rb_thread_polling();
- goto retry;
- }
- return -1;
- }
- if (result == 0) {
- if (oflags & WNOHANG) return 0;
- rb_thread_polling();
- if (rb_thread_alone()) flags = oflags;
- goto retry;
- }
-#else /* NO_WAITPID */
- if (pid_tbl && st_lookup(pid_tbl, pid, (st_data_t *)st)) {
- last_status_set(*st, pid);
- st_delete(pid_tbl, (st_data_t*)&pid, NULL);
- return pid;
- }
-
- if (flags) {
- rb_raise(rb_eArgError, "can't do waitpid with flags");
- }
-
- for (;;) {
- TRAP_BEG;
- result = wait(st);
- TRAP_END;
- if (result < 0) {
- if (errno == EINTR) {
- rb_thread_schedule();
- continue;
- }
- return -1;
- }
- if (result == pid) {
- break;
- }
- if (!pid_tbl)
- pid_tbl = st_init_numtable();
- st_insert(pid_tbl, pid, (st_data_t)st);
- if (!rb_thread_alone()) rb_thread_schedule();
- }
-#endif
- if (result > 0) {
- last_status_set(*st, result);
- }
- return result;
-}
-
-#ifdef NO_WAITPID
-struct wait_data {
- int pid;
- int status;
-};
-
-static int
-wait_each(pid, status, data)
- int pid, status;
- struct wait_data *data;
-{
- if (data->status != -1) return ST_STOP;
-
- data->pid = pid;
- data->status = status;
- return ST_DELETE;
-}
-
-static int
-waitall_each(pid, status, ary)
- int pid, status;
- VALUE ary;
-{
- last_status_set(status, pid);
- rb_ary_push(ary, rb_assoc_new(INT2NUM(pid), rb_last_status));
- return ST_DELETE;
-}
-#endif
-
-
-/* [MG]:FIXME: I wasn't sure how this should be done, since ::wait()
- has historically been documented as if it didn't take any arguments
- despite the fact that it's just an alias for ::waitpid(). The way I
- have it below is more truthful, but a little confusing.
-
- I also took the liberty of putting in the pid values, as they're
- pretty useful, and it looked as if the original 'ri' output was
- supposed to contain them after "[...]depending on the value of
- aPid:".
-
- The 'ansi' and 'bs' formats of the ri output don't display the
- definition list for some reason, but the plain text one does.
- */
-
-/*
- * call-seq:
- * Process.wait() => fixnum
- * Process.wait(pid=-1, flags=0) => fixnum
- * Process.waitpid(pid=-1, flags=0) => fixnum
- *
- * Waits for a child process to exit, returns its process id, and
- * sets <code>$?</code> to a <code>Process::Status</code> object
- * containing information on that process. Which child it waits on
- * depends on the value of _pid_:
- *
- * > 0:: Waits for the child whose process ID equals _pid_.
- *
- * 0:: Waits for any child whose process group ID equals that of the
- * calling process.
- *
- * -1:: Waits for any child process (the default if no _pid_ is
- * given).
- *
- * < -1:: Waits for any child whose process group ID equals the absolute
- * value of _pid_.
- *
- * The _flags_ argument may be a logical or of the flag values
- * <code>Process::WNOHANG</code> (do not block if no child available)
- * or <code>Process::WUNTRACED</code> (return stopped children that
- * haven't been reported). Not all flags are available on all
- * platforms, but a flag value of zero will work on all platforms.
- *
- * Calling this method raises a <code>SystemError</code> if there are
- * no child processes. Not available on all platforms.
- *
- * include Process
- * fork { exit 99 } #=> 27429
- * wait #=> 27429
- * $?.exitstatus #=> 99
- *
- * pid = fork { sleep 3 } #=> 27440
- * Time.now #=> Wed Apr 09 08:57:09 CDT 2003
- * waitpid(pid, Process::WNOHANG) #=> nil
- * Time.now #=> Wed Apr 09 08:57:09 CDT 2003
- * waitpid(pid, 0) #=> 27440
- * Time.now #=> Wed Apr 09 08:57:12 CDT 2003
- */
-
-static VALUE
-proc_wait(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE vpid, vflags;
- int pid, flags, status;
-
- rb_secure(2);
- flags = 0;
- rb_scan_args(argc, argv, "02", &vpid, &vflags);
- if (argc == 0) {
- pid = -1;
- }
- else {
- pid = NUM2INT(vpid);
- if (argc == 2 && !NIL_P(vflags)) {
- flags = NUM2UINT(vflags);
- }
- }
- if ((pid = rb_waitpid(pid, &status, flags)) < 0)
- rb_sys_fail(0);
- if (pid == 0) {
- return rb_last_status = Qnil;
- }
- return INT2FIX(pid);
-}
-
-
-/*
- * call-seq:
- * Process.wait2(pid=-1, flags=0) => [pid, status]
- * Process.waitpid2(pid=-1, flags=0) => [pid, status]
- *
- * Waits for a child process to exit (see Process::waitpid for exact
- * semantics) and returns an array containing the process id and the
- * exit status (a <code>Process::Status</code> object) of that
- * child. Raises a <code>SystemError</code> if there are no child
- * processes.
- *
- * Process.fork { exit 99 } #=> 27437
- * pid, status = Process.wait2
- * pid #=> 27437
- * status.exitstatus #=> 99
- */
-
-static VALUE
-proc_wait2(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE pid = proc_wait(argc, argv);
- if (NIL_P(pid)) return Qnil;
- return rb_assoc_new(pid, rb_last_status);
-}
-
-
-/*
- * call-seq:
- * Process.waitall => [ [pid1,status1], ...]
- *
- * Waits for all children, returning an array of
- * _pid_/_status_ pairs (where _status_ is a
- * <code>Process::Status</code> object).
- *
- * fork { sleep 0.2; exit 2 } #=> 27432
- * fork { sleep 0.1; exit 1 } #=> 27433
- * fork { exit 0 } #=> 27434
- * p Process.waitall
- *
- * <em>produces</em>:
- *
- * [[27434, #<Process::Status: pid=27434,exited(0)>],
- * [27433, #<Process::Status: pid=27433,exited(1)>],
- * [27432, #<Process::Status: pid=27432,exited(2)>]]
- */
-
-static VALUE
-proc_waitall()
-{
- VALUE result;
- int pid, status;
-
- rb_secure(2);
- result = rb_ary_new();
-#ifdef NO_WAITPID
- if (pid_tbl) {
- st_foreach(pid_tbl, waitall_each, result);
- }
-
- for (pid = -1;;) {
- pid = wait(&status);
- if (pid == -1) {
- if (errno == ECHILD)
- break;
- if (errno == EINTR) {
- rb_thread_schedule();
- continue;
- }
- rb_sys_fail(0);
- }
- last_status_set(status, pid);
- rb_ary_push(result, rb_assoc_new(INT2NUM(pid), rb_last_status));
- }
-#else
- rb_last_status = Qnil;
- for (pid = -1;;) {
- pid = rb_waitpid(-1, &status, 0);
- if (pid == -1) {
- if (errno == ECHILD)
- break;
- rb_sys_fail(0);
- }
- rb_ary_push(result, rb_assoc_new(INT2NUM(pid), rb_last_status));
- }
-#endif
- return result;
-}
-
-static VALUE
-detach_process_watcher(pid_p)
- int *pid_p;
-{
- int cpid, status;
-
- for (;;) {
- cpid = rb_waitpid(*pid_p, &status, WNOHANG);
- if (cpid == -1) return rb_last_status;
- rb_thread_sleep(1);
- }
-}
-
-VALUE
-rb_detach_process(pid)
- int pid;
-{
- return rb_thread_create(detach_process_watcher, (void*)&pid);
-}
-
-
-/*
- * call-seq:
- * Process.detach(pid) => thread
- *
- * Some operating systems retain the status of terminated child
- * processes until the parent collects that status (normally using
- * some variant of <code>wait()</code>. If the parent never collects
- * this status, the child stays around as a <em>zombie</em> process.
- * <code>Process::detach</code> prevents this by setting up a
- * separate Ruby thread whose sole job is to reap the status of the
- * process _pid_ when it terminates. Use <code>detach</code>
- * only when you do not intent to explicitly wait for the child to
- * terminate. <code>detach</code> only checks the status
- * periodically (currently once each second).
- *
- * The waiting thread returns the exit status of the detached process
- * when it terminates, so you can use <code>Thread#join</code> to
- * know the result. If specified _pid_ is not a valid child process
- * ID, the thread returns +nil+ immediately.
- *
- * In this first example, we don't reap the first child process, so
- * it appears as a zombie in the process status display.
- *
- * p1 = fork { sleep 0.1 }
- * p2 = fork { sleep 0.2 }
- * Process.waitpid(p2)
- * sleep 2
- * system("ps -ho pid,state -p #{p1}")
- *
- * <em>produces:</em>
- *
- * 27389 Z
- *
- * In the next example, <code>Process::detach</code> is used to reap
- * the child automatically.
- *
- * p1 = fork { sleep 0.1 }
- * p2 = fork { sleep 0.2 }
- * Process.detach(p1)
- * Process.waitpid(p2)
- * sleep 2
- * system("ps -ho pid,state -p #{p1}")
- *
- * <em>(produces no output)</em>
- */
-
-static VALUE
-proc_detach(obj, pid)
- VALUE pid;
-{
- rb_secure(2);
- return rb_detach_process(NUM2INT(pid));
-}
-
-#ifndef HAVE_STRING_H
-char *strtok();
-#endif
-
-#ifdef HAVE_SETITIMER
-#define before_exec() rb_thread_stop_timer()
-#define after_exec() rb_thread_start_timer()
-#else
-#define before_exec()
-#define after_exec()
-#endif
-
-extern char *dln_find_exe();
-
-static void
-security(str)
- const char *str;
-{
- if (rb_env_path_tainted()) {
- if (rb_safe_level() > 0) {
- rb_raise(rb_eSecurityError, "Insecure PATH - %s", str);
- }
- }
-}
-
-static int
-proc_exec_v(argv, prog)
- char **argv;
- const char *prog;
-{
- if (!prog)
- prog = argv[0];
- security(prog);
- prog = dln_find_exe(prog, 0);
- if (!prog) {
- errno = ENOENT;
- return -1;
- }
-
-#if (defined(MSDOS) && !defined(DJGPP)) || defined(__human68k__) || defined(__EMX__) || defined(OS2)
- {
-#if defined(__human68k__)
-#define COMMAND "command.x"
-#endif
-#if defined(__EMX__) || defined(OS2) /* OS/2 emx */
-#define COMMAND "cmd.exe"
-#endif
-#if (defined(MSDOS) && !defined(DJGPP))
-#define COMMAND "command.com"
-#endif
- char *extension;
-
- if ((extension = strrchr(prog, '.')) != NULL && strcasecmp(extension, ".bat") == 0) {
- char **new_argv;
- char *p;
- int n;
-
- for (n = 0; argv[n]; n++)
- /* no-op */;
- new_argv = ALLOCA_N(char*, n + 2);
- for (; n > 0; n--)
- new_argv[n + 1] = argv[n];
- new_argv[1] = strcpy(ALLOCA_N(char, strlen(argv[0]) + 1), argv[0]);
- for (p = new_argv[1]; *p != '\0'; p++)
- if (*p == '/')
- *p = '\\';
- new_argv[0] = COMMAND;
- argv = new_argv;
- prog = dln_find_exe(argv[0], 0);
- if (!prog) {
- errno = ENOENT;
- return -1;
- }
- }
- }
-#endif /* MSDOS or __human68k__ or __EMX__ */
- before_exec();
- execv(prog, argv);
- preserving_errno(after_exec());
- return -1;
-}
-
-int
-rb_proc_exec_n(argc, argv, prog)
- int argc;
- VALUE *argv;
- const char *prog;
-{
- char **args;
- int i;
-
- args = ALLOCA_N(char*, argc+1);
- for (i=0; i<argc; i++) {
- args[i] = RSTRING(argv[i])->ptr;
- }
- args[i] = 0;
- if (args[0]) {
- return proc_exec_v(args, prog);
- }
- return -1;
-}
-
-int
-rb_proc_exec(str)
- const char *str;
-{
- const char *s = str;
- char *ss, *t;
- char **argv, **a;
-
- while (*str && ISSPACE(*str))
- str++;
-
-#ifdef _WIN32
- before_exec();
- rb_w32_spawn(P_OVERLAY, (char *)str, 0);
- after_exec();
-#else
- for (s=str; *s; s++) {
- if (ISSPACE(*s)) {
- const char *p, *nl = NULL;
- for (p = s; ISSPACE(*p); p++) {
- if (*p == '\n') nl = p;
- }
- if (!*p) break;
- if (nl) s = nl;
- }
- if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
- int status;
-#if defined(MSDOS)
- before_exec();
- status = system(str);
- after_exec();
- if (status != -1)
- exit(status);
-#elif defined(__human68k__) || defined(__CYGWIN32__) || defined(__EMX__)
- char *shell = dln_find_exe("sh", 0);
- status = -1;
- before_exec();
- if (shell)
- execl(shell, "sh", "-c", str, (char *) NULL);
- else
- status = system(str);
- after_exec();
- if (status != -1)
- exit(status);
-#else
- before_exec();
- execl("/bin/sh", "sh", "-c", str, (char *)NULL);
- preserving_errno(after_exec());
-#endif
- return -1;
- }
- }
- a = argv = ALLOCA_N(char*, (s-str)/2+2);
- ss = ALLOCA_N(char, s-str+1);
- memcpy(ss, str, s-str);
- ss[s-str] = '\0';
- if (*a++ = strtok(ss, " \t")) {
- while (t = strtok(NULL, " \t")) {
- *a++ = t;
- }
- *a = NULL;
- }
- if (argv[0]) {
- return proc_exec_v(argv, 0);
- }
- errno = ENOENT;
-#endif /* _WIN32 */
- return -1;
-}
-
-#if defined(_WIN32)
-#define HAVE_SPAWNV 1
-#endif
-
-#if !defined(HAVE_FORK) && defined(HAVE_SPAWNV)
-static int
-proc_spawn_v(argv, prog)
- char **argv;
- char *prog;
-{
-#if defined(_WIN32)
- char *cmd = ALLOCA_N(char, rb_w32_argv_size(argv));
- if (!prog) prog = argv[0];
- return rb_w32_spawn(P_NOWAIT, rb_w32_join_argv(cmd, argv), prog);
-#else
- char *extension;
- int status;
-
- if (!prog)
- prog = argv[0];
- security(prog);
- prog = dln_find_exe(prog, 0);
- if (!prog)
- return -1;
-
-#if defined(__human68k__)
- if ((extension = strrchr(prog, '.')) != NULL && strcasecmp(extension, ".bat") == 0) {
- char **new_argv;
- char *p;
- int n;
-
- for (n = 0; argv[n]; n++)
- /* no-op */;
- new_argv = ALLOCA_N(char*, n + 2);
- for (; n > 0; n--)
- new_argv[n + 1] = argv[n];
- new_argv[1] = strcpy(ALLOCA_N(char, strlen(argv[0]) + 1), argv[0]);
- for (p = new_argv[1]; *p != '\0'; p++)
- if (*p == '/')
- *p = '\\';
- new_argv[0] = COMMAND;
- argv = new_argv;
- prog = dln_find_exe(argv[0], 0);
- if (!prog) {
- errno = ENOENT;
- return -1;
- }
- }
-#endif
- before_exec();
- status = spawnv(P_WAIT, prog, argv);
- last_status_set(status == -1 ? 127 : status, 0);
- after_exec();
- return status;
-#endif
-}
-
-static int
-proc_spawn_n(argc, argv, prog)
- int argc;
- VALUE *argv;
- VALUE prog;
-{
- char **args;
- int i;
-
- args = ALLOCA_N(char*, argc + 1);
- for (i = 0; i < argc; i++) {
- args[i] = RSTRING(argv[i])->ptr;
- }
- args[i] = (char*) 0;
- if (args[0])
- return proc_spawn_v(args, prog ? RSTRING(prog)->ptr : 0);
- return -1;
-}
-
-#if defined(_WIN32)
-#define proc_spawn(str) rb_w32_spawn(P_NOWAIT, str, 0)
-#else
-static int
-proc_spawn(str)
- char *str;
-{
- char *s, *t;
- char **argv, **a;
- int status;
-
- for (s = str; *s; s++) {
- if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
- char *shell = dln_find_exe("sh", 0);
- before_exec();
- status = shell?spawnl(P_WAIT,shell,"sh","-c",str,(char*)NULL):system(str);
- last_status_set(status == -1 ? 127 : status, 0);
- after_exec();
- return status;
- }
- }
- a = argv = ALLOCA_N(char*, (s - str) / 2 + 2);
- s = ALLOCA_N(char, s - str + 1);
- strcpy(s, str);
- if (*a++ = strtok(s, " \t")) {
- while (t = strtok(NULL, " \t"))
- *a++ = t;
- *a = NULL;
- }
- return argv[0] ? proc_spawn_v(argv, 0) : -1;
-}
-#endif
-#endif
-
-VALUE
-rb_check_argv(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE tmp, prog;
- int i;
-
- if (argc == 0) {
- rb_raise(rb_eArgError, "wrong number of arguments");
- }
-
- prog = 0;
- tmp = rb_check_array_type(argv[0]);
- if (!NIL_P(tmp)) {
- if (RARRAY(tmp)->len != 2) {
- rb_raise(rb_eArgError, "wrong first argument");
- }
- prog = RARRAY(tmp)->ptr[0];
- argv[0] = RARRAY(tmp)->ptr[1];
- SafeStringValue(prog);
- }
- for (i = 0; i < argc; i++) {
- SafeStringValue(argv[i]);
- }
- security(RSTRING(prog ? prog : argv[0])->ptr);
- return prog;
-}
-
-/*
- * call-seq:
- * exec(command [, arg, ...])
- *
- * Replaces the current process by running the given external _command_.
- * If +exec+ is given a single argument, that argument is
- * taken as a line that is subject to shell expansion before being
- * executed. If multiple arguments are given, the second and subsequent
- * arguments are passed as parameters to _command_ with no shell
- * expansion. If the first argument is a two-element array, the first
- * element is the command to be executed, and the second argument is
- * used as the <code>argv[0]</code> value, which may show up in process
- * listings. In MSDOS environments, the command is executed in a
- * subshell; otherwise, one of the <code>exec(2)</code> system calls is
- * used, so the running command may inherit some of the environment of
- * the original program (including open file descriptors).
- *
- * Raises SystemCallError if the _command_ couldn't execute (typically
- * <code>Errno::ENOENT</code> when it was not found).
- *
- * exec "echo *" # echoes list of files in current directory
- * # never get here
- *
- *
- * exec "echo", "*" # echoes an asterisk
- * # never get here
- */
-
-VALUE
-rb_f_exec(argc, argv)
- int argc;
- VALUE *argv;
-{
- struct rb_exec_arg e;
- VALUE prog;
-
- prog = rb_check_argv(argc, argv);
- if (!prog && argc == 1) {
- e.argc = 0;
- e.argv = 0;
- e.prog = RSTRING(argv[0])->ptr;
- }
- else {
- e.argc = argc;
- e.argv = argv;
- e.prog = prog ? RSTRING(prog)->ptr : 0;
- }
- rb_exec(&e);
- rb_sys_fail(e.prog);
- return Qnil; /* dummy */
-}
-
-int
-rb_exec(e)
- const struct rb_exec_arg *e;
-{
- int argc = e->argc;
- VALUE *argv = e->argv;
- const char *prog = e->prog;
-
- if (argc == 0) {
- rb_proc_exec(prog);
- }
- else {
- rb_proc_exec_n(argc, argv, prog);
- }
-#ifndef FD_CLOEXEC
- preserving_errno({
- fprintf(stderr, "%s:%d: command not found: %s\n",
- ruby_sourcefile, ruby_sourceline, prog);
- });
-#endif
- return -1;
-}
-
-#ifdef HAVE_FORK
-#ifdef FD_CLOEXEC
-#if SIZEOF_INT == SIZEOF_LONG
-#define proc_syswait (VALUE (*)_((VALUE)))rb_syswait
-#else
-static VALUE
-proc_syswait(pid)
- VALUE pid;
-{
- rb_syswait((int)pid);
- return Qnil;
-}
-#endif
-#endif
-
-/*
- * Forks child process, and returns the process ID in the parent
- * process.
- *
- * If +status+ is given, protects from any exceptions and sets the
- * jump status to it.
- *
- * In the child process, just returns 0 if +chfunc+ is +NULL+.
- * Otherwise +chfunc+ will be called with +charg+, and then the child
- * process exits with +EXIT_SUCCESS+ when it returned zero.
- *
- * In the case of the function is called and returns non-zero value,
- * the child process exits with non-+EXIT_SUCCESS+ value (normaly
- * 127). And, on the platforms where +FD_CLOEXEC+ is available,
- * +errno+ is propagated to the parent process, and this function
- * returns -1 in the parent process. On the other platforms, just
- * returns pid.
- *
- * +chfunc+ must not raise any exceptions.
- */
-int
-rb_fork(status, chfunc, charg)
- int *status;
- int (*chfunc) _((void *));
- void *charg;
-{
- int pid, err, state = 0;
-#ifdef FD_CLOEXEC
- int ep[2];
-#endif
-
-#ifndef __VMS
- rb_io_flush(rb_stdout);
- rb_io_flush(rb_stderr);
-#endif
-
-#ifdef FD_CLOEXEC
- if (chfunc) {
- if (pipe(ep)) return -1;
- if (fcntl(ep[1], F_SETFD, FD_CLOEXEC)) {
- preserving_errno((close(ep[0]), close(ep[1])));
- return -1;
- }
- }
-#endif
- while ((pid = fork()) < 0) {
- switch (errno) {
- case EAGAIN:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
-#endif
- if (!status && !chfunc) {
- rb_thread_sleep(1);
- continue;
- }
- else {
- rb_protect((VALUE (*)())rb_thread_sleep, 1, &state);
- if (status) *status = state;
- if (!state) continue;
- }
- default:
-#ifdef FD_CLOEXEC
- if (chfunc) {
- preserving_errno((close(ep[0]), close(ep[1])));
- }
-#endif
- if (state && !status) rb_jump_tag(state);
- return -1;
- }
- }
- if (!pid) {
- if (chfunc) {
-#ifdef FD_CLOEXEC
- close(ep[0]);
-#endif
- if (!(*chfunc)(charg)) _exit(EXIT_SUCCESS);
-#ifdef FD_CLOEXEC
- err = errno;
- write(ep[1], &err, sizeof(err));
-#endif
-#if EXIT_SUCCESS == 127
- _exit(EXIT_FAILURE);
-#else
- _exit(127);
-#endif
- }
- }
-#ifdef FD_CLOEXEC
- else if (chfunc) {
- close(ep[1]);
- if ((state = read(ep[0], &err, sizeof(err))) < 0) {
- err = errno;
- }
- close(ep[0]);
- if (state) {
- if (status) {
- rb_protect(proc_syswait, (VALUE)pid, status);
- }
- else {
- rb_syswait(pid);
- }
- errno = err;
- return -1;
- }
- }
-#endif
- return pid;
-}
-#endif
-
-/*
- * call-seq:
- * Kernel.fork [{ block }] => fixnum or nil
- * Process.fork [{ block }] => fixnum or nil
- *
- * Creates a subprocess. If a block is specified, that block is run
- * in the subprocess, and the subprocess terminates with a status of
- * zero. Otherwise, the +fork+ call returns twice, once in
- * the parent, returning the process ID of the child, and once in
- * the child, returning _nil_. The child process can exit using
- * <code>Kernel.exit!</code> to avoid running any
- * <code>at_exit</code> functions. The parent process should
- * use <code>Process.wait</code> to collect the termination statuses
- * of its children or use <code>Process.detach</code> to register
- * disinterest in their status; otherwise, the operating system
- * may accumulate zombie processes.
- */
-
-static VALUE
-rb_f_fork(obj)
- VALUE obj;
-{
-#ifdef HAVE_FORK
- int pid;
-
- rb_secure(2);
-
- switch (pid = rb_fork(0, 0, 0)) {
- case 0:
-#ifdef linux
- after_exec();
-#endif
- rb_thread_atfork();
- if (rb_block_given_p()) {
- int status;
-
- rb_protect(rb_yield, Qundef, &status);
- ruby_stop(status);
- }
- return Qnil;
-
- case -1:
- rb_sys_fail("fork(2)");
- return Qnil;
-
- default:
- return INT2FIX(pid);
- }
-#else
- rb_notimplement();
-#endif
-}
-
-
-/*
- * call-seq:
- * Process.exit!(fixnum=-1)
- *
- * Exits the process immediately. No exit handlers are
- * run. <em>fixnum</em> is returned to the underlying system as the
- * exit status.
- *
- * Process.exit!(0)
- */
-
-static VALUE
-rb_f_exit_bang(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- 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_FAILURE;
- }
- _exit(istatus);
-
- return Qnil; /* not reached */
-}
-
-#if defined(sun)
-#define signal(a,b) sigset(a,b)
-#endif
-
-void
-rb_syswait(pid)
- int pid;
-{
- static int overriding;
- RETSIGTYPE (*hfunc)_((int)), (*qfunc)_((int)), (*ifunc)_((int));
- int status;
- int i, hooked = Qfalse;
-
- if (!overriding) {
-#ifdef SIGHUP
- hfunc = signal(SIGHUP, SIG_IGN);
-#endif
-#ifdef SIGQUIT
- qfunc = signal(SIGQUIT, SIG_IGN);
-#endif
- ifunc = signal(SIGINT, SIG_IGN);
- overriding = Qtrue;
- hooked = Qtrue;
- }
-
- do {
- i = rb_waitpid(pid, &status, 0);
- } while (i == -1 && errno == EINTR);
-
- if (hooked) {
-#ifdef SIGHUP
- signal(SIGHUP, hfunc);
-#endif
-#ifdef SIGQUIT
- signal(SIGQUIT, qfunc);
-#endif
- signal(SIGINT, ifunc);
- overriding = Qfalse;
- }
-}
-
-int
-rb_spawn(argc, argv)
- int argc;
- VALUE *argv;
-{
- int status;
- VALUE prog;
-#if defined HAVE_FORK
- struct rb_exec_arg earg;
-#endif
-
- prog = rb_check_argv(argc, argv);
-
- if (!prog && argc == 1) {
- --argc;
- prog = *argv++;
- }
-#if defined HAVE_FORK
- earg.argc = argc;
- earg.argv = argv;
- earg.prog = prog ? RSTRING(prog)->ptr : 0;
- status = rb_fork(&status, (int (*)_((void*)))rb_exec, &earg);
- if (prog && argc) argv[0] = prog;
-#elif defined HAVE_SPAWNV
- if (!argc) {
- status = proc_spawn(RSTRING(prog)->ptr);
- }
- else {
- status = proc_spawn_n(argc, argv, prog);
- }
- if (prog && argc) argv[0] = prog;
-#else
- if (prog && argc) argv[0] = prog;
- if (argc) prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
- status = system(StringValuePtr(prog));
-# if defined(__human68k__) || defined(__DJGPP__)
- last_status_set(status == -1 ? 127 : status, 0);
-# else
- last_status_set((status & 0xff) << 8, 0);
-# endif
-#endif
- return status;
-}
-
-/*
- * call-seq:
- * system(cmd [, arg, ...]) => true or false
- *
- * Executes _cmd_ in a subshell, returning +true+ if the command ran
- * successfully, +false+ otherwise. An error status is available in
- * <code>$?</code>. The arguments are processed in the same way as
- * for <code>Kernel::exec</code>, and raises same exceptions as it.
- *
- * system("echo *")
- * system("echo", "*")
- *
- * <em>produces:</em>
- *
- * config.h main.rb
- * *
- */
-
-static VALUE
-rb_f_system(argc, argv)
- int argc;
- VALUE *argv;
-{
- int status;
-
- status = rb_spawn(argc, argv);
- if (status == -1) rb_sys_fail(RSTRING(argv[0])->ptr);
-#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
- rb_syswait(status);
- status = NUM2INT(rb_last_status);
-#endif
- if (status == EXIT_SUCCESS) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * spawn(cmd [, arg, ...]) => pid
- *
- * Similar to <code>Kernel::system</code> except for not waiting for
- * end of _cmd_, but returns its <i>pid</i>.
- */
-
-static VALUE
-rb_f_spawn(argc, argv)
- int argc;
- VALUE *argv;
-{
- int pid;
-
- pid = rb_spawn(argc, argv);
- if (pid == -1) rb_sys_fail(RSTRING(argv[0])->ptr);
-#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
- return INT2NUM(pid);
-#else
- return Qnil;
-#endif
-}
-
-/*
- * call-seq:
- * sleep([duration]) => fixnum
- *
- * Suspends the current thread for _duration_ seconds (which may be
- * any number, including a +Float+ with fractional seconds). Returns the actual
- * number of seconds slept (rounded), which may be less than that asked
- * for if the thread was interrupted by a +SIGALRM+, or if
- * another thread calls <code>Thread#run</code>. Zero arguments
- * causes +sleep+ to sleep forever.
- *
- * Time.new #=> Wed Apr 09 08:56:32 CDT 2003
- * sleep 1.2 #=> 1
- * Time.new #=> Wed Apr 09 08:56:33 CDT 2003
- * sleep 1.9 #=> 2
- * Time.new #=> Wed Apr 09 08:56:35 CDT 2003
- */
-
-static VALUE
-rb_f_sleep(argc, argv)
- int argc;
- VALUE *argv;
-{
- int beg, end;
-
- beg = time(0);
- if (argc == 0) {
- rb_thread_sleep_forever();
- }
- else if (argc == 1) {
- rb_thread_wait_for(rb_time_interval(argv[0]));
- }
- else {
- rb_raise(rb_eArgError, "wrong number of arguments");
- }
-
- end = time(0) - beg;
-
- return INT2FIX(end);
-}
-
-
-/*
- * call-seq:
- * Process.getpgrp => integer
- *
- * Returns the process group ID for this process. Not available on
- * all platforms.
- *
- * Process.getpgid(0) #=> 25527
- * Process.getpgrp #=> 25527
- */
-
-static VALUE
-proc_getpgrp()
-{
- int pgrp;
-
- rb_secure(2);
-#if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
- pgrp = getpgrp();
- if (pgrp < 0) rb_sys_fail(0);
- return INT2FIX(pgrp);
-#else
-# ifdef HAVE_GETPGID
- pgrp = getpgid(0);
- if (pgrp < 0) rb_sys_fail(0);
- return INT2FIX(pgrp);
-# else
- rb_notimplement();
-# endif
-#endif
-}
-
-
-/*
- * call-seq:
- * Process.setpgrp => 0
- *
- * Equivalent to <code>setpgid(0,0)</code>. Not available on all
- * platforms.
- */
-
-static VALUE
-proc_setpgrp()
-{
- rb_secure(2);
- /* check for posix setpgid() first; this matches the posix */
- /* getpgrp() above. It appears that configure will set SETPGRP_VOID */
- /* even though setpgrp(0,0) would be prefered. The posix call avoids */
- /* this confusion. */
-#ifdef HAVE_SETPGID
- if (setpgid(0,0) < 0) rb_sys_fail(0);
-#elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
- if (setpgrp() < 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return INT2FIX(0);
-}
-
-
-/*
- * call-seq:
- * Process.getpgid(pid) => integer
- *
- * Returns the process group ID for the given process id. Not
- * available on all platforms.
- *
- * Process.getpgid(Process.ppid()) #=> 25527
- */
-
-static VALUE
-proc_getpgid(obj, pid)
- VALUE obj, pid;
-{
-#if defined(HAVE_GETPGID) && !defined(__CHECKER__)
- int i;
-
- rb_secure(2);
- i = getpgid(NUM2INT(pid));
- if (i < 0) rb_sys_fail(0);
- return INT2NUM(i);
-#else
- rb_notimplement();
-#endif
-}
-
-
-/*
- * call-seq:
- * Process.setpgid(pid, integer) => 0
- *
- * Sets the process group ID of _pid_ (0 indicates this
- * process) to <em>integer</em>. Not available on all platforms.
- */
-
-static VALUE
-proc_setpgid(obj, pid, pgrp)
- VALUE obj, pid, pgrp;
-{
-#ifdef HAVE_SETPGID
- int ipid, ipgrp;
-
- rb_secure(2);
- ipid = NUM2INT(pid);
- ipgrp = NUM2INT(pgrp);
-
- if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
- return INT2FIX(0);
-#else
- rb_notimplement();
-#endif
-}
-
-
-/*
- * call-seq:
- * Process.setsid => fixnum
- *
- * Establishes this process as a new session and process group
- * leader, with no controlling tty. Returns the session id. Not
- * available on all platforms.
- *
- * Process.setsid #=> 27422
- */
-
-static VALUE
-proc_setsid()
-{
-#if defined(HAVE_SETSID)
- int pid;
-
- rb_secure(2);
- pid = setsid();
- if (pid < 0) rb_sys_fail(0);
- return INT2FIX(pid);
-#elif defined(HAVE_SETPGRP) && defined(TIOCNOTTY)
- pid_t pid;
- int ret;
-
- rb_secure(2);
- pid = getpid();
-#if defined(SETPGRP_VOID)
- ret = setpgrp();
- /* If `pid_t setpgrp(void)' is equivalent to setsid(),
- `ret' will be the same value as `pid', and following open() will fail.
- In Linux, `int setpgrp(void)' is equivalent to setpgid(0, 0). */
-#else
- ret = setpgrp(0, pid);
-#endif
- if (ret == -1) rb_sys_fail(0);
-
- if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
- ioctl(fd, TIOCNOTTY, NULL);
- close(fd);
- }
- return INT2FIX(pid);
-#else
- rb_notimplement();
-#endif
-}
-
-
-/*
- * call-seq:
- * Process.getpriority(kind, integer) => fixnum
- *
- * Gets the scheduling priority for specified process, process group,
- * or user. <em>kind</em> indicates the kind of entity to find: one
- * of <code>Process::PRIO_PGRP</code>,
- * <code>Process::PRIO_USER</code>, or
- * <code>Process::PRIO_PROCESS</code>. _integer_ is an id
- * indicating the particular process, process group, or user (an id
- * of 0 means _current_). Lower priorities are more favorable
- * for scheduling. Not available on all platforms.
- *
- * Process.getpriority(Process::PRIO_USER, 0) #=> 19
- * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
- */
-
-static VALUE
-proc_getpriority(obj, which, who)
- VALUE obj, which, who;
-{
-#ifdef HAVE_GETPRIORITY
- int prio, iwhich, iwho;
-
- rb_secure(2);
- iwhich = NUM2INT(which);
- iwho = NUM2INT(who);
-
- errno = 0;
- prio = getpriority(iwhich, iwho);
- if (errno) rb_sys_fail(0);
- return INT2FIX(prio);
-#else
- rb_notimplement();
-#endif
-}
-
-
-/*
- * call-seq:
- * Process.setpriority(kind, integer, priority) => 0
- *
- * See <code>Process#getpriority</code>.
- *
- * Process.setpriority(Process::PRIO_USER, 0, 19) #=> 0
- * Process.setpriority(Process::PRIO_PROCESS, 0, 19) #=> 0
- * Process.getpriority(Process::PRIO_USER, 0) #=> 19
- * Process.getpriority(Process::PRIO_PROCESS, 0) #=> 19
- */
-
-static VALUE
-proc_setpriority(obj, which, who, prio)
- VALUE obj, which, who, prio;
-{
-#ifdef HAVE_GETPRIORITY
- int iwhich, iwho, iprio;
-
- rb_secure(2);
- iwhich = NUM2INT(which);
- iwho = NUM2INT(who);
- iprio = NUM2INT(prio);
-
- if (setpriority(iwhich, iwho, iprio) < 0)
- rb_sys_fail(0);
- return INT2FIX(0);
-#else
- rb_notimplement();
-#endif
-}
-
-#if SIZEOF_RLIM_T == SIZEOF_INT
-# define RLIM2NUM(v) UINT2NUM(v)
-# define NUM2RLIM(v) NUM2UINT(v)
-#elif SIZEOF_RLIM_T == SIZEOF_LONG
-# define RLIM2NUM(v) ULONG2NUM(v)
-# define NUM2RLIM(v) NUM2ULONG(v)
-#elif SIZEOF_RLIM_T == SIZEOF_LONG_LONG
-# define RLIM2NUM(v) ULL2NUM(v)
-# define NUM2RLIM(v) NUM2ULL(v)
-#endif
-
-/*
- * call-seq:
- * Process.getrlimit(resource) => [cur_limit, max_limit]
- *
- * Gets the resource limit of the process.
- * _cur_limit_ means current (soft) limit and
- * _max_limit_ means maximum (hard) limit.
- *
- * _resource_ indicates the kind of resource to limit:
- * such as <code>Process::RLIMIT_CORE</code>,
- * <code>Process::RLIMIT_CPU</code>, etc.
- * See Process.setrlimit for details.
- *
- * _cur_limit_ and _max_limit_ may be <code>Process::RLIM_INFINITY</code>,
- * <code>Process::RLIM_SAVED_MAX</code> or
- * <code>Process::RLIM_SAVED_CUR</code>.
- * See Process.setrlimit and the system getrlimit(2) manual for details.
- */
-
-static VALUE
-proc_getrlimit(VALUE obj, VALUE resource)
-{
-#if defined(HAVE_GETRLIMIT) && defined(RLIM2NUM)
- struct rlimit rlim;
-
- rb_secure(2);
-
- if (getrlimit(NUM2INT(resource), &rlim) < 0) {
- rb_sys_fail("getrlimit");
- }
- return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
-#else
- rb_notimplement();
-#endif
-}
-
-/*
- * call-seq:
- * Process.setrlimit(resource, cur_limit, max_limit) => nil
- *
- * Sets the resource limit of the process.
- * _cur_limit_ means current (soft) limit and
- * _max_limit_ means maximum (hard) limit.
- *
- * _resource_ indicates the kind of resource to limit.
- * Although the list of resources are OS dependent,
- * SUSv3 defines following resources.
- *
- * [Process::RLIMIT_CORE] core size (bytes)
- * [Process::RLIMIT_CPU] CPU time (seconds)
- * [Process::RLIMIT_DATA] data segment (bytes)
- * [Process::RLIMIT_FSIZE] file size (bytes)
- * [Process::RLIMIT_NOFILE] file descriptors (number)
- * [Process::RLIMIT_STACK] stack size (bytes)
- * [Process::RLIMIT_AS] total available memory (bytes)
- *
- * Other <code>Process::RLIMIT_???</code> constants may be defined.
- *
- * _cur_limit_ and _max_limit_ may be <code>Process::RLIM_INFINITY</code>,
- * which means that the resource is not limited.
- * They may be <code>Process::RLIM_SAVED_MAX</code> or
- * <code>Process::RLIM_SAVED_CUR</code> too.
- * See system setrlimit(2) manual for details.
- *
- */
-
-static VALUE
-proc_setrlimit(VALUE obj, VALUE resource, VALUE rlim_cur, VALUE rlim_max)
-{
-#if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM)
- struct rlimit rlim;
-
- rb_secure(2);
-
- rlim.rlim_cur = NUM2RLIM(rlim_cur);
- rlim.rlim_max = NUM2RLIM(rlim_max);
-
- if (setrlimit(NUM2INT(resource), &rlim) < 0) {
- rb_sys_fail("setrlimit");
- }
- return Qnil;
-#else
- rb_notimplement();
-#endif
-}
-
-static int under_uid_switch = 0;
-static void
-check_uid_switch()
-{
- rb_secure(2);
- if (under_uid_switch) {
- rb_raise(rb_eRuntimeError, "can't handle UID while evaluating block given to Process::UID.switch method");
- }
-}
-
-static int under_gid_switch = 0;
-static void
-check_gid_switch()
-{
- rb_secure(2);
- if (under_gid_switch) {
- rb_raise(rb_eRuntimeError, "can't handle GID while evaluating block given to Process::UID.switch method");
- }
-}
-
-
-/*********************************************************************
- * Document-class: Process::Sys
- *
- * The <code>Process::Sys</code> module contains UID and GID
- * functions which provide direct bindings to the system calls of the
- * same names instead of the more-portable versions of the same
- * functionality found in the <code>Process</code>,
- * <code>Process::UID</code>, and <code>Process::GID</code> modules.
- */
-
-
-/*
- * call-seq:
- * Process::Sys.setuid(integer) => nil
- *
- * Set the user ID of the current process to _integer_. Not
- * available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setuid(obj, id)
- VALUE obj, id;
-{
-#if defined HAVE_SETUID
- check_uid_switch();
- if (setuid(NUM2INT(id)) != 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return Qnil;
-}
-
-
-
-/*
- * call-seq:
- * Process::Sys.setruid(integer) => nil
- *
- * Set the real user ID of the calling process to _integer_.
- * Not available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setruid(obj, id)
- VALUE obj, id;
-{
-#if defined HAVE_SETRUID
- check_uid_switch();
- if (setruid(NUM2INT(id)) != 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * Process::Sys.seteuid(integer) => nil
- *
- * Set the effective user ID of the calling process to
- * _integer_. Not available on all platforms.
- *
- */
-
-static VALUE
-p_sys_seteuid(obj, id)
- VALUE obj, id;
-{
-#if defined HAVE_SETEUID
- check_uid_switch();
- if (seteuid(NUM2INT(id)) != 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * Process::Sys.setreuid(rid, eid) => nil
- *
- * Sets the (integer) real and/or effective user IDs of the current
- * process to _rid_ and _eid_, respectively. A value of
- * <code>-1</code> for either means to leave that ID unchanged. Not
- * available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setreuid(obj, rid, eid)
- VALUE obj, rid, eid;
-{
-#if defined HAVE_SETREUID
- check_uid_switch();
- if (setreuid(NUM2INT(rid),NUM2INT(eid)) != 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * Process::Sys.setresuid(rid, eid, sid) => nil
- *
- * Sets the (integer) real, effective, and saved user IDs of the
- * current process to _rid_, _eid_, and _sid_ respectively. A
- * value of <code>-1</code> for any value means to
- * leave that ID unchanged. Not available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setresuid(obj, rid, eid, sid)
- VALUE obj, rid, eid, sid;
-{
-#if defined HAVE_SETRESUID
- check_uid_switch();
- if (setresuid(NUM2INT(rid),NUM2INT(eid),NUM2INT(sid)) != 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * Process.uid => fixnum
- * Process::UID.rid => fixnum
- * Process::Sys.getuid => fixnum
- *
- * Returns the (real) user ID of this process.
- *
- * Process.uid #=> 501
- */
-
-static VALUE
-proc_getuid(obj)
- VALUE obj;
-{
- int uid = getuid();
- return INT2FIX(uid);
-}
-
-
-/*
- * call-seq:
- * Process.uid= integer => numeric
- *
- * Sets the (integer) user ID for this process. Not available on all
- * platforms.
- */
-
-static VALUE
-proc_setuid(obj, id)
- VALUE obj, id;
-{
- int uid = NUM2INT(id);
-
- check_uid_switch();
-#if defined(HAVE_SETRESUID) && !defined(__CHECKER__)
- if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETREUID
- if (setreuid(uid, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETRUID
- if (setruid(uid) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETUID
- {
- if (geteuid() == uid) {
- if (setuid(uid) < 0) rb_sys_fail(0);
- }
- else {
- rb_notimplement();
- }
- }
-#else
- rb_notimplement();
-#endif
- return INT2FIX(uid);
-}
-
-
-/********************************************************************
- *
- * Document-class: Process::UID
- *
- * The <code>Process::UID</code> module contains a collection of
- * module functions which can be used to portably get, set, and
- * switch the current process's real, effective, and saved user IDs.
- *
- */
-
-static int SAVED_USER_ID;
-
-
-/*
- * call-seq:
- * Process::UID.change_privilege(integer) => fixnum
- *
- * Change the current process's real and effective user ID to that
- * specified by _integer_. Returns the new user ID. Not
- * available on all platforms.
- *
- * [Process.uid, Process.euid] #=> [0, 0]
- * Process::UID.change_privilege(31) #=> 31
- * [Process.uid, Process.euid] #=> [31, 31]
- */
-
-static VALUE
-p_uid_change_privilege(obj, id)
- VALUE obj, id;
-{
- extern int errno;
- int uid;
-
- check_uid_switch();
-
- uid = NUM2INT(id);
-
- if (geteuid() == 0) { /* root-user */
-#if defined(HAVE_SETRESUID)
- if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
-#elif defined(HAVE_SETUID)
- if (setuid(uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
-#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
- if (getuid() == uid) {
- if (SAVED_USER_ID == uid) {
- if (setreuid(-1, uid) < 0) rb_sys_fail(0);
- } else {
- if (uid == 0) { /* (r,e,s) == (root, root, x) */
- if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
- if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
- SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
- if (setreuid(uid, uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- } else {
- if (setreuid(0, -1) < 0) rb_sys_fail(0);
- SAVED_USER_ID = 0;
- if (setreuid(uid, uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- }
- }
- } else {
- if (setreuid(uid, uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- }
-#elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
- if (getuid() == uid) {
- if (SAVED_USER_ID == uid) {
- if (seteuid(uid) < 0) rb_sys_fail(0);
- } else {
- if (uid == 0) {
- if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
- SAVED_USER_ID = 0;
- if (setruid(0) < 0) rb_sys_fail(0);
- } else {
- if (setruid(0) < 0) rb_sys_fail(0);
- SAVED_USER_ID = 0;
- if (seteuid(uid) < 0) rb_sys_fail(0);
- if (setruid(uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- }
- }
- } else {
- if (seteuid(uid) < 0) rb_sys_fail(0);
- if (setruid(uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- }
-#else
- rb_notimplement();
-#endif
- } else { /* unprivileged user */
-#if defined(HAVE_SETRESUID)
- if (setresuid((getuid() == uid)? -1: uid,
- (geteuid() == uid)? -1: uid,
- (SAVED_USER_ID == uid)? -1: uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
-#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
- if (SAVED_USER_ID == uid) {
- if (setreuid((getuid() == uid)? -1: uid,
- (geteuid() == uid)? -1: uid) < 0) rb_sys_fail(0);
- } else if (getuid() != uid) {
- if (setreuid(uid, (geteuid() == uid)? -1: uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- } else if (/* getuid() == uid && */ geteuid() != uid) {
- if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- if (setreuid(uid, -1) < 0) rb_sys_fail(0);
- } else { /* getuid() == uid && geteuid() == uid */
- if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
- if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- if (setreuid(uid, -1) < 0) rb_sys_fail(0);
- }
-#elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
- if (SAVED_USER_ID == uid) {
- if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
- if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
- } else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
- if (getuid() != uid) {
- if (setruid(uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- } else {
- if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- if (setruid(uid) < 0) rb_sys_fail(0);
- }
- } else if (/* geteuid() != uid && */ getuid() == uid) {
- if (seteuid(uid) < 0) rb_sys_fail(0);
- if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- if (setruid(uid) < 0) rb_sys_fail(0);
- } else {
- errno = EPERM;
- rb_sys_fail(0);
- }
-#elif defined HAVE_44BSD_SETUID
- if (getuid() == uid) {
- /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
- if (setuid(uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- } else {
- errno = EPERM;
- rb_sys_fail(0);
- }
-#elif defined HAVE_SETEUID
- if (getuid() == uid && SAVED_USER_ID == uid) {
- if (seteuid(uid) < 0) rb_sys_fail(0);
- } else {
- errno = EPERM;
- rb_sys_fail(0);
- }
-#elif defined HAVE_SETUID
- if (getuid() == uid && SAVED_USER_ID == uid) {
- if (setuid(uid) < 0) rb_sys_fail(0);
- } else {
- errno = EPERM;
- rb_sys_fail(0);
- }
-#else
- rb_notimplement();
-#endif
- }
- return INT2FIX(uid);
-}
-
-
-
-/*
- * call-seq:
- * Process::Sys.setgid(integer) => nil
- *
- * Set the group ID of the current process to _integer_. Not
- * available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setgid(obj, id)
- VALUE obj, id;
-{
-#if defined HAVE_SETGID
- check_gid_switch();
- if (setgid(NUM2INT(id)) != 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * Process::Sys.setrgid(integer) => nil
- *
- * Set the real group ID of the calling process to _integer_.
- * Not available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setrgid(obj, id)
- VALUE obj, id;
-{
-#if defined HAVE_SETRGID
- check_gid_switch();
- if (setrgid(NUM2INT(id)) != 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return Qnil;
-}
-
-
-
-/*
- * call-seq:
- * Process::Sys.setegid(integer) => nil
- *
- * Set the effective group ID of the calling process to
- * _integer_. Not available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setegid(obj, id)
- VALUE obj, id;
-{
-#if defined HAVE_SETEGID
- check_gid_switch();
- if (setegid(NUM2INT(id)) != 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * Process::Sys.setregid(rid, eid) => nil
- *
- * Sets the (integer) real and/or effective group IDs of the current
- * process to <em>rid</em> and <em>eid</em>, respectively. A value of
- * <code>-1</code> for either means to leave that ID unchanged. Not
- * available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setregid(obj, rid, eid)
- VALUE obj, rid, eid;
-{
-#if defined HAVE_SETREGID
- check_gid_switch();
- if (setregid(NUM2INT(rid),NUM2INT(eid)) != 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return Qnil;
-}
-
-/*
- * call-seq:
- * Process::Sys.setresgid(rid, eid, sid) => nil
- *
- * Sets the (integer) real, effective, and saved user IDs of the
- * current process to <em>rid</em>, <em>eid</em>, and <em>sid</em>
- * respectively. A value of <code>-1</code> for any value means to
- * leave that ID unchanged. Not available on all platforms.
- *
- */
-
-static VALUE
-p_sys_setresgid(obj, rid, eid, sid)
- VALUE obj, rid, eid, sid;
-{
-#if defined HAVE_SETRESGID
- check_gid_switch();
- if (setresgid(NUM2INT(rid),NUM2INT(eid),NUM2INT(sid)) != 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * Process::Sys.issetugid => true or false
- *
- * Returns +true+ if the process was created as a result
- * of an execve(2) system call which had either of the setuid or
- * setgid bits set (and extra privileges were given as a result) or
- * if it has changed any of its real, effective or saved user or
- * group IDs since it began execution.
- *
- */
-
-static VALUE
-p_sys_issetugid(obj)
- VALUE obj;
-{
-#if defined HAVE_ISSETUGID
- rb_secure(2);
- if (issetugid()) {
- return Qtrue;
- } else {
- return Qfalse;
- }
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-
-/*
- * call-seq:
- * Process.gid => fixnum
- * Process::GID.rid => fixnum
- * Process::Sys.getgid => fixnum
- *
- * Returns the (real) group ID for this process.
- *
- * Process.gid #=> 500
- */
-
-static VALUE
-proc_getgid(obj)
- VALUE obj;
-{
- int gid = getgid();
- return INT2FIX(gid);
-}
-
-
-/*
- * call-seq:
- * Process.gid= fixnum => fixnum
- *
- * Sets the group ID for this process.
- */
-
-static VALUE
-proc_setgid(obj, id)
- VALUE obj, id;
-{
- int gid = NUM2INT(id);
-
- check_gid_switch();
-#if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
- if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETREGID
- if (setregid(gid, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETRGID
- if (setrgid((GIDTYPE)gid) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETGID
- {
- if (getegid() == gid) {
- if (setgid(gid) < 0) rb_sys_fail(0);
- }
- else {
- rb_notimplement();
- }
- }
-#else
- rb_notimplement();
-#endif
- return INT2FIX(gid);
-}
-
-
-static size_t maxgroups = 32;
-
-
-/*
- * call-seq:
- * Process.groups => array
- *
- * Get an <code>Array</code> of the gids of groups in the
- * supplemental group access list for this process.
- *
- * Process.groups #=> [27, 6, 10, 11]
- *
- */
-
-static VALUE
-proc_getgroups(VALUE obj)
-{
-#ifdef HAVE_GETGROUPS
- VALUE ary;
- size_t ngroups;
- gid_t *groups;
- int i;
-
- groups = ALLOCA_N(gid_t, maxgroups);
-
- ngroups = getgroups(maxgroups, groups);
- if (ngroups == -1)
- rb_sys_fail(0);
-
- ary = rb_ary_new();
- for (i = 0; i < ngroups; i++)
- rb_ary_push(ary, INT2NUM(groups[i]));
-
- return ary;
-#else
- rb_notimplement();
- return Qnil;
-#endif
-}
-
-
-/*
- * call-seq:
- * Process.groups= array => array
- *
- * Set the supplemental group access list to the given
- * <code>Array</code> of group IDs.
- *
- * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
- * Process.groups = [27, 6, 10, 11] #=> [27, 6, 10, 11]
- * Process.groups #=> [27, 6, 10, 11]
- *
- */
-
-static VALUE
-proc_setgroups(VALUE obj, VALUE ary)
-{
-#ifdef HAVE_SETGROUPS
- size_t ngroups;
- gid_t *groups;
- int i;
- struct group *gr;
-
- Check_Type(ary, T_ARRAY);
-
- ngroups = RARRAY(ary)->len;
- if (ngroups > maxgroups)
- rb_raise(rb_eArgError, "too many groups, %d max", maxgroups);
-
- groups = ALLOCA_N(gid_t, ngroups);
-
- for (i = 0; i < ngroups && i < RARRAY(ary)->len; i++) {
- VALUE g = RARRAY(ary)->ptr[i];
-
- if (FIXNUM_P(g)) {
- groups[i] = FIX2INT(g);
- }
- else {
- VALUE tmp = rb_check_string_type(g);
-
- if (NIL_P(tmp)) {
- groups[i] = NUM2INT(g);
- }
- else {
- gr = getgrnam(RSTRING(tmp)->ptr);
- if (gr == NULL)
- rb_raise(rb_eArgError,
- "can't find group for %s", RSTRING(tmp)->ptr);
- groups[i] = gr->gr_gid;
- }
- }
- }
-
- i = setgroups(ngroups, groups);
- if (i == -1)
- rb_sys_fail(0);
-
- return proc_getgroups(obj);
-#else
- rb_notimplement();
- return Qnil;
-#endif
-}
-
-
-/*
- * call-seq:
- * Process.initgroups(username, gid) => array
- *
- * Initializes the supplemental group access list by reading the
- * system group database and using all groups of which the given user
- * is a member. The group with the specified <em>gid</em> is also
- * added to the list. Returns the resulting <code>Array</code> of the
- * gids of all the groups in the supplementary group access list. Not
- * available on all platforms.
- *
- * Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
- * Process.initgroups( "mgranger", 30 ) #=> [30, 6, 10, 11]
- * Process.groups #=> [30, 6, 10, 11]
- *
- */
-
-static VALUE
-proc_initgroups(obj, uname, base_grp)
- VALUE obj, uname, base_grp;
-{
-#ifdef HAVE_INITGROUPS
- if (initgroups(StringValuePtr(uname), (gid_t)NUM2INT(base_grp)) != 0) {
- rb_sys_fail(0);
- }
- return proc_getgroups(obj);
-#else
- rb_notimplement();
- return Qnil;
-#endif
-}
-
-
-/*
- * call-seq:
- * Process.maxgroups => fixnum
- *
- * Returns the maximum number of gids allowed in the supplemental
- * group access list.
- *
- * Process.maxgroups #=> 32
- */
-
-static VALUE
-proc_getmaxgroups(obj)
- VALUE obj;
-{
- return INT2FIX(maxgroups);
-}
-
-
-/*
- * call-seq:
- * Process.maxgroups= fixnum => fixnum
- *
- * Sets the maximum number of gids allowed in the supplemental group
- * access list.
- */
-
-static VALUE
-proc_setmaxgroups(obj, val)
- VALUE obj;
-{
- size_t ngroups = FIX2INT(val);
-
- if (ngroups > 4096)
- ngroups = 4096;
-
- maxgroups = ngroups;
-
- return INT2FIX(maxgroups);
-}
-
-/*
- * call-seq:
- * Process.daemon() => fixnum
- * Process.daemon(nochdir=nil,noclose=nil) => fixnum
- *
- * Detach the process from controlling terminal and run in
- * the background as system daemon. Unless the argument
- * nochdir is true (i.e. non false), it changes the current
- * working directory to the root ("/"). Unless the argument
- * noclose is true, daemon() will redirect standard input,
- * standard output and standard error to /dev/null.
- */
-
-static VALUE
-proc_daemon(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE nochdir, noclose;
- int n;
-
- rb_scan_args(argc, argv, "02", &nochdir, &noclose);
-
-#if defined(HAVE_DAEMON)
- n = daemon(RTEST(nochdir), RTEST(noclose));
- if (n < 0) rb_sys_fail("daemon");
- return INT2FIX(n);
-#elif defined(HAVE_FORK)
- switch (rb_fork(0, 0, 0)) {
- case -1:
- return (-1);
- case 0:
- break;
- default:
- _exit(0);
- }
-
- proc_setsid();
-
- if (!RTEST(nochdir))
- (void)chdir("/");
-
- if (!RTEST(noclose) && (n = open("/dev/null", O_RDWR, 0)) != -1) {
- (void)dup2(n, 0);
- (void)dup2(n, 1);
- (void)dup2(n, 2);
- if (n > 2)
- (void)close (n);
- }
- return INT2FIX(0);
-#else
- rb_notimplement();
-#endif
-}
-
-/********************************************************************
- *
- * Document-class: Process::GID
- *
- * The <code>Process::GID</code> module contains a collection of
- * module functions which can be used to portably get, set, and
- * switch the current process's real, effective, and saved group IDs.
- *
- */
-
-static int SAVED_GROUP_ID;
-
-
-/*
- * call-seq:
- * Process::GID.change_privilege(integer) => fixnum
- *
- * Change the current process's real and effective group ID to that
- * specified by _integer_. Returns the new group ID. Not
- * available on all platforms.
- *
- * [Process.gid, Process.egid] #=> [0, 0]
- * Process::GID.change_privilege(33) #=> 33
- * [Process.gid, Process.egid] #=> [33, 33]
- */
-
-static VALUE
-p_gid_change_privilege(obj, id)
- VALUE obj, id;
-{
- extern int errno;
- int gid;
-
- check_gid_switch();
-
- gid = NUM2INT(id);
-
- if (geteuid() == 0) { /* root-user */
-#if defined(HAVE_SETRESGID)
- if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
-#elif defined HAVE_SETGID
- if (setgid(gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
-#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
- if (getgid() == gid) {
- if (SAVED_GROUP_ID == gid) {
- if (setregid(-1, gid) < 0) rb_sys_fail(0);
- } else {
- if (gid == 0) { /* (r,e,s) == (root, y, x) */
- if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
- if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
- if (setregid(gid, gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- } else { /* (r,e,s) == (z, y, x) */
- if (setregid(0, 0) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = 0;
- if (setregid(gid, gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- }
- }
- } else {
- if (setregid(gid, gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- }
-#elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
- if (getgid() == gid) {
- if (SAVED_GROUP_ID == gid) {
- if (setegid(gid) < 0) rb_sys_fail(0);
- } else {
- if (gid == 0) {
- if (setegid(gid) < 0) rb_sys_fail(0);
- if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = 0;
- if (setrgid(0) < 0) rb_sys_fail(0);
- } else {
- if (setrgid(0) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = 0;
- if (setegid(gid) < 0) rb_sys_fail(0);
- if (setrgid(gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- }
- }
- } else {
- if (setegid(gid) < 0) rb_sys_fail(0);
- if (setrgid(gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- }
-#else
- rb_notimplement();
-#endif
- } else { /* unprivileged user */
-#if defined(HAVE_SETRESGID)
- if (setresgid((getgid() == gid)? -1: gid,
- (getegid() == gid)? -1: gid,
- (SAVED_GROUP_ID == gid)? -1: gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
-#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
- if (SAVED_GROUP_ID == gid) {
- if (setregid((getgid() == gid)? -1: gid,
- (getegid() == gid)? -1: gid) < 0) rb_sys_fail(0);
- } else if (getgid() != gid) {
- if (setregid(gid, (getegid() == gid)? -1: gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- } else if (/* getgid() == gid && */ getegid() != gid) {
- if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- if (setregid(gid, -1) < 0) rb_sys_fail(0);
- } else { /* getgid() == gid && getegid() == gid */
- if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
- if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- if (setregid(gid, -1) < 0) rb_sys_fail(0);
- }
-#elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
- if (SAVED_GROUP_ID == gid) {
- if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
- if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
- } else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
- if (getgid() != gid) {
- if (setrgid(gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- } else {
- if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- if (setrgid(gid) < 0) rb_sys_fail(0);
- }
- } else if (/* getegid() != gid && */ getgid() == gid) {
- if (setegid(gid) < 0) rb_sys_fail(0);
- if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- if (setrgid(gid) < 0) rb_sys_fail(0);
- } else {
- errno = EPERM;
- rb_sys_fail(0);
- }
-#elif defined HAVE_44BSD_SETGID
- if (getgid() == gid) {
- /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
- if (setgid(gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- } else {
- errno = EPERM;
- rb_sys_fail(0);
- }
-#elif defined HAVE_SETEGID
- if (getgid() == gid && SAVED_GROUP_ID == gid) {
- if (setegid(gid) < 0) rb_sys_fail(0);
- } else {
- errno = EPERM;
- rb_sys_fail(0);
- }
-#elif defined HAVE_SETGID
- if (getgid() == gid && SAVED_GROUP_ID == gid) {
- if (setgid(gid) < 0) rb_sys_fail(0);
- } else {
- errno = EPERM;
- rb_sys_fail(0);
- }
-#else
- rb_notimplement();
-#endif
- }
- return INT2FIX(gid);
-}
-
-
-/*
- * call-seq:
- * Process.euid => fixnum
- * Process::UID.eid => fixnum
- * Process::Sys.geteuid => fixnum
- *
- * Returns the effective user ID for this process.
- *
- * Process.euid #=> 501
- */
-
-static VALUE
-proc_geteuid(obj)
- VALUE obj;
-{
- int euid = geteuid();
- return INT2FIX(euid);
-}
-
-
-/*
- * call-seq:
- * Process.euid= integer
- *
- * Sets the effective user ID for this process. Not available on all
- * platforms.
- */
-
-static VALUE
-proc_seteuid(obj, euid)
- VALUE obj, euid;
-{
- check_uid_switch();
-#if defined(HAVE_SETRESUID) && !defined(__CHECKER__)
- if (setresuid(-1, NUM2INT(euid), -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETREUID
- if (setreuid(-1, NUM2INT(euid)) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETEUID
- if (seteuid(NUM2INT(euid)) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETUID
- euid = NUM2INT(euid);
- if (euid == getuid()) {
- if (setuid(euid) < 0) rb_sys_fail(0);
- }
- else {
- rb_notimplement();
- }
-#else
- rb_notimplement();
-#endif
- return euid;
-}
-
-static VALUE
-rb_seteuid_core(euid)
- int euid;
-{
- int uid;
-
- check_uid_switch();
-
- uid = getuid();
-
-#if defined(HAVE_SETRESUID) && !defined(__CHECKER__)
- if (uid != euid) {
- if (setresuid(-1,euid,euid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = euid;
- } else {
- if (setresuid(-1,euid,-1) < 0) rb_sys_fail(0);
- }
-#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
- if (setreuid(-1, euid) < 0) rb_sys_fail(0);
- if (uid != euid) {
- if (setreuid(euid,uid) < 0) rb_sys_fail(0);
- if (setreuid(uid,euid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = euid;
- }
-#elif defined HAVE_SETEUID
- if (seteuid(euid) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETUID
- if (geteuid() == 0) rb_sys_fail(0);
- if (setuid(euid) < 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return INT2FIX(euid);
-}
-
-
-/*
- * call-seq:
- * Process::UID.grant_privilege(integer) => fixnum
- * Process::UID.eid= integer => fixnum
- *
- * Set the effective user ID, and if possible, the saved user ID of
- * the process to the given _integer_. Returns the new
- * effective user ID. Not available on all platforms.
- *
- * [Process.uid, Process.euid] #=> [0, 0]
- * Process::UID.grant_privilege(31) #=> 31
- * [Process.uid, Process.euid] #=> [0, 31]
- */
-
-static VALUE
-p_uid_grant_privilege(obj, id)
- VALUE obj, id;
-{
- return rb_seteuid_core(NUM2INT(id));
-}
-
-
-/*
- * call-seq:
- * Process.egid => fixnum
- * Process::GID.eid => fixnum
- * Process::Sys.geteid => fixnum
- *
- * Returns the effective group ID for this process. Not available on
- * all platforms.
- *
- * Process.egid #=> 500
- */
-
-static VALUE
-proc_getegid(obj)
- VALUE obj;
-{
- int egid = getegid();
-
- return INT2FIX(egid);
-}
-
-
-/*
- * call-seq:
- * Process.egid = fixnum => fixnum
- *
- * Sets the effective group ID for this process. Not available on all
- * platforms.
- */
-
-static VALUE
-proc_setegid(obj, egid)
- VALUE obj, egid;
-{
- check_gid_switch();
-
-#if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
- if (setresgid(-1, NUM2INT(egid), -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETREGID
- if (setregid(-1, NUM2INT(egid)) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETEGID
- if (setegid(NUM2INT(egid)) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETGID
- egid = NUM2INT(egid);
- if (egid == getgid()) {
- if (setgid(egid) < 0) rb_sys_fail(0);
- }
- else {
- rb_notimplement();
- }
-#else
- rb_notimplement();
-#endif
- return egid;
-}
-
-static VALUE
-rb_setegid_core(egid)
- int egid;
-{
- int gid;
-
- check_gid_switch();
-
- gid = getgid();
-
-#if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
- if (gid != egid) {
- if (setresgid(-1,egid,egid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = egid;
- } else {
- if (setresgid(-1,egid,-1) < 0) rb_sys_fail(0);
- }
-#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
- if (setregid(-1, egid) < 0) rb_sys_fail(0);
- if (gid != egid) {
- if (setregid(egid,gid) < 0) rb_sys_fail(0);
- if (setregid(gid,egid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = egid;
- }
-#elif defined HAVE_SETEGID
- if (setegid(egid) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETGID
- if (geteuid() == 0 /* root user */) rb_sys_fail(0);
- if (setgid(egid) < 0) rb_sys_fail(0);
-#else
- rb_notimplement();
-#endif
- return INT2FIX(egid);
-}
-
-
-/*
- * call-seq:
- * Process::GID.grant_privilege(integer) => fixnum
- * Process::GID.eid = integer => fixnum
- *
- * Set the effective group ID, and if possible, the saved group ID of
- * the process to the given _integer_. Returns the new
- * effective group ID. Not available on all platforms.
- *
- * [Process.gid, Process.egid] #=> [0, 0]
- * Process::GID.grant_privilege(31) #=> 33
- * [Process.gid, Process.egid] #=> [0, 33]
- */
-
-static VALUE
-p_gid_grant_privilege(obj, id)
- VALUE obj, id;
-{
- return rb_setegid_core(NUM2INT(id));
-}
-
-
-/*
- * call-seq:
- * Process::UID.re_exchangeable? => true or false
- *
- * Returns +true+ if the real and effective user IDs of a
- * process may be exchanged on the current platform.
- *
- */
-
-static VALUE
-p_uid_exchangeable()
-{
-#if defined(HAVE_SETRESUID) && !defined(__CHECKER__)
- return Qtrue;
-#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
- return Qtrue;
-#else
- return Qfalse;
-#endif
-}
-
-
-/*
- * call-seq:
- * Process::UID.re_exchange => fixnum
- *
- * Exchange real and effective user IDs and return the new effective
- * user ID. Not available on all platforms.
- *
- * [Process.uid, Process.euid] #=> [0, 31]
- * Process::UID.re_exchange #=> 0
- * [Process.uid, Process.euid] #=> [31, 0]
- */
-
-static VALUE
-p_uid_exchange(obj)
- VALUE obj;
-{
- int uid, euid;
-
- check_uid_switch();
-
- uid = getuid();
- euid = geteuid();
-
-#if defined(HAVE_SETRESUID) && !defined(__CHECKER__)
- if (setresuid(euid, uid, uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
-#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
- if (setreuid(euid,uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
-#else
- rb_notimplement();
-#endif
- return INT2FIX(uid);
-}
-
-
-/*
- * call-seq:
- * Process::GID.re_exchangeable? => true or false
- *
- * Returns +true+ if the real and effective group IDs of a
- * process may be exchanged on the current platform.
- *
- */
-
-static VALUE
-p_gid_exchangeable()
-{
-#if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
- return Qtrue;
-#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
- return Qtrue;
-#else
- return Qfalse;
-#endif
-}
-
-
-/*
- * call-seq:
- * Process::GID.re_exchange => fixnum
- *
- * Exchange real and effective group IDs and return the new effective
- * group ID. Not available on all platforms.
- *
- * [Process.gid, Process.egid] #=> [0, 33]
- * Process::GID.re_exchange #=> 0
- * [Process.gid, Process.egid] #=> [33, 0]
- */
-
-static VALUE
-p_gid_exchange(obj)
- VALUE obj;
-{
- int gid, egid;
-
- check_gid_switch();
-
- gid = getgid();
- egid = getegid();
-
-#if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
- if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
-#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
- if (setregid(egid,gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
-#else
- rb_notimplement();
-#endif
- return INT2FIX(gid);
-}
-
-/* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
-
-/*
- * call-seq:
- * Process::UID.sid_available? => true or false
- *
- * Returns +true+ if the current platform has saved user
- * ID functionality.
- *
- */
-
-static VALUE
-p_uid_have_saved_id()
-{
-#if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
- return Qtrue;
-#else
- return Qfalse;
-#endif
-}
-
-
-#if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
-static VALUE
-p_uid_sw_ensure(id)
- int id;
-{
- under_uid_switch = 0;
- return rb_seteuid_core(id);
-}
-
-
-/*
- * call-seq:
- * Process::UID.switch => fixnum
- * Process::UID.switch {|| block} => object
- *
- * Switch the effective and real user IDs of the current process. If
- * a <em>block</em> is given, the user IDs will be switched back
- * after the block is executed. Returns the new effective user ID if
- * called without a block, and the return value of the block if one
- * is given.
- *
- */
-
-static VALUE
-p_uid_switch(obj)
- VALUE obj;
-{
- extern int errno;
- int uid, euid;
-
- check_uid_switch();
-
- uid = getuid();
- euid = geteuid();
-
- if (uid != euid) {
- proc_seteuid(obj, INT2FIX(uid));
- if (rb_block_given_p()) {
- under_uid_switch = 1;
- return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
- } else {
- return INT2FIX(euid);
- }
- } else if (euid != SAVED_USER_ID) {
- proc_seteuid(obj, INT2FIX(SAVED_USER_ID));
- if (rb_block_given_p()) {
- under_uid_switch = 1;
- return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
- } else {
- return INT2FIX(uid);
- }
- } else {
- errno = EPERM;
- rb_sys_fail(0);
- }
-
-#else
-static VALUE
-p_uid_sw_ensure(obj)
- VALUE obj;
-{
- under_uid_switch = 0;
- return p_uid_exchange(obj);
-}
-
-static VALUE
-p_uid_switch(obj)
- VALUE obj;
-{
- extern int errno;
- int uid, euid;
-
- check_uid_switch();
-
- uid = getuid();
- euid = geteuid();
-
- if (uid == euid) {
- errno = EPERM;
- rb_sys_fail(0);
- }
- p_uid_exchange(obj);
- if (rb_block_given_p()) {
- under_uid_switch = 1;
- return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, obj);
- } else {
- return INT2FIX(euid);
- }
-#endif
-}
-
-
-/* [MG] :FIXME: Is this correct? I'm not sure how to phrase this. */
-
-/*
- * call-seq:
- * Process::GID.sid_available? => true or false
- *
- * Returns +true+ if the current platform has saved group
- * ID functionality.
- *
- */
-
-static VALUE
-p_gid_have_saved_id()
-{
-#if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
- return Qtrue;
-#else
- return Qfalse;
-#endif
-}
-
-#if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
-static VALUE
-p_gid_sw_ensure(id)
- int id;
-{
- under_gid_switch = 0;
- return rb_setegid_core(id);
-}
-
-
-/*
- * call-seq:
- * Process::GID.switch => fixnum
- * Process::GID.switch {|| block} => object
- *
- * Switch the effective and real group IDs of the current process. If
- * a <em>block</em> is given, the group IDs will be switched back
- * after the block is executed. Returns the new effective group ID if
- * called without a block, and the return value of the block if one
- * is given.
- *
- */
-
-static VALUE
-p_gid_switch(obj)
- VALUE obj;
-{
- extern int errno;
- int gid, egid;
-
- check_gid_switch();
-
- gid = getgid();
- egid = getegid();
-
- if (gid != egid) {
- proc_setegid(obj, INT2FIX(gid));
- if (rb_block_given_p()) {
- under_gid_switch = 1;
- return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
- } else {
- return INT2FIX(egid);
- }
- } else if (egid != SAVED_GROUP_ID) {
- proc_setegid(obj, INT2FIX(SAVED_GROUP_ID));
- if (rb_block_given_p()) {
- under_gid_switch = 1;
- return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
- } else {
- return INT2FIX(gid);
- }
- } else {
- errno = EPERM;
- rb_sys_fail(0);
- }
-#else
-static VALUE
-p_gid_sw_ensure(obj)
- VALUE obj;
-{
- under_gid_switch = 0;
- return p_gid_exchange(obj);
-}
-
-static VALUE
-p_gid_switch(obj)
- VALUE obj;
-{
- extern int errno;
- int gid, egid;
-
- check_gid_switch();
-
- gid = getgid();
- egid = getegid();
-
- if (gid == egid) {
- errno = EPERM;
- rb_sys_fail(0);
- }
- p_gid_exchange(obj);
- if (rb_block_given_p()) {
- under_gid_switch = 1;
- return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj);
- } else {
- return INT2FIX(egid);
- }
-#endif
-}
-
-
-/*
- * call-seq:
- * Process.times => aStructTms
- *
- * Returns a <code>Tms</code> structure (see <code>Struct::Tms</code>
- * on page 388) that contains user and system CPU times for this
- * process.
- *
- * t = Process.times
- * [ t.utime, t.stime ] #=> [0.0, 0.02]
- */
-
-VALUE
-rb_proc_times(obj)
- VALUE obj;
-{
-#if defined(HAVE_TIMES) && !defined(__CHECKER__)
-#ifndef HZ
-# ifdef CLK_TCK
-# define HZ CLK_TCK
-# else
-# define HZ 60
-# endif
-#endif /* HZ */
- struct tms buf;
- volatile VALUE utime, stime, cutime, sctime;
-
- times(&buf);
- return rb_struct_new(S_Tms,
- utime = rb_float_new((double)buf.tms_utime / HZ),
- stime = rb_float_new((double)buf.tms_stime / HZ),
- cutime = rb_float_new((double)buf.tms_cutime / HZ),
- sctime = rb_float_new((double)buf.tms_cstime / HZ));
-#else
- rb_notimplement();
-#endif
-}
-
-VALUE rb_mProcess;
-VALUE rb_mProcUID;
-VALUE rb_mProcGID;
-VALUE rb_mProcID_Syscall;
-
-
-/*
- * The <code>Process</code> module is a collection of methods used to
- * manipulate processes.
- */
-
-void
-Init_process()
-{
- rb_define_virtual_variable("$$", get_pid, 0);
- rb_define_readonly_variable("$?", &rb_last_status);
- rb_define_global_function("exec", rb_f_exec, -1);
- rb_define_global_function("fork", rb_f_fork, 0);
- rb_define_global_function("exit!", rb_f_exit_bang, -1);
- rb_define_global_function("system", rb_f_system, -1);
- rb_define_global_function("spawn", rb_f_spawn, -1);
- rb_define_global_function("sleep", rb_f_sleep, -1);
-
- rb_mProcess = rb_define_module("Process");
-
-#if !defined(_WIN32) && !defined(DJGPP)
-#ifdef WNOHANG
- rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(WNOHANG));
-#else
- rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(0));
-#endif
-#ifdef WUNTRACED
- rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(WUNTRACED));
-#else
- rb_define_const(rb_mProcess, "WUNTRACED", INT2FIX(0));
-#endif
-#endif
-
- rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
- rb_define_singleton_method(rb_mProcess, "spawn", rb_f_spawn, -1);
- rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, -1);
- rb_define_singleton_method(rb_mProcess, "exit", rb_f_exit, -1); /* in eval.c */
- rb_define_singleton_method(rb_mProcess, "abort", rb_f_abort, -1); /* in eval.c */
-
- rb_define_module_function(rb_mProcess, "kill", rb_f_kill, -1); /* in signal.c */
- rb_define_module_function(rb_mProcess, "wait", proc_wait, -1);
- rb_define_module_function(rb_mProcess, "wait2", proc_wait2, -1);
- rb_define_module_function(rb_mProcess, "waitpid", proc_wait, -1);
- rb_define_module_function(rb_mProcess, "waitpid2", proc_wait2, -1);
- rb_define_module_function(rb_mProcess, "waitall", proc_waitall, 0);
- rb_define_module_function(rb_mProcess, "detach", proc_detach, 1);
-
- rb_cProcStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
- rb_undef_method(CLASS_OF(rb_cProcStatus), "new");
-
- rb_define_method(rb_cProcStatus, "==", pst_equal, 1);
- rb_define_method(rb_cProcStatus, "&", pst_bitand, 1);
- rb_define_method(rb_cProcStatus, ">>", pst_rshift, 1);
- rb_define_method(rb_cProcStatus, "to_i", pst_to_i, 0);
- rb_define_method(rb_cProcStatus, "to_int", pst_to_i, 0);
- rb_define_method(rb_cProcStatus, "to_s", pst_to_s, 0);
- rb_define_method(rb_cProcStatus, "inspect", pst_inspect, 0);
-
- rb_define_method(rb_cProcStatus, "pid", pst_pid, 0);
-
- rb_define_method(rb_cProcStatus, "stopped?", pst_wifstopped, 0);
- rb_define_method(rb_cProcStatus, "stopsig", pst_wstopsig, 0);
- rb_define_method(rb_cProcStatus, "signaled?", pst_wifsignaled, 0);
- rb_define_method(rb_cProcStatus, "termsig", pst_wtermsig, 0);
- rb_define_method(rb_cProcStatus, "exited?", pst_wifexited, 0);
- rb_define_method(rb_cProcStatus, "exitstatus", pst_wexitstatus, 0);
- rb_define_method(rb_cProcStatus, "success?", pst_success_p, 0);
- rb_define_method(rb_cProcStatus, "coredump?", pst_wcoredump, 0);
-
- rb_define_module_function(rb_mProcess, "pid", get_pid, 0);
- rb_define_module_function(rb_mProcess, "ppid", get_ppid, 0);
-
- rb_define_module_function(rb_mProcess, "getpgrp", proc_getpgrp, 0);
- rb_define_module_function(rb_mProcess, "setpgrp", proc_setpgrp, 0);
- rb_define_module_function(rb_mProcess, "getpgid", proc_getpgid, 1);
- rb_define_module_function(rb_mProcess, "setpgid", proc_setpgid, 2);
-
- rb_define_module_function(rb_mProcess, "setsid", proc_setsid, 0);
-
- rb_define_module_function(rb_mProcess, "getpriority", proc_getpriority, 2);
- rb_define_module_function(rb_mProcess, "setpriority", proc_setpriority, 3);
-
-#ifdef HAVE_GETPRIORITY
- rb_define_const(rb_mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
- rb_define_const(rb_mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
- rb_define_const(rb_mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
-#endif
-
-#ifdef HAVE_GETRLIMIT
- rb_define_module_function(rb_mProcess, "getrlimit", proc_getrlimit, 1);
-#endif
-#ifdef HAVE_SETRLIMIT
- rb_define_module_function(rb_mProcess, "setrlimit", proc_setrlimit, 3);
-#endif
-#ifdef RLIM2NUM
-#ifdef RLIM_INFINITY
- rb_define_const(rb_mProcess, "RLIM_INFINITY", RLIM2NUM(RLIM_INFINITY));
-#endif
-#ifdef RLIM_SAVED_MAX
- rb_define_const(rb_mProcess, "RLIM_SAVED_MAX", RLIM2NUM(RLIM_SAVED_MAX));
-#endif
-#ifdef RLIM_SAVED_CUR
- rb_define_const(rb_mProcess, "RLIM_SAVED_CUR", RLIM2NUM(RLIM_SAVED_CUR));
-#endif
-#ifdef RLIMIT_CORE
- rb_define_const(rb_mProcess, "RLIMIT_CORE", INT2FIX(RLIMIT_CORE));
-#endif
-#ifdef RLIMIT_CPU
- rb_define_const(rb_mProcess, "RLIMIT_CPU", INT2FIX(RLIMIT_CPU));
-#endif
-#ifdef RLIMIT_DATA
- rb_define_const(rb_mProcess, "RLIMIT_DATA", INT2FIX(RLIMIT_DATA));
-#endif
-#ifdef RLIMIT_FSIZE
- rb_define_const(rb_mProcess, "RLIMIT_FSIZE", INT2FIX(RLIMIT_FSIZE));
-#endif
-#ifdef RLIMIT_NOFILE
- rb_define_const(rb_mProcess, "RLIMIT_NOFILE", INT2FIX(RLIMIT_NOFILE));
-#endif
-#ifdef RLIMIT_STACK
- rb_define_const(rb_mProcess, "RLIMIT_STACK", INT2FIX(RLIMIT_STACK));
-#endif
-#ifdef RLIMIT_AS
- rb_define_const(rb_mProcess, "RLIMIT_AS", INT2FIX(RLIMIT_AS));
-#endif
-#ifdef RLIMIT_MEMLOCK
- rb_define_const(rb_mProcess, "RLIMIT_MEMLOCK", INT2FIX(RLIMIT_MEMLOCK));
-#endif
-#ifdef RLIMIT_NPROC
- rb_define_const(rb_mProcess, "RLIMIT_NPROC", INT2FIX(RLIMIT_NPROC));
-#endif
-#ifdef RLIMIT_RSS
- rb_define_const(rb_mProcess, "RLIMIT_RSS", INT2FIX(RLIMIT_RSS));
-#endif
-#ifdef RLIMIT_SBSIZE
- rb_define_const(rb_mProcess, "RLIMIT_SBSIZE", INT2FIX(RLIMIT_SBSIZE));
-#endif
-#endif
-
- rb_define_module_function(rb_mProcess, "uid", proc_getuid, 0);
- rb_define_module_function(rb_mProcess, "uid=", proc_setuid, 1);
- rb_define_module_function(rb_mProcess, "gid", proc_getgid, 0);
- rb_define_module_function(rb_mProcess, "gid=", proc_setgid, 1);
- rb_define_module_function(rb_mProcess, "euid", proc_geteuid, 0);
- rb_define_module_function(rb_mProcess, "euid=", proc_seteuid, 1);
- rb_define_module_function(rb_mProcess, "egid", proc_getegid, 0);
- rb_define_module_function(rb_mProcess, "egid=", proc_setegid, 1);
- rb_define_module_function(rb_mProcess, "initgroups", proc_initgroups, 2);
- rb_define_module_function(rb_mProcess, "groups", proc_getgroups, 0);
- rb_define_module_function(rb_mProcess, "groups=", proc_setgroups, 1);
- rb_define_module_function(rb_mProcess, "maxgroups", proc_getmaxgroups, 0);
- rb_define_module_function(rb_mProcess, "maxgroups=", proc_setmaxgroups, 1);
-
- rb_define_module_function(rb_mProcess, "daemon", proc_daemon, -1);
-
- rb_define_module_function(rb_mProcess, "times", rb_proc_times, 0);
-
-#if defined(HAVE_TIMES) || defined(_WIN32)
- S_Tms = rb_struct_define("Tms", "utime", "stime", "cutime", "cstime", NULL);
-#endif
-
- SAVED_USER_ID = geteuid();
- SAVED_GROUP_ID = getegid();
-
- rb_mProcUID = rb_define_module_under(rb_mProcess, "UID");
- rb_mProcGID = rb_define_module_under(rb_mProcess, "GID");
-
- rb_define_module_function(rb_mProcUID, "rid", proc_getuid, 0);
- rb_define_module_function(rb_mProcGID, "rid", proc_getgid, 0);
- rb_define_module_function(rb_mProcUID, "eid", proc_geteuid, 0);
- rb_define_module_function(rb_mProcGID, "eid", proc_getegid, 0);
- rb_define_module_function(rb_mProcUID, "change_privilege", p_uid_change_privilege, 1);
- rb_define_module_function(rb_mProcGID, "change_privilege", p_gid_change_privilege, 1);
- rb_define_module_function(rb_mProcUID, "grant_privilege", p_uid_grant_privilege, 1);
- rb_define_module_function(rb_mProcGID, "grant_privilege", p_gid_grant_privilege, 1);
- rb_define_alias(rb_mProcUID, "eid=", "grant_privilege");
- rb_define_alias(rb_mProcGID, "eid=", "grant_privilege");
- rb_define_module_function(rb_mProcUID, "re_exchange", p_uid_exchange, 0);
- rb_define_module_function(rb_mProcGID, "re_exchange", p_gid_exchange, 0);
- rb_define_module_function(rb_mProcUID, "re_exchangeable?", p_uid_exchangeable, 0);
- rb_define_module_function(rb_mProcGID, "re_exchangeable?", p_gid_exchangeable, 0);
- rb_define_module_function(rb_mProcUID, "sid_available?", p_uid_have_saved_id, 0);
- rb_define_module_function(rb_mProcGID, "sid_available?", p_gid_have_saved_id, 0);
- rb_define_module_function(rb_mProcUID, "switch", p_uid_switch, 0);
- rb_define_module_function(rb_mProcGID, "switch", p_gid_switch, 0);
-
- rb_mProcID_Syscall = rb_define_module_under(rb_mProcess, "Sys");
-
- rb_define_module_function(rb_mProcID_Syscall, "getuid", proc_getuid, 0);
- rb_define_module_function(rb_mProcID_Syscall, "geteuid", proc_geteuid, 0);
- rb_define_module_function(rb_mProcID_Syscall, "getgid", proc_getgid, 0);
- rb_define_module_function(rb_mProcID_Syscall, "getegid", proc_getegid, 0);
-
- rb_define_module_function(rb_mProcID_Syscall, "setuid", p_sys_setuid, 1);
- rb_define_module_function(rb_mProcID_Syscall, "setgid", p_sys_setgid, 1);
-
- rb_define_module_function(rb_mProcID_Syscall, "setruid", p_sys_setruid, 1);
- rb_define_module_function(rb_mProcID_Syscall, "setrgid", p_sys_setrgid, 1);
-
- rb_define_module_function(rb_mProcID_Syscall, "seteuid", p_sys_seteuid, 1);
- rb_define_module_function(rb_mProcID_Syscall, "setegid", p_sys_setegid, 1);
-
- rb_define_module_function(rb_mProcID_Syscall, "setreuid", p_sys_setreuid, 2);
- rb_define_module_function(rb_mProcID_Syscall, "setregid", p_sys_setregid, 2);
-
- rb_define_module_function(rb_mProcID_Syscall, "setresuid", p_sys_setresuid, 3);
- rb_define_module_function(rb_mProcID_Syscall, "setresgid", p_sys_setresgid, 3);
- rb_define_module_function(rb_mProcID_Syscall, "issetugid", p_sys_issetugid, 0);
-}
-/**********************************************************************
-
- random.c -
-
- $Author: nobu $
- $Date: 2005/02/12 06:07:34 $
- created at: Fri Dec 24 16:39:21 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-/*
-This is based on trimmed version of MT19937. To get the original version,
-contact <http://www.math.keio.ac.jp/~matumoto/emt.html>.
-
-The original copyright notice follows.
-
- A C-program for MT19937, with initialization improved 2002/2/10.
- Coded by Takuji Nishimura and Makoto Matsumoto.
- This is a faster version by taking Shawn Cokus's optimization,
- Matthe Bellew's simplification, Isaku Wada's real version.
-
- Before using, initialize the state by using init_genrand(seed)
- or init_by_array(init_key, key_length).
-
- Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
- 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.
-
- 3. The names of its contributors may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
-
-
- Any feedback is very welcome.
- http://www.math.keio.ac.jp/matumoto/emt.html
- email: matumoto@math.keio.ac.jp
-*/
-
-/* Period parameters */
-#define N 624
-#define M 397
-#define MATRIX_A 0x9908b0dfUL /* constant vector a */
-#define UMASK 0x80000000UL /* most significant w-r bits */
-#define LMASK 0x7fffffffUL /* least significant r bits */
-#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
-#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
-
-static unsigned long state[N]; /* the array for the state vector */
-static int left = 1;
-static int initf = 0;
-static unsigned long *next;
-
-/* initializes state[N] with a seed */
-static void
-init_genrand(s)
- unsigned long s;
-{
- int j;
- state[0]= s & 0xffffffffUL;
- for (j=1; j<N; j++) {
- state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);
- /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
- /* In the previous versions, MSBs of the seed affect */
- /* only MSBs of the array state[]. */
- /* 2002/01/09 modified by Makoto Matsumoto */
- state[j] &= 0xffffffffUL; /* for >32 bit machines */
- }
- left = 1; initf = 1;
-}
-
-/* initialize by an array with array-length */
-/* init_key is the array for initializing keys */
-/* key_length is its length */
-/* slight change for C++, 2004/2/26 */
-static void
-init_by_array(unsigned long init_key[], int key_length)
-{
- int i, j, k;
- init_genrand(19650218UL);
- i=1; j=0;
- k = (N>key_length ? N : key_length);
- for (; k; k--) {
- state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525UL))
- + init_key[j] + j; /* non linear */
- state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
- i++; j++;
- if (i>=N) { state[0] = state[N-1]; i=1; }
- if (j>=key_length) j=0;
- }
- for (k=N-1; k; k--) {
- state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL))
- - i; /* non linear */
- state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
- i++;
- if (i>=N) { state[0] = state[N-1]; i=1; }
- }
-
- state[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
- left = 1; initf = 1;
-}
-
-static void
-next_state()
-{
- unsigned long *p=state;
- int j;
-
- /* if init_genrand() has not been called, */
- /* a default initial seed is used */
- if (initf==0) init_genrand(5489UL);
-
- left = N;
- next = state;
-
- for (j=N-M+1; --j; p++)
- *p = p[M] ^ TWIST(p[0], p[1]);
-
- for (j=M; --j; p++)
- *p = p[M-N] ^ TWIST(p[0], p[1]);
-
- *p = p[M-N] ^ TWIST(p[0], state[0]);
-}
-
-/* generates a random number on [0,0xffffffff]-interval */
-static unsigned long
-genrand_int32(void)
-{
- unsigned long y;
-
- if (--left == 0) next_state();
- y = *next++;
-
- /* Tempering */
- y ^= (y >> 11);
- y ^= (y << 7) & 0x9d2c5680UL;
- y ^= (y << 15) & 0xefc60000UL;
- y ^= (y >> 18);
-
- return y;
-}
-
-/* generates a random number on [0,1) with 53-bit resolution*/
-static double
-genrand_real(void)
-{
- unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
- return(a*67108864.0+b)*(1.0/9007199254740992.0);
-}
-/* These real versions are due to Isaku Wada, 2002/01/09 added */
-
-#undef N
-#undef M
-
-/* These real versions are due to Isaku Wada, 2002/01/09 added */
-
-#include "ruby.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-static int first = 1;
-static VALUE saved_seed = INT2FIX(0);
-
-static VALUE
-rand_init(vseed)
- VALUE vseed;
-{
- volatile VALUE seed;
- VALUE old;
- long len;
- unsigned long *buf;
-
- seed = rb_to_int(vseed);
- switch (TYPE(seed)) {
- case T_FIXNUM:
- len = sizeof(VALUE);
- break;
- case T_BIGNUM:
- len = RBIGNUM(seed)->len * SIZEOF_BDIGITS;
- if (len == 0)
- len = 4;
- break;
- default:
- rb_raise(rb_eTypeError, "failed to convert %s into Integer",
- rb_obj_classname(vseed));
- }
- len = (len + 3) / 4; /* number of 32bit words */
- buf = ALLOC_N(unsigned long, len); /* allocate longs for init_by_array */
- memset(buf, 0, len * sizeof(long));
- if (FIXNUM_P(seed)) {
- buf[0] = FIX2ULONG(seed) & 0xffffffff;
-#if SIZEOF_LONG > 4
- buf[1] = FIX2ULONG(seed) >> 32;
-#endif
- }
- else {
- int i, j;
- for (i = RBIGNUM(seed)->len-1; 0 <= i; i--) {
- j = i * SIZEOF_BDIGITS / 4;
-#if SIZEOF_BDIGITS < 4
- buf[j] <<= SIZEOF_BDIGITS * 8;
-#endif
- buf[j] |= ((BDIGIT *)RBIGNUM(seed)->digits)[i];
- }
- }
- while (1 < len && buf[len-1] == 0) {
- len--;
- }
- if (len <= 1) {
- init_genrand(buf[0]);
- }
- else {
- if (buf[len-1] == 1) /* remove leading-zero-guard */
- len--;
- init_by_array(buf, len);
- }
- first = 0;
- old = saved_seed;
- saved_seed = seed;
- free(buf);
- return old;
-}
-
-static VALUE
-random_seed()
-{
- static int n = 0;
- struct timeval tv;
- int fd;
- struct stat statbuf;
-
- int seed_len;
- BDIGIT *digits;
- unsigned long *seed;
- NEWOBJ(big, struct RBignum);
- OBJSETUP(big, rb_cBignum, T_BIGNUM);
-
- seed_len = 4 * sizeof(long);
- big->sign = 1;
- big->len = seed_len / SIZEOF_BDIGITS + 1;
- digits = big->digits = ALLOC_N(BDIGIT, big->len);
- seed = (unsigned long *)big->digits;
-
- memset(digits, 0, big->len * SIZEOF_BDIGITS);
-
-#ifdef S_ISCHR
- if ((fd = open("/dev/urandom", O_RDONLY
-#ifdef O_NONBLOCK
- |O_NONBLOCK
-#endif
-#ifdef O_NOCTTY
- |O_NOCTTY
-#endif
-#ifdef O_NOFOLLOW
- |O_NOFOLLOW
-#endif
- )) >= 0) {
- if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
- read(fd, seed, seed_len);
- }
- close(fd);
- }
-#endif
-
- gettimeofday(&tv, 0);
- seed[0] ^= tv.tv_usec;
- seed[1] ^= tv.tv_sec;
- seed[2] ^= getpid() ^ (n++ << 16);
- seed[3] ^= (unsigned long)&seed;
-
- /* set leading-zero-guard if need. */
- digits[big->len-1] = digits[big->len-2] <= 1 ? 1 : 0;
-
- return rb_big_norm((VALUE)big);
-}
-
-/*
- * call-seq:
- * srand(number=0) => old_seed
- *
- * Seeds the pseudorandom number generator to the value of
- * <i>number</i>.<code>to_i.abs</code>. If <i>number</i> is omitted
- * or zero, seeds the generator using a combination of the time, the
- * process id, and a sequence number. (This is also the behavior if
- * <code>Kernel::rand</code> is called without previously calling
- * <code>srand</code>, but without the sequence.) By setting the seed
- * to a known value, scripts can be made deterministic during testing.
- * The previous seed value is returned. Also see <code>Kernel::rand</code>.
- */
-
-static VALUE
-rb_f_srand(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE seed, old;
-
- rb_secure(4);
- if (rb_scan_args(argc, argv, "01", &seed) == 0) {
- seed = random_seed();
- }
- old = rand_init(seed);
-
- return old;
-}
-
-static unsigned long
-make_mask(unsigned long x)
-{
- x = x | x >> 1;
- x = x | x >> 2;
- x = x | x >> 4;
- x = x | x >> 8;
- x = x | x >> 16;
-#if 4 < SIZEOF_LONG
- x = x | x >> 32;
-#endif
- return x;
-}
-
-static unsigned long
-limited_rand(unsigned long limit)
-{
- unsigned long mask = make_mask(limit);
- int i;
- unsigned long val;
-
- retry:
- val = 0;
- for (i = SIZEOF_LONG/4-1; 0 <= i; i--) {
- if (mask >> (i * 32)) {
- val |= genrand_int32() << (i * 32);
- val &= mask;
- if (limit < val)
- goto retry;
- }
- }
- return val;
-}
-
-static VALUE
-limited_big_rand(struct RBignum *limit)
-{
- unsigned long mask, lim, rnd;
- struct RBignum *val;
- int i, len, boundary;
-
- len = (limit->len * SIZEOF_BDIGITS + 3) / 4;
- val = (struct RBignum *)rb_big_clone((VALUE)limit);
- val->sign = 1;
-#if SIZEOF_BDIGITS == 2
-# define BIG_GET32(big,i) (((BDIGIT *)(big)->digits)[(i)*2] | \
- ((i)*2+1 < (big)->len ? (((BDIGIT *)(big)->digits)[(i)*2+1] << 16) \
- : 0))
-# define BIG_SET32(big,i,d) ((((BDIGIT *)(big)->digits)[(i)*2] = (d) & 0xffff), \
- ((i)*2+1 < (big)->len ? (((BDIGIT *)(big)->digits)[(i)*2+1] = (d) >> 16) \
- : 0))
-#else
- /* SIZEOF_BDIGITS == 4 */
-# define BIG_GET32(big,i) (((BDIGIT *)(big)->digits)[i])
-# define BIG_SET32(big,i,d) (((BDIGIT *)(big)->digits)[i] = (d))
-#endif
- retry:
- mask = 0;
- boundary = 1;
- for (i = len-1; 0 <= i; i--) {
- lim = BIG_GET32(limit, i);
- mask = mask ? 0xffffffff : make_mask(lim);
- if (mask) {
- rnd = genrand_int32() & mask;
- if (boundary) {
- if (lim < rnd)
- goto retry;
- if (rnd < lim)
- boundary = 0;
- }
- }
- else {
- rnd = 0;
- }
- BIG_SET32(val, i, rnd);
- }
- return rb_big_norm((VALUE)val);
-}
-
-/*
- * call-seq:
- * rand(max=0) => number
- *
- * Converts <i>max</i> to an integer using max1 =
- * max<code>.to_i.abs</code>. If the result is zero, returns a
- * pseudorandom floating point number greater than or equal to 0.0 and
- * less than 1.0. Otherwise, returns a pseudorandom integer greater
- * than or equal to zero and less than max1. <code>Kernel::srand</code>
- * may be used to ensure repeatable sequences of random numbers between
- * different runs of the program. Ruby currently uses a modified
- * Mersenne Twister with a period of 219937-1.
- *
- * srand 1234 #=> 0
- * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136]
- * [ rand(10), rand(1000) ] #=> [6, 817]
- * srand 1234 #=> 1234
- * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136]
- */
-
-static VALUE
-rb_f_rand(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE vmax;
- long val, max;
-
- rb_scan_args(argc, argv, "01", &vmax);
- if (first) {
- rand_init(random_seed());
- }
- switch (TYPE(vmax)) {
- case T_FLOAT:
- if (RFLOAT(vmax)->value <= LONG_MAX && RFLOAT(vmax)->value >= LONG_MIN) {
- max = (long)RFLOAT(vmax)->value;
- break;
- }
- if (RFLOAT(vmax)->value < 0)
- vmax = rb_dbl2big(-RFLOAT(vmax)->value);
- else
- vmax = rb_dbl2big(RFLOAT(vmax)->value);
- /* fall through */
- case T_BIGNUM:
- bignum:
- {
- struct RBignum *limit = (struct RBignum *)vmax;
- if (!limit->sign) {
- limit = (struct RBignum *)rb_big_clone(vmax);
- limit->sign = 1;
- }
- limit = (struct RBignum *)rb_big_minus((VALUE)limit, INT2FIX(1));
- if (FIXNUM_P((VALUE)limit)) {
- if (FIX2LONG((VALUE)limit) == -1)
- return rb_float_new(genrand_real());
- return LONG2NUM(limited_rand(FIX2LONG((VALUE)limit)));
- }
- return limited_big_rand(limit);
- }
- case T_NIL:
- max = 0;
- break;
- default:
- vmax = rb_Integer(vmax);
- if (TYPE(vmax) == T_BIGNUM) goto bignum;
- case T_FIXNUM:
- max = FIX2LONG(vmax);
- break;
- }
-
- if (max == 0) {
- return rb_float_new(genrand_real());
- }
- if (max < 0) max = -max;
- val = limited_rand(max-1);
- return LONG2NUM(val);
-}
-
-void
-Init_Random()
-{
- rb_define_global_function("srand", rb_f_srand, -1);
- rb_define_global_function("rand", rb_f_rand, -1);
- rb_global_variable(&saved_seed);
-}
-/**********************************************************************
-
- range.c -
-
- $Author: matz $
- $Date: 2005/03/04 06:47:41 $
- created at: Thu Aug 19 17:46:47 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-
-VALUE rb_cRange;
-static ID id_cmp, id_succ, id_beg, id_end, id_excl;
-
-#define EXCL(r) RTEST(rb_ivar_get((r), id_excl))
-#define SET_EXCL(r,v) rb_ivar_set((r), id_excl, (v) ? Qtrue : Qfalse)
-
-static VALUE
-range_failed()
-{
- rb_raise(rb_eArgError, "bad value for range");
- return Qnil; /* dummy */
-}
-
-static VALUE
-range_check(args)
- VALUE *args;
-{
- VALUE v;
-
- v = rb_funcall(args[0], id_cmp, 1, args[1]);
- if (NIL_P(v)) range_failed();
- return Qnil;
-}
-
-static void
-range_init(range, beg, end, exclude_end)
- VALUE range, beg, end;
- int exclude_end;
-{
- VALUE args[2];
-
- args[0] = beg;
- args[1] = end;
-
- if (!FIXNUM_P(beg) || !FIXNUM_P(end)) {
- rb_rescue(range_check, (VALUE)args, range_failed, 0);
- }
-
- SET_EXCL(range, exclude_end);
- rb_ivar_set(range, id_beg, beg);
- rb_ivar_set(range, id_end, end);
-}
-
-VALUE
-rb_range_new(beg, end, exclude_end)
- VALUE beg, end;
- int exclude_end;
-{
- VALUE range = rb_obj_alloc(rb_cRange);
-
- range_init(range, beg, end, exclude_end);
- return range;
-}
-
-/*
- * call-seq:
- * Range.new(start, end, exclusive=false) => range
- *
- * Constructs a range using the given <i>start</i> and <i>end</i>. If the third
- * parameter is omitted or is <code>false</code>, the <i>range</i> will include
- * the end object; otherwise, it will be excluded.
- */
-
-static VALUE
-range_initialize(argc, argv, range)
- int argc;
- VALUE *argv;
- VALUE range;
-{
- VALUE beg, end, flags;
-
- rb_scan_args(argc, argv, "21", &beg, &end, &flags);
- /* Ranges are immutable, so that they should be initialized only once. */
- if (rb_ivar_defined(range, id_beg)) {
- rb_name_error(rb_intern("initialize"), "`initialize' called twice");
- }
- range_init(range, beg, end, RTEST(flags));
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * rng.exclude_end? => true or false
- *
- * Returns <code>true</code> if <i>rng</i> excludes its end value.
- */
-
-static VALUE
-range_exclude_end_p(range)
- VALUE range;
-{
- return EXCL(range) ? Qtrue : Qfalse;
-}
-
-
-/*
- * call-seq:
- * rng == obj => true or false
- *
- * Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
- * beginning and end items (by comparing them with <code>==</code>), and has
- * the same #exclude_end? setting as <i>rng</t>.
- *
- * (0..2) == (0..2) #=> true
- * (0..2) == Range.new(0,2) #=> true
- * (0..2) == (0...2) #=> false
- *
- */
-
-static VALUE
-range_eq(range, obj)
- VALUE range, obj;
-{
- if (range == obj) return Qtrue;
- if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
- return Qfalse;
-
- if (!rb_equal(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
- return Qfalse;
- if (!rb_equal(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
- return Qfalse;
-
- if (EXCL(range) != EXCL(obj)) return Qfalse;
-
- return Qtrue;
-}
-
-static int
-r_lt(a, b)
- VALUE a, b;
-{
- VALUE r = rb_funcall(a, id_cmp, 1, b);
-
- if (NIL_P(r)) return Qfalse;
- if (rb_cmpint(r, a, b) < 0) return Qtrue;
- return Qfalse;
-}
-
-static int
-r_le(a, b)
- VALUE a, b;
-{
- int c;
- VALUE r = rb_funcall(a, id_cmp, 1, b);
-
- if (NIL_P(r)) return Qfalse;
- c = rb_cmpint(r, a, b);
- if (c == 0) return INT2FIX(0);
- if (c < 0) return Qtrue;
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * rng.eql?(obj) => true or false
- *
- * Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
- * beginning and end items (by comparing them with #eql?), and has the same
- * #exclude_end? setting as <i>rng</i>.
- *
- * (0..2) == (0..2) #=> true
- * (0..2) == Range.new(0,2) #=> true
- * (0..2) == (0...2) #=> false
- *
- */
-
-static VALUE
-range_eql(range, obj)
- VALUE range, obj;
-{
- if (range == obj) return Qtrue;
- if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
- return Qfalse;
-
- if (!rb_eql(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
- return Qfalse;
- if (!rb_eql(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
- return Qfalse;
-
- if (EXCL(range) != EXCL(obj)) return Qfalse;
-
- return Qtrue;
-}
-
-/*
- * call-seq:
- * rng.hash => fixnum
- *
- * Generate a hash value such that two ranges with the same start and
- * end points, and the same value for the "exclude end" flag, generate
- * the same hash value.
- */
-
-static VALUE
-range_hash(range)
- VALUE range;
-{
- long hash = EXCL(range);
- VALUE v;
-
- v = rb_hash(rb_ivar_get(range, id_beg));
- hash ^= v << 1;
- v = rb_hash(rb_ivar_get(range, id_end));
- hash ^= v << 9;
- hash ^= EXCL(range) << 24;
-
- return LONG2FIX(hash);
-}
-
-static VALUE
-str_step(args)
- VALUE *args;
-{
- return rb_str_upto(args[0], args[1], EXCL(args[2]));
-}
-
-static void
-range_each_func(range, func, v, e, arg)
- VALUE range;
- void (*func) _((VALUE, void*));
- VALUE v, e;
- void *arg;
-{
- int c;
-
- if (EXCL(range)) {
- while (r_lt(v, e)) {
- (*func)(v, arg);
- v = rb_funcall(v, id_succ, 0, 0);
- }
- }
- else {
- while (RTEST(c = r_le(v, e))) {
- (*func)(v, arg);
- if (c == INT2FIX(0)) break;
- v = rb_funcall(v, id_succ, 0, 0);
- }
- }
-}
-
-static VALUE
-step_i(i, iter)
- VALUE i;
- long *iter;
-{
- iter[0]--;
- if (iter[0] == 0) {
- rb_yield(i);
- iter[0] = iter[1];
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * rng.step(n=1) {| obj | block } => rng
- *
- * Iterates over <i>rng</i>, passing each <i>n</i>th element to the block. If
- * the range contains numbers or strings, natural ordering is used. Otherwise
- * <code>step</code> invokes <code>succ</code> to iterate through range
- * elements. The following code uses class <code>Xs</code>, which is defined
- * in the class-level documentation.
- *
- * range = Xs.new(1)..Xs.new(10)
- * range.step(2) {|x| puts x}
- * range.step(3) {|x| puts x}
- *
- * <em>produces:</em>
- *
- * 1 x
- * 3 xxx
- * 5 xxxxx
- * 7 xxxxxxx
- * 9 xxxxxxxxx
- * 1 x
- * 4 xxxx
- * 7 xxxxxxx
- * 10 xxxxxxxxxx
- */
-
-
-static VALUE
-range_step(argc, argv, range)
- int argc;
- VALUE *argv;
- VALUE range;
-{
- VALUE b, e, step;
- long unit;
-
- b = rb_ivar_get(range, id_beg);
- e = rb_ivar_get(range, id_end);
- if (rb_scan_args(argc, argv, "01", &step) == 0) {
- step = INT2FIX(1);
- }
-
- unit = NUM2LONG(step);
- if (unit < 0) {
- rb_raise(rb_eArgError, "step can't be negative");
- }
- if (FIXNUM_P(b) && FIXNUM_P(e)) { /* fixnums are special */
- long end = FIX2LONG(e);
- long i;
-
- if (unit == 0) rb_raise(rb_eArgError, "step can't be 0");
- if (!EXCL(range)) end += 1;
- for (i=FIX2LONG(b); i<end; i+=unit) {
- rb_yield(LONG2NUM(i));
- }
- }
- else {
- VALUE tmp = rb_check_string_type(b);
-
- if (!NIL_P(tmp)) {
- VALUE args[5];
- long iter[2];
-
- b = tmp;
- if (unit == 0) rb_raise(rb_eArgError, "step can't be 0");
- args[0] = b; args[1] = e; args[2] = range;
- iter[0] = 1; iter[1] = unit;
- rb_iterate((VALUE(*)_((VALUE)))str_step, (VALUE)args, step_i,
- (VALUE)iter);
- }
- else if (rb_obj_is_kind_of(b, rb_cNumeric)) {
- ID c = rb_intern(EXCL(range) ? "<" : "<=");
-
- if (rb_equal(step, INT2FIX(0))) rb_raise(rb_eArgError, "step can't be 0");
- while (RTEST(rb_funcall(b, c, 1, e))) {
- rb_yield(b);
- b = rb_funcall(b, '+', 1, step);
- }
- }
- else {
- long args[2];
-
- if (unit == 0) rb_raise(rb_eArgError, "step can't be 0");
- if (!rb_respond_to(b, id_succ)) {
- rb_raise(rb_eTypeError, "can't iterate from %s",
- rb_obj_classname(b));
- }
-
- args[0] = 1;
- args[1] = unit;
- range_each_func(range, step_i, b, e, args);
- }
- }
- return range;
-}
-
-static void
-each_i(v, arg)
- VALUE v;
- void *arg;
-{
- rb_yield(v);
-}
-
-/*
- * call-seq:
- * rng.each {| i | block } => rng
- *
- * Iterates over the elements <i>rng</i>, passing each in turn to the
- * block. You can only iterate if the start object of the range
- * supports the +succ+ method (which means that you can't iterate over
- * ranges of +Float+ objects).
- *
- * (10..15).each do |n|
- * print n, ' '
- * end
- *
- * <em>produces:</em>
- *
- * 10 11 12 13 14 15
- */
-
-static VALUE
-range_each(range)
- VALUE range;
-{
- VALUE beg, end;
-
- beg = rb_ivar_get(range, id_beg);
- end = rb_ivar_get(range, id_end);
-
- if (!rb_respond_to(beg, id_succ)) {
- rb_raise(rb_eTypeError, "can't iterate from %s",
- rb_obj_classname(beg));
- }
- if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
- long lim = FIX2LONG(end);
- long i;
-
- if (!EXCL(range)) lim += 1;
- for (i=FIX2LONG(beg); i<lim; i++) {
- rb_yield(LONG2NUM(i));
- }
- }
- else if (TYPE(beg) == T_STRING) {
- VALUE args[5];
- long iter[2];
-
- args[0] = beg; args[1] = end; args[2] = range;
- iter[0] = 1; iter[1] = 1;
- rb_iterate((VALUE(*)_((VALUE)))str_step, (VALUE)args, step_i,
- (VALUE)iter);
- }
- else {
- range_each_func(range, each_i, beg, end, NULL);
- }
- return range;
-}
-
-/*
- * call-seq:
- * rng.first => obj
- * rng.begin => obj
- *
- * Returns the first object in <i>rng</i>.
- */
-
-static VALUE
-range_first(range)
- VALUE range;
-{
- return rb_ivar_get(range, id_beg);
-}
-
-
-/*
- * call-seq:
- * rng.end => obj
- * rng.last => obj
- *
- * Returns the object that defines the end of <i>rng</i>.
- *
- * (1..10).end #=> 10
- * (1...10).end #=> 10
- */
-
-
-static VALUE
-range_last(range)
- VALUE range;
-{
- return rb_ivar_get(range, id_end);
-}
-
-VALUE
-rb_range_beg_len(range, begp, lenp, len, err)
- VALUE range;
- long *begp, *lenp;
- long len;
- int err;
-{
- long beg, end, b, e;
-
- if (!rb_obj_is_kind_of(range, rb_cRange)) return Qfalse;
-
- beg = b = NUM2LONG(rb_ivar_get(range, id_beg));
- end = e = NUM2LONG(rb_ivar_get(range, id_end));
-
- if (beg < 0) {
- beg += len;
- if (beg < 0) goto out_of_range;
- }
- if (err == 0 || err == 2) {
- if (beg > len) goto out_of_range;
- if (end > len) end = len;
- }
- if (end < 0) end += len;
- if (!EXCL(range)) end++; /* include end point */
- len = end - beg;
- if (len < 0) len = 0;
-
- *begp = beg;
- *lenp = len;
- return Qtrue;
-
- out_of_range:
- if (err) {
- rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
- b, EXCL(range)? "." : "", e);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * rng.to_s => string
- *
- * Convert this range object to a printable form.
- */
-
-static VALUE
-range_to_s(range)
- VALUE range;
-{
- VALUE str, str2;
-
- str = rb_obj_as_string(rb_ivar_get(range, id_beg));
- str2 = rb_obj_as_string(rb_ivar_get(range, id_end));
- str = rb_str_dup(str);
- rb_str_cat(str, "...", EXCL(range)?3:2);
- rb_str_append(str, str2);
- OBJ_INFECT(str, str2);
-
- return str;
-}
-
-/*
- * call-seq:
- * rng.inspect => string
- *
- * Convert this range object to a printable form (using
- * <code>inspect</code> to convert the start and end
- * objects).
- */
-
-
-static VALUE
-range_inspect(range)
- VALUE range;
-{
- VALUE str, str2;
-
- str = rb_inspect(rb_ivar_get(range, id_beg));
- str2 = rb_inspect(rb_ivar_get(range, id_end));
- str = rb_str_dup(str);
- rb_str_cat(str, "...", EXCL(range)?3:2);
- rb_str_append(str, str2);
- OBJ_INFECT(str, str2);
-
- return str;
-}
-
-/*
- * call-seq:
- * rng === obj => true or false
- * rng.member?(val) => true or false
- * rng.include?(val) => true or false
- *
- * Returns <code>true</code> if <i>obj</i> is an element of
- * <i>rng</i>, <code>false</code> otherwise. Conveniently,
- * <code>===</code> is the comparison operator used by
- * <code>case</code> statements.
- *
- * case 79
- * when 1..50 then print "low\n"
- * when 51..75 then print "medium\n"
- * when 76..100 then print "high\n"
- * end
- *
- * <em>produces:</em>
- *
- * high
- */
-
-static VALUE
-range_include(range, val)
- VALUE range, val;
-{
- VALUE beg, end;
-
- beg = rb_ivar_get(range, id_beg);
- end = rb_ivar_get(range, id_end);
- if (r_le(beg, val)) {
- if (EXCL(range)) {
- if (r_lt(val, end)) return Qtrue;
- }
- else {
- if (r_le(val, end)) return Qtrue;
- }
- }
- return Qfalse;
-}
-
-
-/* A <code>Range</code> represents an interval---a set of values with a
- * start and an end. Ranges may be constructed using the
- * <em>s</em><code>..</code><em>e</em> and
- * <em>s</em><code>...</code><em>e</em> literals, or with
- * <code>Range::new</code>. Ranges constructed using <code>..</code>
- * run from the start to the end inclusively. Those created using
- * <code>...</code> exclude the end value. When used as an iterator,
- * ranges return each value in the sequence.
- *
- * (-1..-5).to_a #=> []
- * (-5..-1).to_a #=> [-5, -4, -3, -2, -1]
- * ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"]
- * ('a'...'e').to_a #=> ["a", "b", "c", "d"]
- *
- * Ranges can be constructed using objects of any type, as long as the
- * objects can be compared using their <code><=></code> operator and
- * they support the <code>succ</code> method to return the next object
- * in sequence.
- *
- * class Xs # represent a string of 'x's
- * include Comparable
- * attr :length
- * def initialize(n)
- * @length = n
- * end
- * def succ
- * Xs.new(@length + 1)
- * end
- * def <=>(other)
- * @length <=> other.length
- * end
- * def to_s
- * sprintf "%2d #{inspect}", @length
- * end
- * def inspect
- * 'x' * @length
- * end
- * end
- *
- * r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx
- * r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx]
- * r.member?(Xs.new(5)) #=> true
- *
- * In the previous code example, class <code>Xs</code> includes the
- * <code>Comparable</code> module. This is because
- * <code>Enumerable#member?</code> checks for equality using
- * <code>==</code>. Including <code>Comparable</code> ensures that the
- * <code>==</code> method is defined in terms of the <code><=></code>
- * method implemented in <code>Xs</code>.
- *
- */
-
-void
-Init_Range()
-{
- rb_cRange = rb_define_class("Range", rb_cObject);
- rb_include_module(rb_cRange, rb_mEnumerable);
- rb_define_method(rb_cRange, "initialize", range_initialize, -1);
- rb_define_method(rb_cRange, "==", range_eq, 1);
- rb_define_method(rb_cRange, "===", range_include, 1);
- rb_define_method(rb_cRange, "eql?", range_eql, 1);
- rb_define_method(rb_cRange, "hash", range_hash, 0);
- rb_define_method(rb_cRange, "each", range_each, 0);
- rb_define_method(rb_cRange, "step", range_step, -1);
- rb_define_method(rb_cRange, "first", range_first, 0);
- rb_define_method(rb_cRange, "last", range_last, 0);
- rb_define_method(rb_cRange, "begin", range_first, 0);
- rb_define_method(rb_cRange, "end", range_last, 0);
- rb_define_method(rb_cRange, "to_s", range_to_s, 0);
- rb_define_method(rb_cRange, "inspect", range_inspect, 0);
-
- rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
-
- rb_define_method(rb_cRange, "member?", range_include, 1);
- rb_define_method(rb_cRange, "include?", range_include, 1);
-
- id_cmp = rb_intern("<=>");
- id_succ = rb_intern("succ");
- id_beg = rb_intern("begin");
- id_end = rb_intern("end");
- id_excl = rb_intern("excl");
-}
-/**********************************************************************
-
- re.c -
-
- $Author: nobu $
- created at: Mon Aug 9 18:24:49 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include "re.h"
-#include "regint.h"
-#include <ctype.h>
-
-#define MBCTYPE_ASCII 0
-#define MBCTYPE_EUC 1
-#define MBCTYPE_SJIS 2
-#define MBCTYPE_UTF8 3
-
-static VALUE rb_eRegexpError;
-
-#define BEG(no) regs->beg[no]
-#define END(no) regs->end[no]
-
-#if 'a' == 97 /* it's ascii */
-static const char casetable[] = {
- '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
- '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
- '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
- '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
- /* ' ' '!' '"' '#' '$' '%' '&' ''' */
- '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
- /* '(' ')' '*' '+' ',' '-' '.' '/' */
- '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
- /* '0' '1' '2' '3' '4' '5' '6' '7' */
- '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
- /* '8' '9' ':' ';' '<' '=' '>' '?' */
- '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
- /* '@' 'A' 'B' 'C' 'D' 'E' 'F' 'G' */
- '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- /* 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' */
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- /* 'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'W' */
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- /* 'X' 'Y' 'Z' '[' '\' ']' '^' '_' */
- '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
- /* '`' 'a' 'b' 'c' 'd' 'e' 'f' 'g' */
- '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- /* 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' */
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- /* 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' */
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- /* 'x' 'y' 'z' '{' '|' '}' '~' */
- '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
- '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
- '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
- '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
- '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
- '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
- '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
- '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
- '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
- '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
- '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
- '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
- '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
- '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
-};
-#else
-# error >>> "You lose. You will need a translation table for your character set." <<<
-#endif
-
-int
-rb_memcicmp(p1, p2, len)
- char *p1, *p2;
- long len;
-{
- int tmp;
-
- while (len--) {
- if (tmp = casetable[(unsigned)*p1++] - casetable[(unsigned)*p2++])
- return tmp;
- }
- return 0;
-}
-
-int
-rb_memcmp(p1, p2, len)
- char *p1, *p2;
- long len;
-{
- if (!ruby_ignorecase) {
- return memcmp(p1, p2, len);
- }
- return rb_memcicmp(p1, p2, len);
-}
-
-long
-rb_memsearch(x0, m, y0, n)
- char *x0, *y0;
- long m, n;
-{
- unsigned char *x = (unsigned char *)x0, *y = (unsigned char *)y0;
- unsigned char *s, *e;
- long i;
- int d;
- unsigned long hx, hy;
-
-#define KR_REHASH(a, b, h) (((h) << 1) - ((long)(a)<<d) + (b))
-
- if (m > n) return -1;
- s = y; e = s + n - m;
-
- /* Preprocessing */
- /* computes d = 2^(m-1) with
- the left-shift operator */
- d = sizeof(hx) * CHAR_BIT - 1;
- if (d > m) d = m;
-
- if (ruby_ignorecase) {
- if (n == m) {
- return rb_memcicmp(x, s, m) == 0 ? 0 : -1;
- }
- /* Prepare hash value */
- for (hy = hx = i = 0; i < d; ++i) {
- hx = KR_REHASH(0, casetable[x[i]], hx);
- hy = KR_REHASH(0, casetable[s[i]], hy);
- }
- /* Searching */
- while (hx != hy || rb_memcicmp(x, s, m)) {
- if (s >= e) return -1;
- hy = KR_REHASH(casetable[*s], casetable[*(s+d)], hy);
- s++;
- }
- }
- else {
- if (n == m) {
- return memcmp(x, s, m) == 0 ? 0 : -1;
- }
- /* Prepare hash value */
- for (hy = hx = i = 0; i < d; ++i) {
- hx = KR_REHASH(0, x[i], hx);
- hy = KR_REHASH(0, s[i], hy);
- }
- /* Searching */
- while (hx != hy || memcmp(x, s, m)) {
- if (s >= e) return -1;
- hy = KR_REHASH(*s, *(s+d), hy);
- s++;
- }
- }
- return s-y;
-}
-
-#define REG_CASESTATE FL_USER0
-#define KCODE_NONE 0
-#define KCODE_EUC FL_USER1
-#define KCODE_SJIS FL_USER2
-#define KCODE_UTF8 FL_USER3
-#define KCODE_FIXED FL_USER4
-#define KCODE_MASK (KCODE_EUC|KCODE_SJIS|KCODE_UTF8)
-
-static int reg_kcode = DEFAULT_KCODE;
-
-static void
-kcode_euc(re)
- struct RRegexp *re;
-{
- FL_UNSET(re, KCODE_MASK);
- FL_SET(re, KCODE_EUC);
- FL_SET(re, KCODE_FIXED);
-}
-
-static void
-kcode_sjis(re)
- struct RRegexp *re;
-{
- FL_UNSET(re, KCODE_MASK);
- FL_SET(re, KCODE_SJIS);
- FL_SET(re, KCODE_FIXED);
-}
-
-static void
-kcode_utf8(re)
- struct RRegexp *re;
-{
- FL_UNSET(re, KCODE_MASK);
- FL_SET(re, KCODE_UTF8);
- FL_SET(re, KCODE_FIXED);
-}
-
-static void
-kcode_none(re)
- struct RRegexp *re;
-{
- FL_UNSET(re, KCODE_MASK);
- FL_SET(re, KCODE_FIXED);
-}
-
-static int curr_kcode;
-
-static void
-kcode_set_option(re)
- VALUE re;
-{
- if (!FL_TEST(re, KCODE_FIXED)) return;
-
- curr_kcode = RBASIC(re)->flags & KCODE_MASK;
- if (reg_kcode == curr_kcode) return;
- switch (curr_kcode) {
- case KCODE_NONE:
- onigenc_set_default_encoding(ONIG_ENCODING_ASCII);
- break;
- case KCODE_EUC:
- onigenc_set_default_encoding(ONIG_ENCODING_EUC_JP);
- break;
- case KCODE_SJIS:
- onigenc_set_default_encoding(ONIG_ENCODING_SJIS);
- break;
- case KCODE_UTF8:
- onigenc_set_default_encoding(ONIG_ENCODING_UTF8);
- break;
- }
-}
-
-static void
-kcode_reset_option()
-{
- if (reg_kcode == curr_kcode) return;
- switch (reg_kcode) {
- case KCODE_NONE:
- onigenc_set_default_encoding(ONIG_ENCODING_ASCII);
- break;
- case KCODE_EUC:
- onigenc_set_default_encoding(ONIG_ENCODING_EUC_JP);
- break;
- case KCODE_SJIS:
- onigenc_set_default_encoding(ONIG_ENCODING_SJIS);
- break;
- case KCODE_UTF8:
- onigenc_set_default_encoding(ONIG_ENCODING_UTF8);
- break;
- }
-}
-
-int
-rb_reg_mbclen2(c, re)
- unsigned int c;
- VALUE re;
-{
- int len;
- unsigned char uc = (unsigned char)c;
-
- if (!FL_TEST(re, KCODE_FIXED))
- return mbclen(uc);
- kcode_set_option(re);
- len = mbclen(uc);
- kcode_reset_option();
- return len;
-}
-
-static void
-rb_reg_check(re)
- VALUE re;
-{
- if (!RREGEXP(re)->ptr || !RREGEXP(re)->str) {
- rb_raise(rb_eTypeError, "uninitialized Regexp");
- }
-}
-
-static void
-rb_reg_expr_str(str, s, len)
- VALUE str;
- const char *s;
- long len;
-{
- const char *p, *pend;
- int need_escape = 0;
-
- p = s; pend = p + len;
- while (p<pend) {
- if (*p == '/' || (!ISPRINT(*p) && !ismbchar(*p))) {
- need_escape = 1;
- break;
- }
- p += mbclen(*p);
- }
- if (!need_escape) {
- rb_str_buf_cat(str, s, len);
- }
- else {
- p = s;
- while (p<pend) {
- if (*p == '\\') {
- int n = mbclen(p[1]) + 1;
- rb_str_buf_cat(str, p, n);
- p += n;
- continue;
- }
- else if (*p == '/') {
- char c = '\\';
- rb_str_buf_cat(str, &c, 1);
- rb_str_buf_cat(str, p, 1);
- }
- else if (ismbchar(*p)) {
- rb_str_buf_cat(str, p, mbclen(*p));
- p += mbclen(*p);
- continue;
- }
- else if (ISPRINT(*p)) {
- rb_str_buf_cat(str, p, 1);
- }
- else if (!ISSPACE(*p)) {
- char b[8];
-
- sprintf(b, "\\%03o", *p & 0377);
- rb_str_buf_cat(str, b, 4);
- }
- else {
- rb_str_buf_cat(str, p, 1);
- }
- p++;
- }
- }
-}
-
-static VALUE
-rb_reg_desc(s, len, re)
- const char *s;
- long len;
- VALUE re;
-{
- VALUE str = rb_str_buf_new2("/");
-
- rb_reg_expr_str(str, s, len);
- rb_str_buf_cat2(str, "/");
- if (re) {
- rb_reg_check(re);
- if (RREGEXP(re)->ptr->options & ONIG_OPTION_MULTILINE)
- rb_str_buf_cat2(str, "m");
- if (RREGEXP(re)->ptr->options & ONIG_OPTION_IGNORECASE)
- rb_str_buf_cat2(str, "i");
- if (RREGEXP(re)->ptr->options & ONIG_OPTION_EXTEND)
- rb_str_buf_cat2(str, "x");
-
- if (FL_TEST(re, KCODE_FIXED)) {
- switch ((RBASIC(re)->flags & KCODE_MASK)) {
- case KCODE_NONE:
- rb_str_buf_cat2(str, "n");
- break;
- case KCODE_EUC:
- rb_str_buf_cat2(str, "e");
- break;
- case KCODE_SJIS:
- rb_str_buf_cat2(str, "s");
- break;
- case KCODE_UTF8:
- rb_str_buf_cat2(str, "u");
- break;
- }
- }
- }
- OBJ_INFECT(str, re);
- return str;
-}
-
-
-/*
- * call-seq:
- * rxp.source => str
- *
- * Returns the original string of the pattern.
- *
- * /ab+c/ix.source #=> "ab+c"
- */
-
-static VALUE
-rb_reg_source(re)
- VALUE re;
-{
- VALUE str;
-
- rb_reg_check(re);
- str = rb_str_new(RREGEXP(re)->str,RREGEXP(re)->len);
- if (OBJ_TAINTED(re)) OBJ_TAINT(str);
- return str;
-}
-
-/*
- * call-seq:
- * rxp.inspect => string
- *
- * Produce a nicely formatted string-version of _rxp_. Perhaps surprisingly,
- * <code>#inspect</code> actually produces the more natural version of
- * the string than <code>#to_s</code>.
- *
- * /ab+c/ix.to_s #=> /ab+c/ix
-*/
-
-static VALUE
-rb_reg_inspect(re)
- VALUE re;
-{
- rb_reg_check(re);
- return rb_reg_desc(RREGEXP(re)->str, RREGEXP(re)->len, re);
-}
-
-
-/*
- * call-seq:
- * rxp.to_s => str
- *
- * Returns a string containing the regular expression and its options (using the
- * <code>(?xxx:yyy)</code> notation. This string can be fed back in to
- * <code>Regexp::new</code> to a regular expression with the same semantics as
- * the original. (However, <code>Regexp#==</code> may not return true when
- * comparing the two, as the source of the regular expression itself may
- * differ, as the example shows). <code>Regexp#inspect</code> produces a
- * generally more readable version of <i>rxp</i>.
- *
- * r1 = /ab+c/ix #=> /ab+c/ix
- * s1 = r1.to_s #=> "(?ix-m:ab+c)"
- * r2 = Regexp.new(s1) #=> /(?ix-m:ab+c)/
- * r1 == r2 #=> false
- * r1.source #=> "ab+c"
- * r2.source #=> "(?ix-m:ab+c)"
- */
-
-static VALUE
-rb_reg_to_s(re)
- VALUE re;
-{
- int options;
- const int embeddable = ONIG_OPTION_MULTILINE|ONIG_OPTION_IGNORECASE|ONIG_OPTION_EXTEND;
- long len;
- const char* ptr;
- VALUE str = rb_str_buf_new2("(?");
-
- rb_reg_check(re);
-
- options = RREGEXP(re)->ptr->options;
- ptr = RREGEXP(re)->str;
- len = RREGEXP(re)->len;
- again:
- if (len >= 4 && ptr[0] == '(' && ptr[1] == '?') {
- int err = 1;
- ptr += 2;
- if ((len -= 2) > 0) {
- do {
- if (*ptr == 'm') {
- options |= ONIG_OPTION_MULTILINE;
- }
- else if (*ptr == 'i') {
- options |= ONIG_OPTION_IGNORECASE;
- }
- else if (*ptr == 'x') {
- options |= ONIG_OPTION_EXTEND;
- }
- else break;
- ++ptr;
- } while (--len > 0);
- }
- if (len > 1 && *ptr == '-') {
- ++ptr;
- --len;
- do {
- if (*ptr == 'm') {
- options &= ~ONIG_OPTION_MULTILINE;
- }
- else if (*ptr == 'i') {
- options &= ~ONIG_OPTION_IGNORECASE;
- }
- else if (*ptr == 'x') {
- options &= ~ONIG_OPTION_EXTEND;
- }
- else break;
- ++ptr;
- } while (--len > 0);
- }
- if (*ptr == ')') {
- --len;
- ++ptr;
- goto again;
- }
- if (*ptr == ':' && ptr[len-1] == ')') {
- int r;
- Regexp *rp;
- kcode_set_option(re);
- r = onig_alloc_init(&rp, ONIG_OPTION_DEFAULT,
- ONIGENC_AMBIGUOUS_MATCH_DEFAULT,
- onigenc_get_default_encoding(),
- OnigDefaultSyntax);
- if (r == 0) {
- ++ptr;
- len -= 2;
- err = (onig_compile(rp, ptr, ptr + len, NULL) != 0);
- }
- kcode_reset_option();
- onig_free(rp);
- }
- if (err) {
- options = RREGEXP(re)->ptr->options;
- ptr = RREGEXP(re)->str;
- len = RREGEXP(re)->len;
- }
- }
-
- if (options & ONIG_OPTION_MULTILINE) rb_str_buf_cat2(str, "m");
- if (options & ONIG_OPTION_IGNORECASE) rb_str_buf_cat2(str, "i");
- if (options & ONIG_OPTION_EXTEND) rb_str_buf_cat2(str, "x");
-
- if ((options & embeddable) != embeddable) {
- rb_str_buf_cat2(str, "-");
- if (!(options & ONIG_OPTION_MULTILINE)) rb_str_buf_cat2(str, "m");
- if (!(options & ONIG_OPTION_IGNORECASE)) rb_str_buf_cat2(str, "i");
- if (!(options & ONIG_OPTION_EXTEND)) rb_str_buf_cat2(str, "x");
- }
-
- rb_str_buf_cat2(str, ":");
- rb_reg_expr_str(str, ptr, len);
- rb_str_buf_cat2(str, ")");
-
- OBJ_INFECT(str, re);
- return str;
-}
-
-static void
-rb_reg_raise(s, len, err, re, ce)
- const char *s;
- long len;
- const char *err;
- VALUE re;
- int ce;
-{
- VALUE desc = rb_reg_desc(s, len, re);
-
- if (ce)
- rb_compile_error("%s: %s", err, RSTRING(desc)->ptr);
- else
- rb_raise(rb_eRegexpError, "%s: %s", err, RSTRING(desc)->ptr);
-}
-
-
-/*
- * call-seq:
- * rxp.casefold? => true or false
- *
- * Returns the value of the case-insensitive flag.
- */
-
-static VALUE
-rb_reg_casefold_p(re)
- VALUE re;
-{
- rb_reg_check(re);
- if (RREGEXP(re)->ptr->options & ONIG_OPTION_IGNORECASE) return Qtrue;
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * rxp.options => fixnum
- *
- * Returns the set of bits corresponding to the options used when creating this
- * Regexp (see <code>Regexp::new</code> for details. Note that additional bits
- * may be set in the returned options: these are used internally by the regular
- * expression code. These extra bits are ignored if the options are passed to
- * <code>Regexp::new</code>.
- *
- * Regexp::IGNORECASE #=> 1
- * Regexp::EXTENDED #=> 2
- * Regexp::MULTILINE #=> 4
- *
- * /cat/.options #=> 128
- * /cat/ix.options #=> 131
- * Regexp.new('cat', true).options #=> 129
- * Regexp.new('cat', 0, 's').options #=> 384
- *
- * r = /cat/ix
- * Regexp.new(r.source, r.options) #=> /cat/ix
- */
-
-static VALUE
-rb_reg_options_m(re)
- VALUE re;
-{
- int options = rb_reg_options(re);
- return INT2NUM(options);
-}
-
-
-/*
- * call-seq:
- * rxp.kcode => str
- *
- * Returns the character set code for the regexp.
- */
-
-static VALUE
-rb_reg_kcode_m(re)
- VALUE re;
-{
- char *kcode;
-
- if (FL_TEST(re, KCODE_FIXED)) {
- switch (RBASIC(re)->flags & KCODE_MASK) {
- case KCODE_NONE:
- kcode = "none"; break;
- case KCODE_EUC:
- kcode = "euc"; break;
- case KCODE_SJIS:
- kcode = "sjis"; break;
- case KCODE_UTF8:
- kcode = "utf8"; break;
- default:
- rb_bug("unknown kcode - should not happen");
- break;
- }
- return rb_str_new2(kcode);
- }
- return Qnil;
-}
-
-static Regexp*
-make_regexp(s, len, flags, ce)
- const char *s;
- long len;
- int flags;
- int ce;
-{
- Regexp *rp;
- char err[ONIG_MAX_ERROR_MESSAGE_LEN];
- int r;
- OnigErrorInfo einfo;
-
- /* Handle escaped characters first. */
-
- /* Build a copy of the string (in dest) with the
- escaped characters translated, and generate the regex
- from that.
- */
-
- r = onig_alloc_init(&rp, flags,
- ONIGENC_AMBIGUOUS_MATCH_DEFAULT,
- onigenc_get_default_encoding(),
- OnigDefaultSyntax);
- if (r) {
- onig_error_code_to_str((UChar* )err, r);
- rb_reg_raise(s, len, err, 0, ce);
- }
-
- r = onig_compile(rp, (UChar* )s, (UChar* )(s + len), &einfo);
-
- if (r != 0) {
- onig_free(rp);
- (void )onig_error_code_to_str((UChar* )err, r, &einfo);
- rb_reg_raise(s, len, err, 0, ce);
- }
- return rp;
-}
-
-
-/*
- * Document-class: MatchData
- *
- * <code>MatchData</code> is the type of the special variable <code>$~</code>,
- * and is the type of the object returned by <code>Regexp#match</code> and
- * <code>Regexp#last_match</code>. It encapsulates all the results of a pattern
- * match, results normally accessed through the special variables
- * <code>$&</code>, <code>$'</code>, <code>$`</code>, <code>$1</code>,
- * <code>$2</code>, and so on. <code>Matchdata</code> is also known as
- * <code>MatchingData</code>.
- *
- */
-
-static VALUE rb_cMatch;
-
-static VALUE match_alloc _((VALUE));
-static VALUE
-match_alloc(klass)
- VALUE klass;
-{
- NEWOBJ(match, struct RMatch);
- OBJSETUP(match, klass, T_MATCH);
-
- match->str = 0;
- match->regs = 0;
- match->regs = ALLOC(struct re_registers);
- MEMZERO(match->regs, struct re_registers, 1);
-
- return (VALUE)match;
-}
-
-/* :nodoc: */
-static VALUE
-match_init_copy(obj, orig)
- VALUE obj, orig;
-{
- if (obj == orig) return obj;
-
- if (!rb_obj_is_instance_of(orig, rb_obj_class(obj))) {
- rb_raise(rb_eTypeError, "wrong argument class");
- }
- RMATCH(obj)->str = RMATCH(orig)->str;
- onig_region_free(RMATCH(obj)->regs, 0);
- RMATCH(obj)->regs->allocated = 0;
- onig_region_copy(RMATCH(obj)->regs, RMATCH(orig)->regs);
-
- return obj;
-}
-
-
-/*
- * call-seq:
- * mtch.length => integer
- * mtch.size => integer
- *
- * Returns the number of elements in the match array.
- *
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.length #=> 5
- * m.size #=> 5
- */
-
-static VALUE
-match_size(match)
- VALUE match;
-{
- return INT2FIX(RMATCH(match)->regs->num_regs);
-}
-
-
-/*
- * call-seq:
- * mtch.offset(n) => array
- *
- * Returns a two-element array containing the beginning and ending offsets of
- * the <em>n</em>th match.
- *
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.offset(0) #=> [1, 7]
- * m.offset(4) #=> [6, 7]
- */
-
-static VALUE
-match_offset(match, n)
- VALUE match, n;
-{
- int i = NUM2INT(n);
-
- if (i < 0 || RMATCH(match)->regs->num_regs <= i)
- rb_raise(rb_eIndexError, "index %d out of matches", i);
-
- if (RMATCH(match)->regs->beg[i] < 0)
- return rb_assoc_new(Qnil, Qnil);
-
- return rb_assoc_new(INT2FIX(RMATCH(match)->regs->beg[i]),
- INT2FIX(RMATCH(match)->regs->end[i]));
-}
-
-
-/*
- * call-seq:
- * mtch.begin(n) => integer
- *
- * Returns the offset of the start of the <em>n</em>th element of the match
- * array in the string.
- *
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.begin(0) #=> 1
- * m.begin(2) #=> 2
- */
-
-static VALUE
-match_begin(match, n)
- VALUE match, n;
-{
- int i = NUM2INT(n);
-
- if (i < 0 || RMATCH(match)->regs->num_regs <= i)
- rb_raise(rb_eIndexError, "index %d out of matches", i);
-
- if (RMATCH(match)->regs->beg[i] < 0)
- return Qnil;
-
- return INT2FIX(RMATCH(match)->regs->beg[i]);
-}
-
-
-/*
- * call-seq:
- * mtch.end(n) => integer
- *
- * Returns the offset of the character immediately following the end of the
- * <em>n</em>th element of the match array in the string.
- *
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.end(0) #=> 7
- * m.end(2) #=> 3
- */
-
-static VALUE
-match_end(match, n)
- VALUE match, n;
-{
- int i = NUM2INT(n);
-
- if (i < 0 || RMATCH(match)->regs->num_regs <= i)
- rb_raise(rb_eIndexError, "index %d out of matches", i);
-
- if (RMATCH(match)->regs->beg[i] < 0)
- return Qnil;
-
- return INT2FIX(RMATCH(match)->regs->end[i]);
-}
-
-#define MATCH_BUSY FL_USER2
-
-void
-rb_match_busy(match)
- VALUE match;
-{
- FL_SET(match, MATCH_BUSY);
-}
-
-int ruby_ignorecase;
-static int may_need_recompile;
-
-static void
-rb_reg_prepare_re(re)
- VALUE re;
-{
- int need_recompile = 0;
- int state;
-
- rb_reg_check(re);
- state = FL_TEST(re, REG_CASESTATE);
- /* ignorecase status */
- if (ruby_ignorecase && !state) {
- FL_SET(re, REG_CASESTATE);
- RREGEXP(re)->ptr->options |= ONIG_OPTION_IGNORECASE;
- need_recompile = 1;
- }
- if (!ruby_ignorecase && state) {
- FL_UNSET(re, REG_CASESTATE);
- RREGEXP(re)->ptr->options &= ~ONIG_OPTION_IGNORECASE;
- need_recompile = 1;
- }
-
- if (!FL_TEST(re, KCODE_FIXED) &&
- (RBASIC(re)->flags & KCODE_MASK) != reg_kcode) {
- need_recompile = 1;
- RBASIC(re)->flags &= ~KCODE_MASK;
- RBASIC(re)->flags |= reg_kcode;
- }
-
- if (need_recompile) {
- char err[ONIG_MAX_ERROR_MESSAGE_LEN];
- int r;
- OnigErrorInfo einfo;
- regex_t *reg;
- UChar *pattern;
-
- if (FL_TEST(re, KCODE_FIXED))
- kcode_set_option(re);
- rb_reg_check(re);
- reg = RREGEXP(re)->ptr;
- pattern = ((UChar* )RREGEXP(re)->str);
- r = onig_recompile(reg, pattern, pattern + RREGEXP(re)->len,
- reg->options, onigenc_get_default_encoding(),
- OnigDefaultSyntax, &einfo);
-
- if (r != 0) {
- (void )onig_error_code_to_str((UChar* )err, r, &einfo);
- rb_reg_raise(pattern, RREGEXP(re)->len, err, re, Qfalse);
- }
- }
-}
-
-long
-rb_reg_adjust_startpos(re, str, pos, reverse)
- VALUE re, str;
- long pos, reverse;
-{
- long range;
- OnigEncoding enc;
- UChar *p, *string;
-
- rb_reg_check(re);
- if (may_need_recompile) rb_reg_prepare_re(re);
-
- if (FL_TEST(re, KCODE_FIXED))
- kcode_set_option(re);
- else if (reg_kcode != curr_kcode)
- kcode_reset_option();
-
- if (reverse) {
- range = -pos;
- }
- else {
- range = RSTRING(str)->len - pos;
- }
-
- enc = (RREGEXP(re)->ptr)->enc;
-
- if (pos > 0 && ONIGENC_MBC_MAXLEN(enc) != 1 && pos < RSTRING(str)->len) {
- string = (UChar* )RSTRING(str)->ptr;
-
- if (range > 0) {
- p = onigenc_get_right_adjust_char_head(enc, string, string + pos);
- }
- else {
- p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, string, string + pos);
- }
- return p - string;
- }
-
- return pos;
-}
-
-long
-rb_reg_search(re, str, pos, reverse)
- VALUE re, str;
- long pos, reverse;
-{
- long result;
- VALUE match;
- static struct re_registers regs;
- long range;
-
- if (pos > RSTRING(str)->len || pos < 0) {
- rb_backref_set(Qnil);
- return -1;
- }
-
- rb_reg_check(re);
- if (may_need_recompile) rb_reg_prepare_re(re);
-
- if (FL_TEST(re, KCODE_FIXED))
- kcode_set_option(re);
- else if (reg_kcode != curr_kcode)
- kcode_reset_option();
-
- if (reverse) {
- range = -pos;
- }
- else {
- range = RSTRING(str)->len - pos;
- }
-
- result = onig_search(RREGEXP(re)->ptr,
- (UChar* )(RSTRING(str)->ptr),
- ((UChar* )(RSTRING(str)->ptr) + RSTRING(str)->len),
- ((UChar* )(RSTRING(str)->ptr) + pos),
- ((UChar* )(RSTRING(str)->ptr) + pos + range),
- &regs, ONIG_OPTION_NONE);
-
- if (FL_TEST(re, KCODE_FIXED))
- kcode_reset_option();
-
- if (result < 0) {
- if (result == ONIG_MISMATCH) {
- rb_backref_set(Qnil);
- return result;
- }
- else {
- char err[ONIG_MAX_ERROR_MESSAGE_LEN];
- onig_error_code_to_str((UChar* )err, result);
- rb_reg_raise(RREGEXP(re)->str, RREGEXP(re)->len, err, 0, Qfalse);
- }
- }
-
- match = rb_backref_get();
- if (NIL_P(match) || FL_TEST(match, MATCH_BUSY)) {
- match = match_alloc(rb_cMatch);
- }
- else {
- if (rb_safe_level() >= 3)
- OBJ_TAINT(match);
- else
- FL_UNSET(match, FL_TAINT);
- }
-
- onig_region_copy(RMATCH(match)->regs, &regs);
- RMATCH(match)->str = rb_str_new4(str);
- rb_backref_set(match);
-
- OBJ_INFECT(match, re);
- OBJ_INFECT(match, str);
- return result;
-}
-
-VALUE
-rb_reg_nth_defined(nth, match)
- int nth;
- VALUE match;
-{
- if (NIL_P(match)) return Qnil;
- if (nth >= RMATCH(match)->regs->num_regs) {
- return Qnil;
- }
- if (nth < 0) {
- nth += RMATCH(match)->regs->num_regs;
- if (nth <= 0) return Qnil;
- }
- if (RMATCH(match)->BEG(nth) == -1) return Qfalse;
- return Qtrue;
-}
-
-VALUE
-rb_reg_nth_match(nth, match)
- int nth;
- VALUE match;
-{
- VALUE str;
- long start, end, len;
-
- if (NIL_P(match)) return Qnil;
- if (nth >= RMATCH(match)->regs->num_regs) {
- return Qnil;
- }
- if (nth < 0) {
- nth += RMATCH(match)->regs->num_regs;
- if (nth <= 0) return Qnil;
- }
- start = RMATCH(match)->BEG(nth);
- if (start == -1) return Qnil;
- end = RMATCH(match)->END(nth);
- len = end - start;
- str = rb_str_substr(RMATCH(match)->str, start, len);
- OBJ_INFECT(str, match);
- return str;
-}
-
-VALUE
-rb_reg_last_match(match)
- VALUE match;
-{
- return rb_reg_nth_match(0, match);
-}
-
-
-/*
- * call-seq:
- * mtch.pre_match => str
- *
- * Returns the portion of the original string before the current match.
- * Equivalent to the special variable <code>$`</code>.
- *
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.pre_match #=> "T"
- */
-
-VALUE
-rb_reg_match_pre(match)
- VALUE match;
-{
- VALUE str;
-
- if (NIL_P(match)) return Qnil;
- if (RMATCH(match)->BEG(0) == -1) return Qnil;
- str = rb_str_substr(RMATCH(match)->str, 0, RMATCH(match)->BEG(0));
- if (OBJ_TAINTED(match)) OBJ_TAINT(str);
- return str;
-}
-
-
-/*
- * call-seq:
- * mtch.post_match => str
- *
- * Returns the portion of the original string after the current match.
- * Equivalent to the special variable <code>$'</code>.
- *
- * m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
- * m.post_match #=> ": The Movie"
- */
-
-VALUE
-rb_reg_match_post(match)
- VALUE match;
-{
- VALUE str;
- long pos;
-
- if (NIL_P(match)) return Qnil;
- if (RMATCH(match)->BEG(0) == -1) return Qnil;
- str = RMATCH(match)->str;
- pos = RMATCH(match)->END(0);
- str = rb_str_substr(str, pos, RSTRING(str)->len - pos);
- if (OBJ_TAINTED(match)) OBJ_TAINT(str);
- return str;
-}
-
-VALUE
-rb_reg_match_last(match)
- VALUE match;
-{
- int i;
-
- if (NIL_P(match)) return Qnil;
- if (RMATCH(match)->BEG(0) == -1) return Qnil;
-
- for (i=RMATCH(match)->regs->num_regs-1; RMATCH(match)->BEG(i) == -1 && i > 0; i--)
- ;
- if (i == 0) return Qnil;
- return rb_reg_nth_match(i, match);
-}
-
-static VALUE
-last_match_getter()
-{
- return rb_reg_last_match(rb_backref_get());
-}
-
-static VALUE
-prematch_getter()
-{
- return rb_reg_match_pre(rb_backref_get());
-}
-
-static VALUE
-postmatch_getter()
-{
- return rb_reg_match_post(rb_backref_get());
-}
-
-static VALUE
-last_paren_match_getter()
-{
- return rb_reg_match_last(rb_backref_get());
-}
-
-static VALUE
-match_array(match, start)
- VALUE match;
- int start;
-{
- struct re_registers *regs = RMATCH(match)->regs;
- VALUE ary = rb_ary_new2(regs->num_regs);
- VALUE target = RMATCH(match)->str;
- int i;
- int taint = OBJ_TAINTED(match);
-
- for (i=start; i<regs->num_regs; i++) {
- if (regs->beg[i] == -1) {
- rb_ary_push(ary, Qnil);
- }
- else {
- VALUE str = rb_str_substr(target, regs->beg[i], regs->end[i]-regs->beg[i]);
- if (taint) OBJ_TAINT(str);
- rb_ary_push(ary, str);
- }
- }
- return ary;
-}
-
-
-/* [MG]:FIXME: I put parens around the /.../.match() in the first line of the
- second example to prevent the '*' followed by a '/' from ending the
- comment. */
-
-/*
- * call-seq:
- * mtch.to_a => anArray
- *
- * Returns the array of matches.
- *
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.to_a #=> ["HX1138", "H", "X", "113", "8"]
- *
- * Because <code>to_a</code> is called when expanding
- * <code>*</code><em>variable</em>, there's a useful assignment
- * shortcut for extracting matched fields. This is slightly slower than
- * accessing the fields directly (as an intermediate array is
- * generated).
- *
- * all,f1,f2,f3 = *(/(.)(.)(\d+)(\d)/.match("THX1138."))
- * all #=> "HX1138"
- * f1 #=> "H"
- * f2 #=> "X"
- * f3 #=> "113"
- */
-
-static VALUE
-match_to_a(match)
- VALUE match;
-{
- return match_array(match, 0);
-}
-
-
-/*
- * call-seq:
- * mtch.captures => array
- *
- * Returns the array of captures; equivalent to <code>mtch.to_a[1..-1]</code>.
- *
- * f1,f2,f3,f4 = /(.)(.)(\d+)(\d)/.match("THX1138.").captures
- * f1 #=> "H"
- * f2 #=> "X"
- * f3 #=> "113"
- * f4 #=> "8"
- */
-static VALUE
-match_captures(match)
- VALUE match;
-{
- return match_array(match, 1);
-}
-
-
-/*
- * call-seq:
- * mtch[i] => obj
- * mtch[start, length] => array
- * mtch[range] => array
- *
- * Match Reference---<code>MatchData</code> acts as an array, and may be
- * accessed using the normal array indexing techniques. <i>mtch</i>[0] is
- * equivalent to the special variable <code>$&</code>, and returns the entire
- * matched string. <i>mtch</i>[1], <i>mtch</i>[2], and so on return the values
- * of the matched backreferences (portions of the pattern between parentheses).
- *
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m[0] #=> "HX1138"
- * m[1, 2] #=> ["H", "X"]
- * m[1..3] #=> ["H", "X", "113"]
- * m[-3, 2] #=> ["X", "113"]
- */
-
-static VALUE
-match_aref(argc, argv, match)
- int argc;
- VALUE *argv;
- VALUE match;
-{
- VALUE idx, rest;
-
- rb_scan_args(argc, argv, "11", &idx, &rest);
-
- if (!NIL_P(rest) || !FIXNUM_P(idx) || FIX2INT(idx) < 0) {
- return rb_ary_aref(argc, argv, match_to_a(match));
- }
- return rb_reg_nth_match(FIX2INT(idx), match);
-}
-
-static VALUE match_entry _((VALUE, long));
-static VALUE
-match_entry(match, n)
- VALUE match;
- long n;
-{
- return rb_reg_nth_match(n, match);
-}
-
-
-/*
- * call-seq:
- * mtch.select([index]*) => array
- *
- * Uses each <i>index</i> to access the matching values, returning an array of
- * the corresponding matches.
- *
- * m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
- * m.to_a #=> ["HX1138", "H", "X", "113", "8"]
- * m.select(0, 2, -2) #=> ["HX1138", "X", "113"]
- */
-
-static VALUE
-match_values_at(argc, argv, match)
- int argc;
- VALUE *argv;
- VALUE match;
-{
- return rb_get_values_at(match, RMATCH(match)->regs->num_regs, argc, argv, match_entry);
-}
-
-
-/*
- * call-seq:
- * mtch.select([index]*) => array
- *
- * Uses each <i>index</i> to access the matching values, returning an
- * array of the corresponding matches.
- *
- * m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
- * m.to_a #=> ["HX1138", "H", "X", "113", "8"]
- * m.select(0, 2, -2) #=> ["HX1138", "X", "113"]
- */
-
-static VALUE
-match_select(argc, argv, match)
- int argc;
- VALUE *argv;
- VALUE match;
-{
- if (argc > 0) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
- }
- else {
- struct re_registers *regs = RMATCH(match)->regs;
- VALUE target = RMATCH(match)->str;
- VALUE result = rb_ary_new();
- int i;
- int taint = OBJ_TAINTED(match);
-
- for (i=0; i<regs->num_regs; i++) {
- VALUE str = rb_str_substr(target, regs->beg[i], regs->end[i]-regs->beg[i]);
- if (taint) OBJ_TAINT(str);
- if (RTEST(rb_yield(str))) {
- rb_ary_push(result, str);
- }
- }
- return result;
- }
-}
-
-
-/*
- * call-seq:
- * mtch.to_s => str
- *
- * Returns the entire matched string.
- *
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.to_s #=> "HX1138"
- */
-
-static VALUE
-match_to_s(match)
- VALUE match;
-{
- VALUE str = rb_reg_last_match(match);
-
- if (NIL_P(str)) str = rb_str_new(0,0);
- if (OBJ_TAINTED(match)) OBJ_TAINT(str);
- if (OBJ_TAINTED(RMATCH(match)->str)) OBJ_TAINT(str);
- return str;
-}
-
-
-/*
- * call-seq:
- * mtch.string => str
- *
- * Returns a frozen copy of the string passed in to <code>match</code>.
- *
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.string #=> "THX1138."
- */
-
-static VALUE
-match_string(match)
- VALUE match;
-{
- return RMATCH(match)->str; /* str is frozen */
-}
-
-VALUE rb_cRegexp;
-
-static void
-rb_reg_initialize(obj, s, len, options, ce)
- VALUE obj;
- const char *s;
- long len;
- int options; /* CASEFOLD = 1 */
- /* EXTENDED = 2 */
- /* MULTILINE = 4 */
- /* CODE_NONE = 16 */
- /* CODE_EUC = 32 */
- /* CODE_SJIS = 48 */
- /* CODE_UTF8 = 64 */
- int ce; /* call rb_compile_error() */
-{
- struct RRegexp *re = RREGEXP(obj);
-
- if (re->ptr) onig_free(re->ptr);
- if (re->str) free(re->str);
- re->ptr = 0;
- re->str = 0;
-
- switch (options & ~0xf) {
- case 0:
- default:
- FL_SET(re, reg_kcode);
- break;
- case 16:
- kcode_none(re);
- break;
- case 32:
- kcode_euc(re);
- break;
- case 48:
- kcode_sjis(re);
- break;
- case 64:
- kcode_utf8(re);
- break;
- }
-
- if (options & ~0xf) {
- kcode_set_option((VALUE)re);
- }
- if (ruby_ignorecase) {
- options |= ONIG_OPTION_IGNORECASE;
- FL_SET(re, REG_CASESTATE);
- }
- re->ptr = make_regexp(s, len, options & 0xf, ce);
- re->str = ALLOC_N(char, len+1);
- memcpy(re->str, s, len);
- re->str[len] = '\0';
- re->len = len;
- if (options & ~0xf) {
- kcode_reset_option();
- }
-}
-
-static VALUE rb_reg_s_alloc _((VALUE));
-static VALUE
-rb_reg_s_alloc(klass)
- VALUE klass;
-{
- NEWOBJ(re, struct RRegexp);
- OBJSETUP(re, klass, T_REGEXP);
-
- re->ptr = 0;
- re->len = 0;
- re->str = 0;
-
- return (VALUE)re;
-}
-
-VALUE
-rb_reg_new(s, len, options)
- const char *s;
- long len;
- int options;
-{
- VALUE re = rb_reg_s_alloc(rb_cRegexp);
-
- rb_reg_initialize(re, s, len, options, Qfalse);
- return (VALUE)re;
-}
-
-VALUE
-rb_reg_compile(s, len, options)
- const char *s;
- long len;
- int options;
-{
- VALUE re = rb_reg_s_alloc(rb_cRegexp);
-
- rb_reg_initialize(re, s, len, options, Qtrue);
- return (VALUE)re;
-}
-
-static int case_cache;
-static int kcode_cache;
-static VALUE reg_cache;
-
-VALUE
-rb_reg_regcomp(str)
- VALUE str;
-{
- if (reg_cache && RREGEXP(reg_cache)->len == RSTRING(str)->len
- && case_cache == ruby_ignorecase
- && kcode_cache == reg_kcode
- && memcmp(RREGEXP(reg_cache)->str, RSTRING(str)->ptr, RSTRING(str)->len) == 0)
- return reg_cache;
-
- case_cache = ruby_ignorecase;
- kcode_cache = reg_kcode;
- return reg_cache = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
- ruby_ignorecase);
-}
-
-static int
-rb_reg_cur_kcode(re)
- VALUE re;
-{
- if (FL_TEST(re, KCODE_FIXED)) {
- return RBASIC(re)->flags & KCODE_MASK;
- }
- return 0;
-}
-
-/*
- * call-seq:
- * rxp.hash => fixnum
- *
- * Produce a hash based on the text and options of this regular expression.
- */
-
-static VALUE
-rb_reg_hash(re)
- VALUE re;
-{
- int hashval, len;
- char *p;
-
- rb_reg_check(re);
- hashval = RREGEXP(re)->ptr->options;
- len = RREGEXP(re)->len;
- p = RREGEXP(re)->str;
- while (len--) {
- hashval = hashval * 33 + *p++;
- }
- hashval = hashval + (hashval>>5);
-
- return INT2FIX(hashval);
-}
-
-
-/*
- * call-seq:
- * rxp == other_rxp => true or false
- * rxp.eql?(other_rxp) => true or false
- *
- * Equality---Two regexps are equal if their patterns are identical, they have
- * the same character set code, and their <code>casefold?</code> values are the
- * same.
- *
- * /abc/ == /abc/x #=> false
- * /abc/ == /abc/i #=> false
- * /abc/u == /abc/n #=> false
- */
-
-static VALUE
-rb_reg_equal(re1, re2)
- VALUE re1, re2;
-{
- if (re1 == re2) return Qtrue;
- if (TYPE(re2) != T_REGEXP) return Qfalse;
- rb_reg_check(re1); rb_reg_check(re2);
- if (RREGEXP(re1)->len != RREGEXP(re2)->len) return Qfalse;
- if (memcmp(RREGEXP(re1)->str, RREGEXP(re2)->str, RREGEXP(re1)->len) == 0 &&
- rb_reg_cur_kcode(re1) == rb_reg_cur_kcode(re2) &&
- RREGEXP(re1)->ptr->options == RREGEXP(re2)->ptr->options) {
- return Qtrue;
- }
- return Qfalse;
-}
-
-static VALUE
-rb_reg_match_pos(re, str, pos)
- VALUE re, str;
- long pos;
-{
- if (NIL_P(str)) {
- rb_backref_set(Qnil);
- return Qnil;
- }
- StringValue(str);
- if (pos != 0) {
- if (pos < 0) {
- pos += RSTRING(str)->len;
- if (pos < 0) {
- return Qnil;
- }
- }
- pos = rb_reg_adjust_startpos(re, str, pos, 0);
- }
- pos = rb_reg_search(re, str, pos, 0);
- if (pos < 0) {
- return Qnil;
- }
- return LONG2FIX(pos);
-}
-
-/*
- * call-seq:
- * rxp =~ str => integer or nil
- *
- * Match---Matches <i>rxp</i> against <i>str</i>.
- *
- * /at/ =~ "input data" #=> 7
- */
-
-VALUE
-rb_reg_match(re, str)
- VALUE re, str;
-{
- return rb_reg_match_pos(re, str, 0);
-}
-
-/*
- * call-seq:
- * rxp === str => true or false
- *
- * Case Equality---Synonym for <code>Regexp#=~</code> used in case statements.
- *
- * a = "HELLO"
- * case a
- * when /^[a-z]*$/; print "Lower case\n"
- * when /^[A-Z]*$/; print "Upper case\n"
- * else; print "Mixed case\n"
- * end
- *
- * <em>produces:</em>
- *
- * Upper case
- */
-
-VALUE
-rb_reg_eqq(re, str)
- VALUE re, str;
-{
- long start;
-
- if (TYPE(str) != T_STRING) {
- str = rb_check_string_type(str);
- if (NIL_P(str)) {
- rb_backref_set(Qnil);
- return Qfalse;
- }
- }
- StringValue(str);
- start = rb_reg_search(re, str, 0, 0);
- if (start < 0) {
- return Qfalse;
- }
- return Qtrue;
-}
-
-
-/*
- * call-seq:
- * ~ rxp => integer or nil
- *
- * Match---Matches <i>rxp</i> against the contents of <code>$_</code>.
- * Equivalent to <code><i>rxp</i> =~ $_</code>.
- *
- * $_ = "input data"
- * ~ /at/ #=> 7
- */
-
-VALUE
-rb_reg_match2(re)
- VALUE re;
-{
- long start;
- VALUE line = rb_lastline_get();
-
- if (TYPE(line) != T_STRING) {
- rb_backref_set(Qnil);
- return Qnil;
- }
-
- start = rb_reg_search(re, line, 0, 0);
- if (start < 0) {
- return Qnil;
- }
- return LONG2FIX(start);
-}
-
-
-/*
- * call-seq:
- * rxp.match(str) => matchdata or nil
- * rxp.match(str,pos) => matchdata or nil
- *
- * Returns a <code>MatchData</code> object describing the match, or
- * <code>nil</code> if there was no match. This is equivalent to retrieving the
- * value of the special variable <code>$~</code> following a normal match.
- * If the second parameter is present, it specifies the position in the string
- * to begin the search.
- *
- * /(.)(.)(.)/.match("abc")[2] #=> "b"
- * /(.)(.)/.match("abc", 1)[2] #=> "c"
- */
-
-static VALUE
-rb_reg_match_m(argc, argv, re)
- int argc;
- VALUE *argv;
- VALUE re;
-{
- VALUE result, str, initpos;
- long pos;
-
- if (rb_scan_args(argc, argv, "11", &str, &initpos) == 2) {
- pos = NUM2LONG(initpos);
- }
- else {
- pos = 0;
- }
-
- result = rb_reg_match_pos(re, str, pos);
- if (NIL_P(result)) {
- rb_backref_set(Qnil);
- return Qnil;
- }
- result = rb_backref_get();
- rb_match_busy(result);
- return result;
-}
-
-/*
- * Document-method: compile
- *
- * Synonym for <code>Regexp.new</code>
- */
-
-
-/*
- * call-seq:
- * Regexp.new(string [, options [, lang]]) => regexp
- * Regexp.new(regexp) => regexp
- * Regexp.compile(string [, options [, lang]]) => regexp
- * Regexp.compile(regexp) => regexp
- *
- * Constructs a new regular expression from <i>pattern</i>, which can be either
- * a <code>String</code> or a <code>Regexp</code> (in which case that regexp's
- * options are propagated, and new options may not be specified (a change as of
- * Ruby 1.8). If <i>options</i> is a <code>Fixnum</code>, it should be one or
- * more of the constants <code>Regexp::EXTENDED</code>,
- * <code>Regexp::IGNORECASE</code>, and <code>Regexp::MULTILINE</code>,
- * <em>or</em>-ed together. Otherwise, if <i>options</i> is not
- * <code>nil</code>, the regexp will be case insensitive. The <i>lang</i>
- * parameter enables multibyte support for the regexp: `n', `N' = none, `e',
- * `E' = EUC, `s', `S' = SJIS, `u', `U' = UTF-8.
- *
- * r1 = Regexp.new('^a-z+:\\s+\w+') #=> /^a-z+:\s+\w+/
- * r2 = Regexp.new('cat', true) #=> /cat/i
- * r3 = Regexp.new('dog', Regexp::EXTENDED) #=> /dog/x
- * r4 = Regexp.new(r2) #=> /cat/i
- */
-
-static VALUE
-rb_reg_initialize_m(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- const char *s;
- long len;
- int flags = 0;
-
- rb_check_frozen(self);
- if (argc == 0 || argc > 3) {
- rb_raise(rb_eArgError, "wrong number of arguments");
- }
- if (TYPE(argv[0]) == T_REGEXP) {
- if (argc > 1) {
- rb_warn("flags%s ignored", (argc == 3) ? " and encoding": "");
- }
- rb_reg_check(argv[0]);
- flags = RREGEXP(argv[0])->ptr->options & 0xf;
- if (FL_TEST(argv[0], KCODE_FIXED)) {
- switch (RBASIC(argv[0])->flags & KCODE_MASK) {
- case KCODE_NONE:
- flags |= 16;
- break;
- case KCODE_EUC:
- flags |= 32;
- break;
- case KCODE_SJIS:
- flags |= 48;
- break;
- case KCODE_UTF8:
- flags |= 64;
- break;
- default:
- break;
- }
- }
- s = RREGEXP(argv[0])->str;
- len = RREGEXP(argv[0])->len;
- }
- else {
- if (argc >= 2) {
- if (FIXNUM_P(argv[1])) flags = FIX2INT(argv[1]);
- else if (RTEST(argv[1])) flags = ONIG_OPTION_IGNORECASE;
- }
- if (argc == 3 && !NIL_P(argv[2])) {
- char *kcode = StringValuePtr(argv[2]);
-
- flags &= ~0x70;
- switch (kcode[0]) {
- case 'n': case 'N':
- flags |= 16;
- break;
- case 'e': case 'E':
- flags |= 32;
- break;
- case 's': case 'S':
- flags |= 48;
- break;
- case 'u': case 'U':
- flags |= 64;
- break;
- default:
- break;
- }
- }
- s = StringValuePtr(argv[0]);
- len = RSTRING(argv[0])->len;
- }
- rb_reg_initialize(self, s, len, flags, Qfalse);
- return self;
-}
-
-VALUE
-rb_reg_quote(str)
- VALUE str;
-{
- char *s, *send, *t;
- VALUE tmp;
- int c;
-
- s = RSTRING(str)->ptr;
- send = s + RSTRING(str)->len;
- for (; s < send; s++) {
- c = *s;
- if (ismbchar(*s)) {
- int n = mbclen(*s);
-
- while (n-- && s < send)
- s++;
- s--;
- continue;
- }
- switch (c) {
- case '[': case ']': case '{': case '}':
- case '(': case ')': case '|': case '-':
- case '*': case '.': case '\\':
- case '?': case '+': case '^': case '$':
- case ' ': case '#':
- case '\t': case '\f': case '\n': case '\r':
- goto meta_found;
- }
- }
- return str;
-
- meta_found:
- tmp = rb_str_new(0, RSTRING(str)->len*2);
- t = RSTRING(tmp)->ptr;
- /* copy upto metacharacter */
- memcpy(t, RSTRING(str)->ptr, s - RSTRING(str)->ptr);
- t += s - RSTRING(str)->ptr;
-
- for (; s < send; s++) {
- c = *s;
- if (ismbchar(*s)) {
- int n = mbclen(*s);
-
- while (n-- && s < send)
- *t++ = *s++;
- s--;
- continue;
- }
- switch (c) {
- case '[': case ']': case '{': case '}':
- case '(': case ')': case '|': case '-':
- case '*': case '.': case '\\':
- case '?': case '+': case '^': case '$':
- case '#':
- *t++ = '\\';
- break;
- case ' ':
- *t++ = '\\';
- *t++ = ' ';
- continue;
- case '\t':
- *t++ = '\\';
- *t++ = 't';
- continue;
- case '\n':
- *t++ = '\\';
- *t++ = 'n';
- continue;
- case '\r':
- *t++ = '\\';
- *t++ = 'r';
- continue;
- case '\f':
- *t++ = '\\';
- *t++ = 'f';
- continue;
- }
- *t++ = c;
- }
- rb_str_resize(tmp, t - RSTRING(tmp)->ptr);
- OBJ_INFECT(tmp, str);
- return tmp;
-}
-
-
-/*
- * call-seq:
- * Regexp.escape(str) => a_str
- * Regexp.quote(str) => a_str
- *
- * Escapes any characters that would have special meaning in a regular
- * expression. Returns a new escaped string, or self if no characters are
- * escaped. For any string,
- * <code>Regexp.escape(<i>str</i>)=~<i>str</i></code> will be true.
- *
- * Regexp.escape('\\*?{}.') #=> \\\\\*\?\{\}\.
- */
-
-static VALUE
-rb_reg_s_quote(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE str, kcode;
- int kcode_saved = reg_kcode;
-
- rb_scan_args(argc, argv, "11", &str, &kcode);
- if (!NIL_P(kcode)) {
- rb_set_kcode(StringValuePtr(kcode));
- curr_kcode = reg_kcode;
- reg_kcode = kcode_saved;
- }
- StringValue(str);
- str = rb_reg_quote(str);
- kcode_reset_option();
- return str;
-}
-
-int
-rb_kcode()
-{
- switch (reg_kcode) {
- case KCODE_EUC:
- return MBCTYPE_EUC;
- case KCODE_SJIS:
- return MBCTYPE_SJIS;
- case KCODE_UTF8:
- return MBCTYPE_UTF8;
- case KCODE_NONE:
- return MBCTYPE_ASCII;
- }
- rb_bug("wrong reg_kcode value (0x%x)", reg_kcode);
-}
-
-static int
-rb_reg_get_kcode(re)
- VALUE re;
-{
- switch (RBASIC(re)->flags & KCODE_MASK) {
- case KCODE_NONE:
- return 16;
- case KCODE_EUC:
- return 32;
- case KCODE_SJIS:
- return 48;
- case KCODE_UTF8:
- return 64;
- default:
- return 0;
- }
-}
-
-int
-rb_reg_options(re)
- VALUE re;
-{
- int options;
-
- rb_reg_check(re);
- options = RREGEXP(re)->ptr->options &
- (ONIG_OPTION_IGNORECASE|ONIG_OPTION_MULTILINE|ONIG_OPTION_EXTEND);
- if (FL_TEST(re, KCODE_FIXED)) {
- options |= rb_reg_get_kcode(re);
- }
- return options;
-}
-
-
-/*
- * call-seq:
- * Regexp.union([pattern]*) => new_str
- *
- * Return a <code>Regexp</code> object that is the union of the given
- * <em>pattern</em>s, i.e., will match any of its parts. The <em>pattern</em>s
- * can be Regexp objects, in which case their options will be preserved, or
- * Strings. If no arguments are given, returns <code>/(?!)/</code>.
- *
- * Regexp.union #=> /(?!)/
- * Regexp.union("penzance") #=> /penzance/
- * Regexp.union("skiing", "sledding") #=> /skiing|sledding/
- * Regexp.union(/dogs/, /cats/i) #=> /(?-mix:dogs)|(?i-mx:cats)/
- */
-static VALUE
-rb_reg_s_union(argc, argv)
- int argc;
- VALUE *argv;
-{
- if (argc == 0) {
- VALUE args[1];
- args[0] = rb_str_new2("(?!)");
- return rb_class_new_instance(1, args, rb_cRegexp);
- }
- else if (argc == 1) {
- VALUE v;
- v = rb_check_convert_type(argv[0], T_REGEXP, "Regexp", "to_regexp");
- if (!NIL_P(v))
- return v;
- else {
- VALUE args[1];
- args[0] = rb_reg_s_quote(argc, argv);
- return rb_class_new_instance(1, args, rb_cRegexp);
- }
- }
- else {
- int i, kcode = -1;
- VALUE kcode_re = Qnil;
- VALUE source = rb_str_buf_new(0);
- VALUE args[3];
- for (i = 0; i < argc; i++) {
- volatile VALUE v;
- if (0 < i)
- rb_str_buf_cat2(source, "|");
- v = rb_check_convert_type(argv[i], T_REGEXP, "Regexp", "to_regexp");
- if (!NIL_P(v)) {
- if (FL_TEST(v, KCODE_FIXED)) {
- if (kcode == -1) {
- kcode_re = v;
- kcode = RBASIC(v)->flags & KCODE_MASK;
- }
- else if ((RBASIC(v)->flags & KCODE_MASK) != kcode) {
- volatile VALUE str1, str2;
- str1 = rb_inspect(kcode_re);
- str2 = rb_inspect(v);
- rb_raise(rb_eArgError, "mixed kcode: %s and %s",
- RSTRING(str1)->ptr, RSTRING(str2)->ptr);
- }
- }
- v = rb_reg_to_s(v);
- }
- else {
- args[0] = argv[i];
- v = rb_reg_s_quote(1, args);
- }
- rb_str_buf_append(source, v);
- }
- args[0] = source;
- args[1] = Qnil;
- switch (kcode) {
- case -1:
- args[2] = Qnil;
- break;
- case KCODE_NONE:
- args[2] = rb_str_new2("n");
- break;
- case KCODE_EUC:
- args[2] = rb_str_new2("e");
- break;
- case KCODE_SJIS:
- args[2] = rb_str_new2("s");
- break;
- case KCODE_UTF8:
- args[2] = rb_str_new2("u");
- break;
- }
- return rb_class_new_instance(3, args, rb_cRegexp);
- }
-}
-
-/* :nodoc: */
-static VALUE
-rb_reg_init_copy(copy, re)
- VALUE copy, re;
-{
- if (copy == re) return copy;
- rb_check_frozen(copy);
- /* need better argument type check */
- if (!rb_obj_is_instance_of(re, rb_obj_class(copy))) {
- rb_raise(rb_eTypeError, "wrong argument type");
- }
- rb_reg_check(re);
- rb_reg_initialize(copy, RREGEXP(re)->str, RREGEXP(re)->len,
- rb_reg_options(re), Qfalse);
- return copy;
-}
-
-VALUE
-rb_reg_regsub(str, src, regs)
- VALUE str, src;
- struct re_registers *regs;
-{
- VALUE val = 0;
- char *p, *s, *e;
- unsigned char uc;
- int no;
-
-
- p = s = RSTRING(str)->ptr;
- e = s + RSTRING(str)->len;
-
- while (s < e) {
- char *ss = s;
-
- uc = (unsigned char)*s++;
- if (ismbchar(uc)) {
- s += mbclen(uc) - 1;
- continue;
- }
- if (uc != '\\' || s == e) continue;
-
- if (!val) {
- val = rb_str_buf_new(ss-p);
- rb_str_buf_cat(val, p, ss-p);
- }
- else {
- rb_str_buf_cat(val, p, ss-p);
- }
-
- uc = (unsigned char)*s++;
- p = s;
- switch (uc) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- no = uc - '0';
- break;
- case '&':
- no = 0;
- break;
-
- case '`':
- rb_str_buf_cat(val, RSTRING(src)->ptr, BEG(0));
- continue;
-
- case '\'':
- rb_str_buf_cat(val, RSTRING(src)->ptr+END(0), RSTRING(src)->len-END(0));
- continue;
-
- case '+':
- no = regs->num_regs-1;
- while (BEG(no) == -1 && no > 0) no--;
- if (no == 0) continue;
- break;
-
- case '\\':
- rb_str_buf_cat(val, s-1, 1);
- continue;
-
- default:
- rb_str_buf_cat(val, s-2, 2);
- continue;
- }
-
- if (no >= 0) {
- if (no >= regs->num_regs) continue;
- if (BEG(no) == -1) continue;
- rb_str_buf_cat(val, RSTRING(src)->ptr+BEG(no), END(no)-BEG(no));
- }
- }
-
- if (p < e) {
- if (!val) {
- val = rb_str_buf_new(e-p);
- rb_str_buf_cat(val, p, e-p);
- }
- else {
- rb_str_buf_cat(val, p, e-p);
- }
- }
- if (!val) return str;
-
- return val;
-}
-
-const char*
-rb_get_kcode()
-{
- switch (reg_kcode) {
- case KCODE_SJIS:
- return "SJIS";
- case KCODE_EUC:
- return "EUC";
- case KCODE_UTF8:
- return "UTF8";
- default:
- return "NONE";
- }
-}
-
-static VALUE
-kcode_getter()
-{
- return rb_str_new2(rb_get_kcode());
-}
-
-void
-rb_set_kcode(code)
- const char *code;
-{
- if (code == 0) goto set_no_conversion;
-
- switch (code[0]) {
- case 'E':
- case 'e':
- reg_kcode = KCODE_EUC;
- onigenc_set_default_encoding(ONIG_ENCODING_EUC_JP);
- break;
- case 'S':
- case 's':
- reg_kcode = KCODE_SJIS;
- onigenc_set_default_encoding(ONIG_ENCODING_SJIS);
- break;
- case 'U':
- case 'u':
- reg_kcode = KCODE_UTF8;
- onigenc_set_default_encoding(ONIG_ENCODING_UTF8);
- break;
- default:
- case 'N':
- case 'n':
- case 'A':
- case 'a':
- set_no_conversion:
- reg_kcode = KCODE_NONE;
- onigenc_set_default_encoding(ONIG_ENCODING_ASCII);
- break;
- }
-}
-
-static void
-kcode_setter(val)
- VALUE val;
-{
- may_need_recompile = 1;
- rb_set_kcode(StringValuePtr(val));
-}
-
-static VALUE
-ignorecase_getter()
-{
- return ruby_ignorecase?Qtrue:Qfalse;
-}
-
-static void
-ignorecase_setter(val, id)
- VALUE val;
- ID id;
-{
- rb_warn("modifying %s is deprecated", rb_id2name(id));
- may_need_recompile = 1;
- ruby_ignorecase = RTEST(val);
-}
-
-static VALUE
-match_getter()
-{
- VALUE match = rb_backref_get();
-
- if (NIL_P(match)) return Qnil;
- rb_match_busy(match);
- return match;
-}
-
-static void
-match_setter(val)
- VALUE val;
-{
- if (!NIL_P(val)) {
- Check_Type(val, T_MATCH);
- }
- rb_backref_set(val);
-}
-
-/*
- * call-seq:
- * Regexp.last_match => matchdata
- * Regexp.last_match(fixnum) => str
- *
- * The first form returns the <code>MatchData</code> object generated by the
- * last successful pattern match. Equivalent to reading the global variable
- * <code>$~</code>. The second form returns the nth field in this
- * <code>MatchData</code> object.
- *
- * /c(.)t/ =~ 'cat' #=> 0
- * Regexp.last_match #=> #<MatchData:0x401b3d30>
- * Regexp.last_match(0) #=> "cat"
- * Regexp.last_match(1) #=> "a"
- * Regexp.last_match(2) #=> nil
- */
-
-static VALUE
-rb_reg_s_last_match(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE nth;
-
- if (rb_scan_args(argc, argv, "01", &nth) == 1) {
- return rb_reg_nth_match(NUM2INT(nth), rb_backref_get());
- }
- return match_getter();
-}
-
-
-/*
- * Document-class: Regexp
- *
- * A <code>Regexp</code> holds a regular expression, used to match a pattern
- * against strings. Regexps are created using the <code>/.../</code> and
- * <code>%r{...}</code> literals, and by the <code>Regexp::new</code>
- * constructor.
- *
- */
-
-void
-Init_Regexp()
-{
- rb_eRegexpError = rb_define_class("RegexpError", rb_eStandardError);
-
- onigenc_set_default_caseconv_table((UChar* )casetable);
-#if DEFAULT_KCODE == KCODE_EUC
- onigenc_set_default_encoding(ONIG_ENCODING_EUC_JP);
-#else
-#if DEFAULT_KCODE == KCODE_SJIS
- onigenc_set_default_encoding(ONIG_ENCODING_SJIS);
-#else
-#if DEFAULT_KCODE == KCODE_UTF8
- onigenc_set_default_encoding(ONIG_ENCODING_UTF8);
-#else
- onigenc_set_default_encoding(ONIG_ENCODING_ASCII);
-#endif
-#endif
-#endif
-
- rb_define_virtual_variable("$~", match_getter, match_setter);
- rb_define_virtual_variable("$&", last_match_getter, 0);
- rb_define_virtual_variable("$`", prematch_getter, 0);
- rb_define_virtual_variable("$'", postmatch_getter, 0);
- rb_define_virtual_variable("$+", last_paren_match_getter, 0);
-
- rb_define_virtual_variable("$=", ignorecase_getter, ignorecase_setter);
- rb_define_virtual_variable("$KCODE", kcode_getter, kcode_setter);
- rb_define_virtual_variable("$-K", kcode_getter, kcode_setter);
-
- rb_cRegexp = rb_define_class("Regexp", rb_cObject);
- rb_define_alloc_func(rb_cRegexp, rb_reg_s_alloc);
- rb_define_singleton_method(rb_cRegexp, "compile", rb_class_new_instance, -1);
- rb_define_singleton_method(rb_cRegexp, "quote", rb_reg_s_quote, -1);
- rb_define_singleton_method(rb_cRegexp, "escape", rb_reg_s_quote, -1);
- rb_define_singleton_method(rb_cRegexp, "union", rb_reg_s_union, -1);
- rb_define_singleton_method(rb_cRegexp, "last_match", rb_reg_s_last_match, -1);
-
- rb_define_method(rb_cRegexp, "initialize", rb_reg_initialize_m, -1);
- rb_define_method(rb_cRegexp, "initialize_copy", rb_reg_init_copy, 1);
- rb_define_method(rb_cRegexp, "hash", rb_reg_hash, 0);
- rb_define_method(rb_cRegexp, "eql?", rb_reg_equal, 1);
- rb_define_method(rb_cRegexp, "==", rb_reg_equal, 1);
- rb_define_method(rb_cRegexp, "=~", rb_reg_match, 1);
- rb_define_method(rb_cRegexp, "===", rb_reg_eqq, 1);
- rb_define_method(rb_cRegexp, "~", rb_reg_match2, 0);
- rb_define_method(rb_cRegexp, "match", rb_reg_match_m, -1);
- rb_define_method(rb_cRegexp, "to_s", rb_reg_to_s, 0);
- rb_define_method(rb_cRegexp, "inspect", rb_reg_inspect, 0);
- rb_define_method(rb_cRegexp, "source", rb_reg_source, 0);
- rb_define_method(rb_cRegexp, "casefold?", rb_reg_casefold_p, 0);
- rb_define_method(rb_cRegexp, "options", rb_reg_options_m, 0);
- rb_define_method(rb_cRegexp, "kcode", rb_reg_kcode_m, 0);
-
- rb_define_const(rb_cRegexp, "IGNORECASE", INT2FIX(ONIG_OPTION_IGNORECASE));
- rb_define_const(rb_cRegexp, "EXTENDED", INT2FIX(ONIG_OPTION_EXTEND));
- rb_define_const(rb_cRegexp, "MULTILINE", INT2FIX(ONIG_OPTION_MULTILINE));
-
- rb_global_variable(&reg_cache);
-
- rb_cMatch = rb_define_class("MatchData", rb_cObject);
- rb_define_global_const("MatchingData", rb_cMatch);
- rb_define_alloc_func(rb_cMatch, match_alloc);
- rb_undef_method(CLASS_OF(rb_cMatch), "new");
-
- rb_define_method(rb_cMatch, "initialize_copy", match_init_copy, 1);
- rb_define_method(rb_cMatch, "size", match_size, 0);
- rb_define_method(rb_cMatch, "length", match_size, 0);
- rb_define_method(rb_cMatch, "offset", match_offset, 1);
- rb_define_method(rb_cMatch, "begin", match_begin, 1);
- rb_define_method(rb_cMatch, "end", match_end, 1);
- rb_define_method(rb_cMatch, "to_a", match_to_a, 0);
- rb_define_method(rb_cMatch, "[]", match_aref, -1);
- rb_define_method(rb_cMatch, "captures", match_captures, 0);
- rb_define_method(rb_cMatch, "select", match_select, -1);
- rb_define_method(rb_cMatch, "values_at", match_values_at, -1);
- rb_define_method(rb_cMatch, "pre_match", rb_reg_match_pre, 0);
- rb_define_method(rb_cMatch, "post_match", rb_reg_match_post, 0);
- rb_define_method(rb_cMatch, "to_s", match_to_s, 0);
- rb_define_method(rb_cMatch, "inspect", rb_any_to_s, 0); /* in object.c */
- rb_define_method(rb_cMatch, "string", match_string, 0);
-}
-/**********************************************************************
- regcomp.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 "regparse.h"
-
-OnigAmbigType OnigDefaultAmbigFlag =
- (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE |
- ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE);
-
-extern OnigAmbigType
-onig_get_default_ambig_flag()
-{
- return OnigDefaultAmbigFlag;
-}
-
-extern int
-onig_set_default_ambig_flag(OnigAmbigType ambig_flag)
-{
- OnigDefaultAmbigFlag = ambig_flag;
- return 0;
-}
-
-
-#ifndef PLATFORM_UNALIGNED_WORD_ACCESS
-static unsigned char PadBuf[WORD_ALIGNMENT_SIZE];
-#endif
-
-static UChar*
-k_strdup(UChar* s, UChar* end)
-{
- int len = end - s;
-
- if (len > 0) {
- UChar* r = (UChar* )xmalloc(len + 1);
- CHECK_NULL_RETURN(r);
- xmemcpy(r, s, len);
- r[len] = (UChar )0;
- return r;
- }
- else return NULL;
-}
-
-/*
- Caution: node should not be a string node.
- (s and end member address break)
-*/
-static void
-swap_node(Node* a, Node* b)
-{
- Node c;
- c = *a; *a = *b; *b = c;
-}
-
-static OnigDistance
-distance_add(OnigDistance d1, OnigDistance d2)
-{
- if (d1 == ONIG_INFINITE_DISTANCE || d2 == ONIG_INFINITE_DISTANCE)
- return ONIG_INFINITE_DISTANCE;
- else {
- if (d1 <= ONIG_INFINITE_DISTANCE - d2) return d1 + d2;
- else return ONIG_INFINITE_DISTANCE;
- }
-}
-
-static OnigDistance
-distance_multiply(OnigDistance d, int m)
-{
- if (m == 0) return 0;
-
- if (d < ONIG_INFINITE_DISTANCE / m)
- return d * m;
- else
- return ONIG_INFINITE_DISTANCE;
-}
-
-static int
-bitset_is_empty(BitSetRef bs)
-{
- int i;
- for (i = 0; i < BITSET_SIZE; i++) {
- if (bs[i] != 0) return 0;
- }
- return 1;
-}
-
-#ifdef ONIG_DEBUG
-static int
-bitset_on_num(BitSetRef bs)
-{
- int i, n;
-
- n = 0;
- for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
- if (BITSET_AT(bs, i)) n++;
- }
- return n;
-}
-#endif
-
-extern int
-onig_bbuf_init(BBuf* buf, int size)
-{
- buf->p = (UChar* )xmalloc(size);
- if (IS_NULL(buf->p)) return(ONIGERR_MEMORY);
-
- buf->alloc = size;
- buf->used = 0;
- return 0;
-}
-
-
-#ifdef USE_SUBEXP_CALL
-
-static int
-unset_addr_list_init(UnsetAddrList* uslist, int size)
-{
- UnsetAddr* p;
-
- p = (UnsetAddr* )xmalloc(sizeof(UnsetAddr)* size);
- CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY);
- uslist->num = 0;
- uslist->alloc = size;
- uslist->us = p;
- return 0;
-}
-
-static void
-unset_addr_list_end(UnsetAddrList* uslist)
-{
- if (IS_NOT_NULL(uslist->us))
- xfree(uslist->us);
-}
-
-static int
-unset_addr_list_add(UnsetAddrList* uslist, int offset, struct _Node* node)
-{
- UnsetAddr* p;
- int size;
-
- if (uslist->num >= uslist->alloc) {
- size = uslist->alloc * 2;
- p = (UnsetAddr* )xrealloc(uslist->us, sizeof(UnsetAddr) * size);
- CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY);
- uslist->alloc = size;
- uslist->us = p;
- }
-
- uslist->us[uslist->num].offset = offset;
- uslist->us[uslist->num].target = node;
- uslist->num++;
- return 0;
-}
-#endif /* USE_SUBEXP_CALL */
-
-
-static int
-add_opcode(regex_t* reg, int opcode)
-{
- BBUF_ADD1(reg, opcode);
- return 0;
-}
-
-static int
-add_rel_addr(regex_t* reg, int addr)
-{
- RelAddrType ra = (RelAddrType )addr;
-
- BBUF_ADD(reg, &ra, SIZE_RELADDR);
- return 0;
-}
-
-static int
-add_abs_addr(regex_t* reg, int addr)
-{
- AbsAddrType ra = (AbsAddrType )addr;
-
- BBUF_ADD(reg, &ra, SIZE_ABSADDR);
- return 0;
-}
-
-static int
-add_length(regex_t* reg, int len)
-{
- LengthType l = (LengthType )len;
-
- BBUF_ADD(reg, &l, SIZE_LENGTH);
- return 0;
-}
-
-static int
-add_mem_num(regex_t* reg, int num)
-{
- MemNumType n = (MemNumType )num;
-
- BBUF_ADD(reg, &n, SIZE_MEMNUM);
- return 0;
-}
-
-static int
-add_pointer(regex_t* reg, void* addr)
-{
- PointerType ptr = (PointerType )addr;
-
- BBUF_ADD(reg, &ptr, SIZE_POINTER);
- return 0;
-}
-
-static int
-add_option(regex_t* reg, OnigOptionType option)
-{
- BBUF_ADD(reg, &option, SIZE_OPTION);
- return 0;
-}
-
-static int
-add_opcode_rel_addr(regex_t* reg, int opcode, int addr)
-{
- int r;
-
- r = add_opcode(reg, opcode);
- if (r) return r;
- r = add_rel_addr(reg, addr);
- return r;
-}
-
-static int
-add_bytes(regex_t* reg, UChar* bytes, int len)
-{
- BBUF_ADD(reg, bytes, len);
- return 0;
-}
-
-static int
-add_bitset(regex_t* reg, BitSetRef bs)
-{
- BBUF_ADD(reg, bs, SIZE_BITSET);
- return 0;
-}
-
-static int
-add_opcode_option(regex_t* reg, int opcode, OnigOptionType option)
-{
- int r;
-
- r = add_opcode(reg, opcode);
- if (r) return r;
- r = add_option(reg, option);
- return r;
-}
-
-static int compile_length_tree(Node* node, regex_t* reg);
-static int compile_tree(Node* node, regex_t* reg);
-
-
-#define IS_NEED_STR_LEN_OP_EXACT(op) \
- ((op) == OP_EXACTN || (op) == OP_EXACTMB2N ||\
- (op) == OP_EXACTMB3N || (op) == OP_EXACTMBN || (op) == OP_EXACTN_IC)
-
-static int
-select_str_opcode(int mb_len, int str_len, int ignore_case)
-{
- int op;
-
- if (ignore_case) {
- switch (str_len) {
- case 1: op = OP_EXACT1_IC; break;
- default: op = OP_EXACTN_IC; break;
- }
- }
- else {
- switch (mb_len) {
- case 1:
- switch (str_len) {
- case 1: op = OP_EXACT1; break;
- case 2: op = OP_EXACT2; break;
- case 3: op = OP_EXACT3; break;
- case 4: op = OP_EXACT4; break;
- case 5: op = OP_EXACT5; break;
- default: op = OP_EXACTN; break;
- }
- break;
-
- case 2:
- switch (str_len) {
- case 1: op = OP_EXACTMB2N1; break;
- case 2: op = OP_EXACTMB2N2; break;
- case 3: op = OP_EXACTMB2N3; break;
- default: op = OP_EXACTMB2N; break;
- }
- break;
-
- case 3:
- op = OP_EXACTMB3N;
- break;
-
- default:
- op = OP_EXACTMBN;
- break;
- }
- }
- return op;
-}
-
-static int
-compile_tree_empty_check(Node* node, regex_t* reg, int empty_info)
-{
- int r;
- int saved_num_null_check = reg->num_null_check;
-
- if (empty_info != 0) {
- r = add_opcode(reg, OP_NULL_CHECK_START);
- if (r) return r;
- r = add_mem_num(reg, reg->num_null_check); /* NULL CHECK ID */
- if (r) return r;
- reg->num_null_check++;
- }
-
- r = compile_tree(node, reg);
- if (r) return r;
-
- if (empty_info != 0) {
- if (empty_info == NQ_TARGET_IS_EMPTY)
- r = add_opcode(reg, OP_NULL_CHECK_END);
- else if (empty_info == NQ_TARGET_IS_EMPTY_MEM)
- r = add_opcode(reg, OP_NULL_CHECK_END_MEMST);
- else if (empty_info == NQ_TARGET_IS_EMPTY_REC)
- r = add_opcode(reg, OP_NULL_CHECK_END_MEMST_PUSH);
-
- if (r) return r;
- r = add_mem_num(reg, saved_num_null_check); /* NULL CHECK ID */
- }
- return r;
-}
-
-#ifdef USE_SUBEXP_CALL
-static int
-compile_call(CallNode* node, regex_t* reg)
-{
- int r;
-
- r = add_opcode(reg, OP_CALL);
- if (r) return r;
- r = unset_addr_list_add(node->unset_addr_list, BBUF_GET_OFFSET_POS(reg),
- node->target);
- if (r) return r;
- r = add_abs_addr(reg, 0 /*dummy addr.*/);
- return r;
-}
-#endif
-
-static int
-compile_tree_n_times(Node* node, int n, regex_t* reg)
-{
- int i, r;
-
- for (i = 0; i < n; i++) {
- r = compile_tree(node, reg);
- if (r) return r;
- }
- return 0;
-}
-
-static int
-add_compile_string_length(UChar* s, int mb_len, int str_len,
- regex_t* reg, int ignore_case)
-{
- int len;
- int op = select_str_opcode(mb_len, str_len, ignore_case);
-
- len = SIZE_OPCODE;
-
- if (op == OP_EXACTMBN) len += SIZE_LENGTH;
- if (IS_NEED_STR_LEN_OP_EXACT(op))
- len += SIZE_LENGTH;
-
- len += mb_len * str_len;
- return len;
-}
-
-static int
-add_compile_string(UChar* s, int mb_len, int str_len,
- regex_t* reg, int ignore_case)
-{
- int op = select_str_opcode(mb_len, str_len, ignore_case);
- add_opcode(reg, op);
-
- if (op == OP_EXACTMBN)
- add_length(reg, mb_len);
-
- if (IS_NEED_STR_LEN_OP_EXACT(op)) {
- if (op == OP_EXACTN_IC)
- add_length(reg, mb_len * str_len);
- else
- add_length(reg, str_len);
- }
-
- add_bytes(reg, s, mb_len * str_len);
- return 0;
-}
-
-
-static int
-compile_length_string_node(Node* node, regex_t* reg)
-{
- int rlen, r, len, prev_len, slen, ambig;
- OnigEncoding enc = reg->enc;
- UChar *p, *prev;
- StrNode* sn;
-
- sn = &(NSTRING(node));
- if (sn->end <= sn->s)
- return 0;
-
- ambig = NSTRING_IS_AMBIG(node);
-
- p = prev = sn->s;
- prev_len = enc_len(enc, p);
- p += prev_len;
- slen = 1;
- rlen = 0;
-
- for (; p < sn->end; ) {
- len = enc_len(enc, p);
- if (len == prev_len) {
- slen++;
- }
- else {
- r = add_compile_string_length(prev, prev_len, slen, reg, ambig);
- rlen += r;
- prev = p;
- slen = 1;
- prev_len = len;
- }
- p += len;
- }
- r = add_compile_string_length(prev, prev_len, slen, reg, ambig);
- rlen += r;
- return rlen;
-}
-
-static int
-compile_length_string_raw_node(StrNode* sn, regex_t* reg)
-{
- if (sn->end <= sn->s)
- return 0;
-
- return add_compile_string_length(sn->s, 1 /* sb */, sn->end - sn->s, reg, 0);
-}
-
-static int
-compile_string_node(Node* node, regex_t* reg)
-{
- int r, len, prev_len, slen, ambig;
- OnigEncoding enc = reg->enc;
- UChar *p, *prev, *end;
- StrNode* sn;
-
- sn = &(NSTRING(node));
- if (sn->end <= sn->s)
- return 0;
-
- end = sn->end;
- ambig = NSTRING_IS_AMBIG(node);
-
- p = prev = sn->s;
- prev_len = enc_len(enc, p);
- p += prev_len;
- slen = 1;
-
- for (; p < end; ) {
- len = enc_len(enc, p);
- if (len == prev_len) {
- slen++;
- }
- else {
- r = add_compile_string(prev, prev_len, slen, reg, ambig);
- if (r) return r;
-
- prev = p;
- slen = 1;
- prev_len = len;
- }
-
- p += len;
- }
- return add_compile_string(prev, prev_len, slen, reg, ambig);
-}
-
-static int
-compile_string_raw_node(StrNode* sn, regex_t* reg)
-{
- if (sn->end <= sn->s)
- return 0;
-
- return add_compile_string(sn->s, 1 /* sb */, sn->end - sn->s, reg, 0);
-}
-
-static int
-add_multi_byte_cclass(BBuf* mbuf, regex_t* reg)
-{
-#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
- add_length(reg, mbuf->used);
- return add_bytes(reg, mbuf->p, mbuf->used);
-#else
- int r, pad_size;
- UChar* p = BBUF_GET_ADD_ADDRESS(reg) + SIZE_LENGTH;
-
- GET_ALIGNMENT_PAD_SIZE(p, pad_size);
- add_length(reg, mbuf->used + (WORD_ALIGNMENT_SIZE - 1));
- if (pad_size != 0) add_bytes(reg, PadBuf, pad_size);
-
- r = add_bytes(reg, mbuf->p, mbuf->used);
-
- /* padding for return value from compile_length_cclass_node() to be fix. */
- pad_size = (WORD_ALIGNMENT_SIZE - 1) - pad_size;
- if (pad_size != 0) add_bytes(reg, PadBuf, pad_size);
- return r;
-#endif
-}
-
-static int
-compile_length_cclass_node(CClassNode* cc, regex_t* reg)
-{
- int len;
-
- if (IS_CCLASS_SHARE(cc)) {
- len = SIZE_OPCODE + SIZE_POINTER;
- return len;
- }
-
- if (IS_NULL(cc->mbuf)) {
- len = SIZE_OPCODE + SIZE_BITSET;
- }
- else {
- if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
- len = SIZE_OPCODE;
- }
- else {
- len = SIZE_OPCODE + SIZE_BITSET;
- }
-#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
- len += SIZE_LENGTH + cc->mbuf->used;
-#else
- len += SIZE_LENGTH + cc->mbuf->used + (WORD_ALIGNMENT_SIZE - 1);
-#endif
- }
-
- return len;
-}
-
-static int
-compile_cclass_node(CClassNode* cc, regex_t* reg)
-{
- int r;
-
- if (IS_CCLASS_SHARE(cc)) {
- add_opcode(reg, OP_CCLASS_NODE);
- r = add_pointer(reg, cc);
- return r;
- }
-
- if (IS_NULL(cc->mbuf)) {
- if (IS_CCLASS_NOT(cc))
- add_opcode(reg, OP_CCLASS_NOT);
- else
- add_opcode(reg, OP_CCLASS);
-
- r = add_bitset(reg, cc->bs);
- }
- else {
- if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
- if (IS_CCLASS_NOT(cc))
- add_opcode(reg, OP_CCLASS_MB_NOT);
- else
- add_opcode(reg, OP_CCLASS_MB);
-
- r = add_multi_byte_cclass(cc->mbuf, reg);
- }
- else {
- if (IS_CCLASS_NOT(cc))
- add_opcode(reg, OP_CCLASS_MIX_NOT);
- else
- add_opcode(reg, OP_CCLASS_MIX);
-
- r = add_bitset(reg, cc->bs);
- if (r) return r;
- r = add_multi_byte_cclass(cc->mbuf, reg);
- }
- }
-
- return r;
-}
-
-static int
-entry_repeat_range(regex_t* reg, int id, int lower, int upper)
-{
-#define REPEAT_RANGE_ALLOC 4
-
- OnigRepeatRange* p;
-
- if (reg->repeat_range_alloc == 0) {
- p = (OnigRepeatRange* )xmalloc(sizeof(OnigRepeatRange) * REPEAT_RANGE_ALLOC);
- CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY);
- reg->repeat_range = p;
- reg->repeat_range_alloc = REPEAT_RANGE_ALLOC;
- }
- else if (reg->repeat_range_alloc <= id) {
- int n;
- n = reg->repeat_range_alloc + REPEAT_RANGE_ALLOC;
- p = (OnigRepeatRange* )xrealloc(reg->repeat_range,
- sizeof(OnigRepeatRange) * n);
- CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY);
- reg->repeat_range = p;
- reg->repeat_range_alloc = n;
- }
- else {
- p = reg->repeat_range;
- }
-
- p[id].lower = lower;
- p[id].upper = upper;
- return 0;
-}
-
-static int
-compile_range_repeat_node(QualifierNode* qn, int target_len, int empty_info,
- regex_t* reg)
-{
- int r;
- int num_repeat = reg->num_repeat;
-
- r = add_opcode(reg, qn->greedy ? OP_REPEAT : OP_REPEAT_NG);
- if (r) return r;
- r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
- reg->num_repeat++;
- if (r) return r;
- r = add_rel_addr(reg, target_len + SIZE_OP_REPEAT_INC);
- if (r) return r;
-
- r = entry_repeat_range(reg, num_repeat, qn->lower, qn->upper);
- if (r) return r;
-
- r = compile_tree_empty_check(qn->target, reg, empty_info);
- if (r) return r;
-
- if (
-#ifdef USE_SUBEXP_CALL
- reg->num_call > 0 ||
-#endif
- IS_QUALIFIER_IN_REPEAT(qn)) {
- r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC_SG : OP_REPEAT_INC_NG_SG);
- }
- else {
- r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC : OP_REPEAT_INC_NG);
- }
- if (r) return r;
- r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
- return r;
-}
-
-#define QUALIFIER_EXPAND_LIMIT_SIZE 50
-
-static int
-compile_length_qualifier_node(QualifierNode* qn, regex_t* reg)
-{
- int len, mod_tlen;
- int infinite = IS_REPEAT_INFINITE(qn->upper);
- int empty_info = qn->target_empty_info;
- int tlen = compile_length_tree(qn->target, reg);
-
- if (tlen < 0) return tlen;
-
- /* anychar repeat */
- if (NTYPE(qn->target) == N_ANYCHAR) {
- if (qn->greedy && infinite) {
- if (IS_NOT_NULL(qn->next_head_exact))
- return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower;
- else
- return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower;
- }
- }
-
- if (empty_info != 0)
- mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
- else
- mod_tlen = tlen;
-
- if (infinite &&
- (qn->lower <= 1 || tlen * qn->lower <= QUALIFIER_EXPAND_LIMIT_SIZE)) {
- if (qn->lower == 1 && tlen > QUALIFIER_EXPAND_LIMIT_SIZE) {
- len = SIZE_OP_JUMP;
- }
- else {
- len = tlen * qn->lower;
- }
-
- if (qn->greedy) {
- if (IS_NOT_NULL(qn->head_exact))
- len += SIZE_OP_PUSH_OR_JUMP_EXACT1 + mod_tlen + SIZE_OP_JUMP;
- else if (IS_NOT_NULL(qn->next_head_exact))
- len += SIZE_OP_PUSH_IF_PEEK_NEXT + mod_tlen + SIZE_OP_JUMP;
- else
- len += SIZE_OP_PUSH + mod_tlen + SIZE_OP_JUMP;
- }
- else
- len += SIZE_OP_JUMP + mod_tlen + SIZE_OP_PUSH;
- }
- else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?<n>..){0}/ */
- len = SIZE_OP_JUMP + tlen;
- }
- else if (!infinite && qn->greedy &&
- (qn->upper == 1 || (tlen + SIZE_OP_PUSH) * qn->upper
- <= QUALIFIER_EXPAND_LIMIT_SIZE)) {
- len = tlen * qn->lower;
- len += (SIZE_OP_PUSH + tlen) * (qn->upper - qn->lower);
- }
- else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
- len = SIZE_OP_PUSH + SIZE_OP_JUMP + tlen;
- }
- else {
- len = SIZE_OP_REPEAT_INC
- + mod_tlen + SIZE_OPCODE + SIZE_RELADDR + SIZE_MEMNUM;
- }
-
- return len;
-}
-
-static int
-is_anychar_star_qualifier(QualifierNode* qn)
-{
- if (qn->greedy && IS_REPEAT_INFINITE(qn->upper) &&
- NTYPE(qn->target) == N_ANYCHAR)
- return 1;
- else
- return 0;
-}
-
-static int
-compile_qualifier_node(QualifierNode* qn, regex_t* reg)
-{
- int i, r, mod_tlen;
- int infinite = IS_REPEAT_INFINITE(qn->upper);
- int empty_info = qn->target_empty_info;
- int tlen = compile_length_tree(qn->target, reg);
-
- if (tlen < 0) return tlen;
-
- if (is_anychar_star_qualifier(qn)) {
- r = compile_tree_n_times(qn->target, qn->lower, reg);
- if (r) return r;
- if (IS_NOT_NULL(qn->next_head_exact)) {
- if (IS_MULTILINE(reg->options))
- r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
- else
- r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
- if (r) return r;
- return add_bytes(reg, NSTRING(qn->next_head_exact).s, 1);
- }
- else {
- if (IS_MULTILINE(reg->options))
- return add_opcode(reg, OP_ANYCHAR_ML_STAR);
- else
- return add_opcode(reg, OP_ANYCHAR_STAR);
- }
- }
-
- if (empty_info != 0)
- mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END);
- else
- mod_tlen = tlen;
-
- if (infinite &&
- (qn->lower <= 1 || tlen * qn->lower <= QUALIFIER_EXPAND_LIMIT_SIZE)) {
- if (qn->lower == 1 && tlen > QUALIFIER_EXPAND_LIMIT_SIZE) {
- if (qn->greedy) {
- if (IS_NOT_NULL(qn->head_exact))
- r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_OR_JUMP_EXACT1);
- else if (IS_NOT_NULL(qn->next_head_exact))
- r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_IF_PEEK_NEXT);
- else
- r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH);
- }
- else {
- r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_JUMP);
- }
- if (r) return r;
- }
- else {
- r = compile_tree_n_times(qn->target, qn->lower, reg);
- if (r) return r;
- }
-
- if (qn->greedy) {
- if (IS_NOT_NULL(qn->head_exact)) {
- r = add_opcode_rel_addr(reg, OP_PUSH_OR_JUMP_EXACT1,
- mod_tlen + SIZE_OP_JUMP);
- if (r) return r;
- add_bytes(reg, NSTRING(qn->head_exact).s, 1);
- r = compile_tree_empty_check(qn->target, reg, empty_info);
- if (r) return r;
- r = add_opcode_rel_addr(reg, OP_JUMP,
- -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_OR_JUMP_EXACT1));
- }
- else if (IS_NOT_NULL(qn->next_head_exact)) {
- r = add_opcode_rel_addr(reg, OP_PUSH_IF_PEEK_NEXT,
- mod_tlen + SIZE_OP_JUMP);
- if (r) return r;
- add_bytes(reg, NSTRING(qn->next_head_exact).s, 1);
- r = compile_tree_empty_check(qn->target, reg, empty_info);
- if (r) return r;
- r = add_opcode_rel_addr(reg, OP_JUMP,
- -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_IF_PEEK_NEXT));
- }
- else {
- r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
- if (r) return r;
- r = compile_tree_empty_check(qn->target, reg, empty_info);
- if (r) return r;
- r = add_opcode_rel_addr(reg, OP_JUMP,
- -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH));
- }
- }
- else {
- r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);
- if (r) return r;
- r = compile_tree_empty_check(qn->target, reg, empty_info);
- if (r) return r;
- r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));
- }
- }
- else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?<n>..){0}/ */
- r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
- if (r) return r;
- r = compile_tree(qn->target, reg);
- }
- else if (!infinite && qn->greedy &&
- (qn->upper == 1 || (tlen + SIZE_OP_PUSH) * qn->upper
- <= QUALIFIER_EXPAND_LIMIT_SIZE)) {
- int n = qn->upper - qn->lower;
-
- r = compile_tree_n_times(qn->target, qn->lower, reg);
- if (r) return r;
-
- for (i = 0; i < n; i++) {
- r = add_opcode_rel_addr(reg, OP_PUSH,
- (n - i) * tlen + (n - i - 1) * SIZE_OP_PUSH);
- if (r) return r;
- r = compile_tree(qn->target, reg);
- if (r) return r;
- }
- }
- else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */
- r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP);
- if (r) return r;
- r = add_opcode_rel_addr(reg, OP_JUMP, tlen);
- if (r) return r;
- r = compile_tree(qn->target, reg);
- }
- else {
- r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg);
- }
- return r;
-}
-
-static int
-compile_length_option_node(EffectNode* node, regex_t* reg)
-{
- int tlen;
- OnigOptionType prev = reg->options;
-
- reg->options = node->option;
- tlen = compile_length_tree(node->target, reg);
- reg->options = prev;
-
- if (tlen < 0) return tlen;
-
- if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
- return SIZE_OP_SET_OPTION_PUSH + SIZE_OP_SET_OPTION + SIZE_OP_FAIL
- + tlen + SIZE_OP_SET_OPTION;
- }
- else
- return tlen;
-}
-
-static int
-compile_option_node(EffectNode* node, regex_t* reg)
-{
- int r;
- OnigOptionType prev = reg->options;
-
- if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
- r = add_opcode_option(reg, OP_SET_OPTION_PUSH, node->option);
- if (r) return r;
- r = add_opcode_option(reg, OP_SET_OPTION, prev);
- if (r) return r;
- r = add_opcode(reg, OP_FAIL);
- if (r) return r;
- }
-
- reg->options = node->option;
- r = compile_tree(node->target, reg);
- reg->options = prev;
-
- if (IS_DYNAMIC_OPTION(prev ^ node->option)) {
- if (r) return r;
- r = add_opcode_option(reg, OP_SET_OPTION, prev);
- }
- return r;
-}
-
-static int
-compile_length_effect_node(EffectNode* node, regex_t* reg)
-{
- int len;
- int tlen;
-
- if (node->type == EFFECT_OPTION)
- return compile_length_option_node(node, reg);
-
- if (node->target) {
- tlen = compile_length_tree(node->target, reg);
- if (tlen < 0) return tlen;
- }
- else
- tlen = 0;
-
- switch (node->type) {
- case EFFECT_MEMORY:
-#ifdef USE_SUBEXP_CALL
- if (IS_EFFECT_CALLED(node)) {
- len = SIZE_OP_MEMORY_START_PUSH + tlen
- + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;
- if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
- len += (IS_EFFECT_RECURSION(node)
- ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
- else
- len += (IS_EFFECT_RECURSION(node)
- ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
- }
- else
-#endif
- {
- if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum))
- len = SIZE_OP_MEMORY_START_PUSH;
- else
- len = SIZE_OP_MEMORY_START;
-
- len += tlen + (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)
- ? SIZE_OP_MEMORY_END_PUSH : SIZE_OP_MEMORY_END);
- }
- break;
-
- case EFFECT_STOP_BACKTRACK:
- if (IS_EFFECT_STOP_BT_SIMPLE_REPEAT(node)) {
- QualifierNode* qn = &NQUALIFIER(node->target);
- tlen = compile_length_tree(qn->target, reg);
- if (tlen < 0) return tlen;
-
- len = tlen * qn->lower
- + SIZE_OP_PUSH + tlen + SIZE_OP_POP + SIZE_OP_JUMP;
- }
- else {
- len = SIZE_OP_PUSH_STOP_BT + tlen + SIZE_OP_POP_STOP_BT;
- }
- break;
-
- default:
- return ONIGERR_TYPE_BUG;
- break;
- }
-
- return len;
-}
-
-static int get_char_length_tree(Node* node, regex_t* reg, int* len);
-
-static int
-compile_effect_node(EffectNode* node, regex_t* reg)
-{
- int r, len;
-
- if (node->type == EFFECT_OPTION)
- return compile_option_node(node, reg);
-
- switch (node->type) {
- case EFFECT_MEMORY:
-#ifdef USE_SUBEXP_CALL
- if (IS_EFFECT_CALLED(node)) {
- r = add_opcode(reg, OP_CALL);
- if (r) return r;
- node->call_addr = BBUF_GET_OFFSET_POS(reg) + SIZE_ABSADDR + SIZE_OP_JUMP;
- node->state |= NST_ADDR_FIXED;
- r = add_abs_addr(reg, (int )node->call_addr);
- if (r) return r;
- len = compile_length_tree(node->target, reg);
- len += (SIZE_OP_MEMORY_START_PUSH + SIZE_OP_RETURN);
- if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
- len += (IS_EFFECT_RECURSION(node)
- ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
- else
- len += (IS_EFFECT_RECURSION(node)
- ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
-
- r = add_opcode_rel_addr(reg, OP_JUMP, len);
- if (r) return r;
- }
-#endif
- if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum))
- r = add_opcode(reg, OP_MEMORY_START_PUSH);
- else
- r = add_opcode(reg, OP_MEMORY_START);
- if (r) return r;
- r = add_mem_num(reg, node->regnum);
- if (r) return r;
- r = compile_tree(node->target, reg);
- if (r) return r;
-#ifdef USE_SUBEXP_CALL
- if (IS_EFFECT_CALLED(node)) {
- if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
- r = add_opcode(reg, (IS_EFFECT_RECURSION(node)
- ? OP_MEMORY_END_PUSH_REC : OP_MEMORY_END_PUSH));
- else
- r = add_opcode(reg, (IS_EFFECT_RECURSION(node)
- ? OP_MEMORY_END_REC : OP_MEMORY_END));
-
- if (r) return r;
- r = add_mem_num(reg, node->regnum);
- if (r) return r;
- r = add_opcode(reg, OP_RETURN);
- }
- else
-#endif
- {
- if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
- r = add_opcode(reg, OP_MEMORY_END_PUSH);
- else
- r = add_opcode(reg, OP_MEMORY_END);
- if (r) return r;
- r = add_mem_num(reg, node->regnum);
- }
- break;
-
- case EFFECT_STOP_BACKTRACK:
- if (IS_EFFECT_STOP_BT_SIMPLE_REPEAT(node)) {
- QualifierNode* qn = &NQUALIFIER(node->target);
- r = compile_tree_n_times(qn->target, qn->lower, reg);
- if (r) return r;
-
- len = compile_length_tree(qn->target, reg);
- if (len < 0) return len;
-
- r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_POP + SIZE_OP_JUMP);
- if (r) return r;
- r = compile_tree(qn->target, reg);
- if (r) return r;
- r = add_opcode(reg, OP_POP);
- if (r) return r;
- r = add_opcode_rel_addr(reg, OP_JUMP,
- -((int )SIZE_OP_PUSH + len + (int )SIZE_OP_POP + (int )SIZE_OP_JUMP));
- }
- else {
- r = add_opcode(reg, OP_PUSH_STOP_BT);
- if (r) return r;
- r = compile_tree(node->target, reg);
- if (r) return r;
- r = add_opcode(reg, OP_POP_STOP_BT);
- }
- break;
-
- default:
- return ONIGERR_TYPE_BUG;
- break;
- }
-
- return r;
-}
-
-static int
-compile_length_anchor_node(AnchorNode* node, regex_t* reg)
-{
- int len;
- int tlen = 0;
-
- if (node->target) {
- tlen = compile_length_tree(node->target, reg);
- if (tlen < 0) return tlen;
- }
-
- switch (node->type) {
- case ANCHOR_PREC_READ:
- len = SIZE_OP_PUSH_POS + tlen + SIZE_OP_POP_POS;
- break;
- case ANCHOR_PREC_READ_NOT:
- len = SIZE_OP_PUSH_POS_NOT + tlen + SIZE_OP_FAIL_POS;
- break;
- case ANCHOR_LOOK_BEHIND:
- len = SIZE_OP_LOOK_BEHIND + tlen;
- break;
- case ANCHOR_LOOK_BEHIND_NOT:
- len = SIZE_OP_PUSH_LOOK_BEHIND_NOT + tlen + SIZE_OP_FAIL_LOOK_BEHIND_NOT;
- break;
-
- default:
- len = SIZE_OPCODE;
- break;
- }
-
- return len;
-}
-
-static int
-compile_anchor_node(AnchorNode* node, regex_t* reg)
-{
- int r, len;
-
- switch (node->type) {
- case ANCHOR_BEGIN_BUF: r = add_opcode(reg, OP_BEGIN_BUF); break;
- case ANCHOR_END_BUF: r = add_opcode(reg, OP_END_BUF); break;
- case ANCHOR_BEGIN_LINE: r = add_opcode(reg, OP_BEGIN_LINE); break;
- case ANCHOR_END_LINE: r = add_opcode(reg, OP_END_LINE); break;
- case ANCHOR_SEMI_END_BUF: r = add_opcode(reg, OP_SEMI_END_BUF); break;
- case ANCHOR_BEGIN_POSITION: r = add_opcode(reg, OP_BEGIN_POSITION); break;
-
- case ANCHOR_WORD_BOUND: r = add_opcode(reg, OP_WORD_BOUND); break;
- case ANCHOR_NOT_WORD_BOUND: r = add_opcode(reg, OP_NOT_WORD_BOUND); break;
-#ifdef USE_WORD_BEGIN_END
- case ANCHOR_WORD_BEGIN: r = add_opcode(reg, OP_WORD_BEGIN); break;
- case ANCHOR_WORD_END: r = add_opcode(reg, OP_WORD_END); break;
-#endif
-
- case ANCHOR_PREC_READ:
- r = add_opcode(reg, OP_PUSH_POS);
- if (r) return r;
- r = compile_tree(node->target, reg);
- if (r) return r;
- r = add_opcode(reg, OP_POP_POS);
- break;
-
- case ANCHOR_PREC_READ_NOT:
- len = compile_length_tree(node->target, reg);
- if (len < 0) return len;
- r = add_opcode_rel_addr(reg, OP_PUSH_POS_NOT, len + SIZE_OP_FAIL_POS);
- if (r) return r;
- r = compile_tree(node->target, reg);
- if (r) return r;
- r = add_opcode(reg, OP_FAIL_POS);
- break;
-
- case ANCHOR_LOOK_BEHIND:
- {
- int n;
- r = add_opcode(reg, OP_LOOK_BEHIND);
- if (r) return r;
- if (node->char_len < 0) {
- r = get_char_length_tree(node->target, reg, &n);
- if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
- }
- else
- n = node->char_len;
- r = add_length(reg, n);
- if (r) return r;
- r = compile_tree(node->target, reg);
- }
- break;
-
- case ANCHOR_LOOK_BEHIND_NOT:
- {
- int n;
- len = compile_length_tree(node->target, reg);
- r = add_opcode_rel_addr(reg, OP_PUSH_LOOK_BEHIND_NOT,
- len + SIZE_OP_FAIL_LOOK_BEHIND_NOT);
- if (r) return r;
- if (node->char_len < 0) {
- r = get_char_length_tree(node->target, reg, &n);
- if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
- }
- else
- n = node->char_len;
- r = add_length(reg, n);
- if (r) return r;
- r = compile_tree(node->target, reg);
- if (r) return r;
- r = add_opcode(reg, OP_FAIL_LOOK_BEHIND_NOT);
- }
- break;
-
- default:
- return ONIGERR_TYPE_BUG;
- break;
- }
-
- return r;
-}
-
-static int
-compile_length_tree(Node* node, regex_t* reg)
-{
- int len, type, r;
-
- type = NTYPE(node);
- switch (type) {
- case N_LIST:
- len = 0;
- do {
- r = compile_length_tree(NCONS(node).left, reg);
- if (r < 0) return r;
- len += r;
- } while (IS_NOT_NULL(node = NCONS(node).right));
- r = len;
- break;
-
- case N_ALT:
- {
- int n;
-
- n = r = 0;
- do {
- r += compile_length_tree(NCONS(node).left, reg);
- n++;
- } while (IS_NOT_NULL(node = NCONS(node).right));
- r += (SIZE_OP_PUSH + SIZE_OP_JUMP) * (n - 1);
- }
- break;
-
- case N_STRING:
- if (NSTRING_IS_RAW(node))
- r = compile_length_string_raw_node(&(NSTRING(node)), reg);
- else
- r = compile_length_string_node(node, reg);
- break;
-
- case N_CCLASS:
- r = compile_length_cclass_node(&(NCCLASS(node)), reg);
- break;
-
- case N_CTYPE:
- case N_ANYCHAR:
- r = SIZE_OPCODE;
- break;
-
- case N_BACKREF:
- {
- BackrefNode* br = &(NBACKREF(node));
-
- if (br->back_num == 1) {
- r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 3)
- ? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM));
- }
- else {
- r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
- }
- }
- break;
-
-#ifdef USE_SUBEXP_CALL
- case N_CALL:
- r = SIZE_OP_CALL;
- break;
-#endif
-
- case N_QUALIFIER:
- r = compile_length_qualifier_node(&(NQUALIFIER(node)), reg);
- break;
-
- case N_EFFECT:
- r = compile_length_effect_node(&NEFFECT(node), reg);
- break;
-
- case N_ANCHOR:
- r = compile_length_anchor_node(&(NANCHOR(node)), reg);
- break;
-
- default:
- return ONIGERR_TYPE_BUG;
- break;
- }
-
- return r;
-}
-
-static int
-compile_tree(Node* node, regex_t* reg)
-{
- int n, type, len, pos, r = 0;
-
- type = NTYPE(node);
- switch (type) {
- case N_LIST:
- do {
- r = compile_tree(NCONS(node).left, reg);
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- case N_ALT:
- {
- Node* x = node;
- len = 0;
- do {
- len += compile_length_tree(NCONS(x).left, reg);
- if (NCONS(x).right != NULL) {
- len += SIZE_OP_PUSH + SIZE_OP_JUMP;
- }
- } while (IS_NOT_NULL(x = NCONS(x).right));
- pos = reg->used + len; /* goal position */
-
- do {
- len = compile_length_tree(NCONS(node).left, reg);
- if (IS_NOT_NULL(NCONS(node).right)) {
- r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_JUMP);
- if (r) break;
- }
- r = compile_tree(NCONS(node).left, reg);
- if (r) break;
- if (IS_NOT_NULL(NCONS(node).right)) {
- len = pos - (reg->used + SIZE_OP_JUMP);
- r = add_opcode_rel_addr(reg, OP_JUMP, len);
- if (r) break;
- }
- } while (IS_NOT_NULL(node = NCONS(node).right));
- }
- break;
-
- case N_STRING:
- if (NSTRING_IS_RAW(node))
- r = compile_string_raw_node(&(NSTRING(node)), reg);
- else
- r = compile_string_node(node, reg);
- break;
-
- case N_CCLASS:
- r = compile_cclass_node(&(NCCLASS(node)), reg);
- break;
-
- case N_CTYPE:
- {
- int op;
-
- switch (NCTYPE(node).type) {
- case CTYPE_WORD: op = OP_WORD; break;
- case CTYPE_NOT_WORD: op = OP_NOT_WORD; break;
- default:
- return ONIGERR_TYPE_BUG;
- break;
- }
- r = add_opcode(reg, op);
- }
- break;
-
- case N_ANYCHAR:
- if (IS_MULTILINE(reg->options))
- r = add_opcode(reg, OP_ANYCHAR_ML);
- else
- r = add_opcode(reg, OP_ANYCHAR);
- break;
-
- case N_BACKREF:
- {
- int i;
- BackrefNode* br = &(NBACKREF(node));
-
- if (br->back_num == 1) {
- n = br->back_static[0];
- if (IS_IGNORECASE(reg->options)) {
- r = add_opcode(reg, OP_BACKREFN_IC);
- if (r) return r;
- r = add_mem_num(reg, n);
- }
- else {
- switch (n) {
- case 1: r = add_opcode(reg, OP_BACKREF1); break;
- case 2: r = add_opcode(reg, OP_BACKREF2); break;
- case 3: r = add_opcode(reg, OP_BACKREF3); break;
- default:
- r = add_opcode(reg, OP_BACKREFN);
- if (r) return r;
- r = add_mem_num(reg, n);
- break;
- }
- }
- }
- else {
- int* p;
-
- if (IS_IGNORECASE(reg->options)) {
- add_opcode(reg, OP_BACKREF_MULTI_IC);
- }
- else {
- add_opcode(reg, OP_BACKREF_MULTI);
- }
-
- if (r) return r;
- add_length(reg, br->back_num);
- if (r) return r;
- p = BACKREFS_P(br);
- for (i = br->back_num - 1; i >= 0; i--) {
- r = add_mem_num(reg, p[i]);
- if (r) return r;
- }
- }
- }
- break;
-
-#ifdef USE_SUBEXP_CALL
- case N_CALL:
- r = compile_call(&(NCALL(node)), reg);
- break;
-#endif
-
- case N_QUALIFIER:
- r = compile_qualifier_node(&(NQUALIFIER(node)), reg);
- break;
-
- case N_EFFECT:
- r = compile_effect_node(&NEFFECT(node), reg);
- break;
-
- case N_ANCHOR:
- r = compile_anchor_node(&(NANCHOR(node)), reg);
- break;
-
- default:
-#ifdef ONIG_DEBUG
- fprintf(stderr, "compile_tree: undefined node type %d\n", NTYPE(node));
-#endif
- break;
- }
-
- return r;
-}
-
-#ifdef USE_NAMED_GROUP
-
-static int
-noname_disable_map(Node** plink, GroupNumRemap* map, int* counter)
-{
- int r = 0;
- Node* node = *plink;
-
- switch (NTYPE(node)) {
- case N_LIST:
- case N_ALT:
- do {
- r = noname_disable_map(&(NCONS(node).left), map, counter);
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- case N_QUALIFIER:
- {
- Node** ptarget = &(NQUALIFIER(node).target);
- Node* old = *ptarget;
- r = noname_disable_map(ptarget, map, counter);
- if (*ptarget != old && NTYPE(*ptarget) == N_QUALIFIER) {
- onig_reduce_nested_qualifier(node, *ptarget);
- }
- }
- break;
-
- case N_EFFECT:
- {
- EffectNode* en = &(NEFFECT(node));
- if (en->type == EFFECT_MEMORY) {
- if (IS_EFFECT_NAMED_GROUP(en)) {
- (*counter)++;
- map[en->regnum].new_val = *counter;
- en->regnum = *counter;
- r = noname_disable_map(&(en->target), map, counter);
- }
- else {
- *plink = en->target;
- en->target = NULL_NODE;
- onig_node_free(node);
- r = noname_disable_map(plink, map, counter);
- }
- }
- else
- r = noname_disable_map(&(en->target), map, counter);
- }
- break;
-
- default:
- break;
- }
-
- return r;
-}
-
-static int
-renumber_node_backref(Node* node, GroupNumRemap* map)
-{
- int i, pos, n, old_num;
- int *backs;
- BackrefNode* bn = &(NBACKREF(node));
-
- if (! IS_BACKREF_NAME_REF(bn))
- return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
-
- old_num = bn->back_num;
- if (IS_NULL(bn->back_dynamic))
- backs = bn->back_static;
- else
- backs = bn->back_dynamic;
-
- for (i = 0, pos = 0; i < old_num; i++) {
- n = map[backs[i]].new_val;
- if (n > 0) {
- backs[pos] = n;
- pos++;
- }
- }
-
- bn->back_num = pos;
- return 0;
-}
-
-static int
-renumber_by_map(Node* node, GroupNumRemap* map)
-{
- int r = 0;
-
- switch (NTYPE(node)) {
- case N_LIST:
- case N_ALT:
- do {
- r = renumber_by_map(NCONS(node).left, map);
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
- case N_QUALIFIER:
- r = renumber_by_map(NQUALIFIER(node).target, map);
- break;
- case N_EFFECT:
- r = renumber_by_map(NEFFECT(node).target, map);
- break;
-
- case N_BACKREF:
- r = renumber_node_backref(node, map);
- break;
-
- default:
- break;
- }
-
- return r;
-}
-
-static int
-numbered_ref_check(Node* node)
-{
- int r = 0;
-
- switch (NTYPE(node)) {
- case N_LIST:
- case N_ALT:
- do {
- r = numbered_ref_check(NCONS(node).left);
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
- case N_QUALIFIER:
- r = numbered_ref_check(NQUALIFIER(node).target);
- break;
- case N_EFFECT:
- r = numbered_ref_check(NEFFECT(node).target);
- break;
-
- case N_BACKREF:
- if (! IS_BACKREF_NAME_REF(&(NBACKREF(node))))
- return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
- break;
-
- default:
- break;
- }
-
- return r;
-}
-
-static int
-disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env)
-{
- int r, i, pos, counter;
- BitStatusType loc;
- GroupNumRemap* map;
-
- map = (GroupNumRemap* )xalloca(sizeof(GroupNumRemap) * (env->num_mem + 1));
- CHECK_NULL_RETURN_VAL(map, ONIGERR_MEMORY);
- for (i = 1; i <= env->num_mem; i++) {
- map[i].new_val = 0;
- }
- counter = 0;
- r = noname_disable_map(root, map, &counter);
- if (r != 0) return r;
-
- r = renumber_by_map(*root, map);
- if (r != 0) return r;
-
- for (i = 1, pos = 1; i <= env->num_mem; i++) {
- if (map[i].new_val > 0) {
- SCANENV_MEM_NODES(env)[pos] = SCANENV_MEM_NODES(env)[i];
- pos++;
- }
- }
-
- loc = env->capture_history;
- BIT_STATUS_CLEAR(env->capture_history);
- for (i = 1; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) {
- if (BIT_STATUS_AT(loc, i)) {
- BIT_STATUS_ON_AT_SIMPLE(env->capture_history, map[i].new_val);
- }
- }
-
- env->num_mem = env->num_named;
- reg->num_mem = env->num_named;
-
- return onig_renumber_name_table(reg, map);
-}
-#endif /* USE_NAMED_GROUP */
-
-#ifdef USE_SUBEXP_CALL
-static int
-unset_addr_list_fix(UnsetAddrList* uslist, regex_t* reg)
-{
- int i, offset;
- EffectNode* en;
- AbsAddrType addr;
-
- for (i = 0; i < uslist->num; i++) {
- en = &(NEFFECT(uslist->us[i].target));
- if (! IS_EFFECT_ADDR_FIXED(en)) return ONIGERR_PARSER_BUG;
- addr = en->call_addr;
- offset = uslist->us[i].offset;
-
- BBUF_WRITE(reg, offset, &addr, SIZE_ABSADDR);
- }
- return 0;
-}
-#endif
-
-#ifdef USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
-static int
-qualifiers_memory_node_info(Node* node)
-{
- int r = 0;
-
- switch (NTYPE(node)) {
- case N_LIST:
- case N_ALT:
- {
- int v;
- do {
- v = qualifiers_memory_node_info(NCONS(node).left);
- if (v > r) r = v;
- } while (v >= 0 && IS_NOT_NULL(node = NCONS(node).right));
- }
- break;
-
-#ifdef USE_SUBEXP_CALL
- case N_CALL:
- if (IS_CALL_RECURSION(&NCALL(node))) {
- return NQ_TARGET_IS_EMPTY_REC; /* tiny version */
- }
- else
- r = qualifiers_memory_node_info(NCALL(node).target);
- break;
-#endif
-
- case N_QUALIFIER:
- {
- QualifierNode* qn = &(NQUALIFIER(node));
- if (qn->upper != 0) {
- r = qualifiers_memory_node_info(qn->target);
- }
- }
- break;
-
- case N_EFFECT:
- {
- EffectNode* en = &(NEFFECT(node));
- switch (en->type) {
- case EFFECT_MEMORY:
- return NQ_TARGET_IS_EMPTY_MEM;
- break;
-
- case EFFECT_OPTION:
- case EFFECT_STOP_BACKTRACK:
- r = qualifiers_memory_node_info(en->target);
- break;
- default:
- break;
- }
- }
- break;
-
- case N_BACKREF:
- case N_STRING:
- case N_CTYPE:
- case N_CCLASS:
- case N_ANYCHAR:
- case N_ANCHOR:
- default:
- break;
- }
-
- return r;
-}
-#endif /* USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK */
-
-static int
-get_min_match_length(Node* node, OnigDistance *min, ScanEnv* env)
-{
- OnigDistance tmin;
- int r = 0;
-
- *min = 0;
- switch (NTYPE(node)) {
- case N_BACKREF:
- {
- int i;
- int* backs;
- Node** nodes = SCANENV_MEM_NODES(env);
- BackrefNode* br = &(NBACKREF(node));
- if (br->state & NST_RECURSION) break;
-
- backs = BACKREFS_P(br);
- if (backs[0] > env->num_mem) return ONIGERR_INVALID_BACKREF;
- r = get_min_match_length(nodes[backs[0]], min, env);
- if (r != 0) break;
- for (i = 1; i < br->back_num; i++) {
- if (backs[i] > env->num_mem) return ONIGERR_INVALID_BACKREF;
- r = get_min_match_length(nodes[backs[i]], &tmin, env);
- if (r != 0) break;
- if (*min > tmin) *min = tmin;
- }
- }
- break;
-
-#ifdef USE_SUBEXP_CALL
- case N_CALL:
- if (IS_CALL_RECURSION(&NCALL(node))) {
- EffectNode* en = &(NEFFECT(NCALL(node).target));
- if (IS_EFFECT_MIN_FIXED(en))
- *min = en->min_len;
- }
- else
- r = get_min_match_length(NCALL(node).target, min, env);
- break;
-#endif
-
- case N_LIST:
- do {
- r = get_min_match_length(NCONS(node).left, &tmin, env);
- if (r == 0) *min += tmin;
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- case N_ALT:
- {
- Node *x, *y;
- y = node;
- do {
- x = NCONS(y).left;
- r = get_min_match_length(x, &tmin, env);
- if (r != 0) break;
- if (y == node) *min = tmin;
- else if (*min > tmin) *min = tmin;
- } while (r == 0 && IS_NOT_NULL(y = NCONS(y).right));
- }
- break;
-
- case N_STRING:
- {
- StrNode* sn = &(NSTRING(node));
- *min = sn->end - sn->s;
- }
- break;
-
- case N_CTYPE:
- switch (NCTYPE(node).type) {
- case CTYPE_WORD: *min = 1; break;
- case CTYPE_NOT_WORD: *min = 1; break;
- default:
- break;
- }
- break;
-
- case N_CCLASS:
- case N_ANYCHAR:
- *min = 1;
- break;
-
- case N_QUALIFIER:
- {
- QualifierNode* qn = &(NQUALIFIER(node));
-
- if (qn->lower > 0) {
- r = get_min_match_length(qn->target, min, env);
- if (r == 0)
- *min = distance_multiply(*min, qn->lower);
- }
- }
- break;
-
- case N_EFFECT:
- {
- EffectNode* en = &(NEFFECT(node));
- switch (en->type) {
- case EFFECT_MEMORY:
-#ifdef USE_SUBEXP_CALL
- if (IS_EFFECT_MIN_FIXED(en))
- *min = en->min_len;
- else {
- r = get_min_match_length(en->target, min, env);
- if (r == 0) {
- en->min_len = *min;
- SET_EFFECT_STATUS(node, NST_MIN_FIXED);
- }
- }
- break;
-#endif
- case EFFECT_OPTION:
- case EFFECT_STOP_BACKTRACK:
- r = get_min_match_length(en->target, min, env);
- break;
- }
- }
- break;
-
- case N_ANCHOR:
- default:
- break;
- }
-
- return r;
-}
-
-static int
-get_max_match_length(Node* node, OnigDistance *max, ScanEnv* env)
-{
- OnigDistance tmax;
- int r = 0;
-
- *max = 0;
- switch (NTYPE(node)) {
- case N_LIST:
- do {
- r = get_max_match_length(NCONS(node).left, &tmax, env);
- if (r == 0)
- *max = distance_add(*max, tmax);
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- case N_ALT:
- do {
- r = get_max_match_length(NCONS(node).left, &tmax, env);
- if (r == 0 && *max < tmax) *max = tmax;
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- case N_STRING:
- {
- StrNode* sn = &(NSTRING(node));
- *max = sn->end - sn->s;
- }
- break;
-
- case N_CTYPE:
- switch (NCTYPE(node).type) {
- case CTYPE_WORD:
- case CTYPE_NOT_WORD:
- *max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
- break;
-
- default:
- break;
- }
- break;
-
- case N_CCLASS:
- case N_ANYCHAR:
- *max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
- break;
-
- case N_BACKREF:
- {
- int i;
- int* backs;
- Node** nodes = SCANENV_MEM_NODES(env);
- BackrefNode* br = &(NBACKREF(node));
- if (br->state & NST_RECURSION) {
- *max = ONIG_INFINITE_DISTANCE;
- break;
- }
- backs = BACKREFS_P(br);
- for (i = 0; i < br->back_num; i++) {
- if (backs[i] > env->num_mem) return ONIGERR_INVALID_BACKREF;
- r = get_max_match_length(nodes[backs[i]], &tmax, env);
- if (r != 0) break;
- if (*max < tmax) *max = tmax;
- }
- }
- break;
-
-#ifdef USE_SUBEXP_CALL
- case N_CALL:
- if (! IS_CALL_RECURSION(&(NCALL(node))))
- r = get_max_match_length(NCALL(node).target, max, env);
- else
- *max = ONIG_INFINITE_DISTANCE;
- break;
-#endif
-
- case N_QUALIFIER:
- {
- QualifierNode* qn = &(NQUALIFIER(node));
-
- if (qn->upper != 0) {
- r = get_max_match_length(qn->target, max, env);
- if (r == 0 && *max != 0) {
- if (! IS_REPEAT_INFINITE(qn->upper))
- *max = distance_multiply(*max, qn->upper);
- else
- *max = ONIG_INFINITE_DISTANCE;
- }
- }
- }
- break;
-
- case N_EFFECT:
- {
- EffectNode* en = &(NEFFECT(node));
- switch (en->type) {
- case EFFECT_MEMORY:
-#ifdef USE_SUBEXP_CALL
- if (IS_EFFECT_MAX_FIXED(en))
- *max = en->max_len;
- else {
- r = get_max_match_length(en->target, max, env);
- if (r == 0) {
- en->max_len = *max;
- SET_EFFECT_STATUS(node, NST_MAX_FIXED);
- }
- }
- break;
-#endif
- case EFFECT_OPTION:
- case EFFECT_STOP_BACKTRACK:
- r = get_max_match_length(en->target, max, env);
- break;
- }
- }
- break;
-
- case N_ANCHOR:
- default:
- break;
- }
-
- return r;
-}
-
-#define GET_CHAR_LEN_VARLEN -1
-#define GET_CHAR_LEN_TOP_ALT_VARLEN -2
-
-/* fixed size pattern node only */
-static int
-get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)
-{
- int tlen;
- int r = 0;
-
- level++;
- *len = 0;
- switch (NTYPE(node)) {
- case N_LIST:
- do {
- r = get_char_length_tree1(NCONS(node).left, reg, &tlen, level);
- if (r == 0)
- *len = distance_add(*len, tlen);
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- case N_ALT:
- {
- int tlen2;
- int varlen = 0;
-
- r = get_char_length_tree1(NCONS(node).left, reg, &tlen, level);
- while (r == 0 && IS_NOT_NULL(node = NCONS(node).right)) {
- r = get_char_length_tree1(NCONS(node).left, reg, &tlen2, level);
- if (r == 0) {
- if (tlen != tlen2)
- varlen = 1;
- }
- }
- if (r == 0) {
- if (varlen != 0) {
- if (level == 1)
- r = GET_CHAR_LEN_TOP_ALT_VARLEN;
- else
- r = GET_CHAR_LEN_VARLEN;
- }
- else
- *len = tlen;
- }
- }
- break;
-
- case N_STRING:
- {
- StrNode* sn = &(NSTRING(node));
- UChar *s = sn->s;
- while (s < sn->end) {
- s += enc_len(reg->enc, s);
- (*len)++;
- }
- }
- break;
-
- case N_QUALIFIER:
- {
- QualifierNode* qn = &(NQUALIFIER(node));
- if (qn->lower == qn->upper) {
- r = get_char_length_tree1(qn->target, reg, &tlen, level);
- if (r == 0)
- *len = distance_multiply(tlen, qn->lower);
- }
- else
- r = GET_CHAR_LEN_VARLEN;
- }
- break;
-
-#ifdef USE_SUBEXP_CALL
- case N_CALL:
- if (! IS_CALL_RECURSION(&(NCALL(node))))
- r = get_char_length_tree1(NCALL(node).target, reg, len, level);
- else
- r = GET_CHAR_LEN_VARLEN;
- break;
-#endif
-
- case N_CTYPE:
- switch (NCTYPE(node).type) {
- case CTYPE_WORD:
- case CTYPE_NOT_WORD:
- *len = 1;
- break;
- }
- break;
-
- case N_CCLASS:
- case N_ANYCHAR:
- *len = 1;
- break;
-
- case N_EFFECT:
- {
- EffectNode* en = &(NEFFECT(node));
- switch (en->type) {
- case EFFECT_MEMORY:
-#ifdef USE_SUBEXP_CALL
- if (IS_EFFECT_CLEN_FIXED(en))
- *len = en->char_len;
- else {
- r = get_char_length_tree1(en->target, reg, len, level);
- if (r == 0) {
- en->char_len = *len;
- SET_EFFECT_STATUS(node, NST_CLEN_FIXED);
- }
- }
- break;
-#endif
- case EFFECT_OPTION:
- case EFFECT_STOP_BACKTRACK:
- r = get_char_length_tree1(en->target, reg, len, level);
- break;
- default:
- break;
- }
- }
- break;
-
- case N_ANCHOR:
- break;
-
- default:
- r = GET_CHAR_LEN_VARLEN;
- break;
- }
-
- return r;
-}
-
-static int
-get_char_length_tree(Node* node, regex_t* reg, int* len)
-{
- return get_char_length_tree1(node, reg, len, 0);
-}
-
-extern int
-onig_is_code_in_cc(OnigEncoding enc, OnigCodePoint code, CClassNode* cc)
-{
- int found;
-
- if (ONIGENC_MBC_MINLEN(enc) > 1 || (code >= SINGLE_BYTE_SIZE)) {
- if (IS_NULL(cc->mbuf)) {
- found = 0;
- }
- else {
- found = (onig_is_in_code_range(cc->mbuf->p, code) != 0 ? 1 : 0);
- }
- }
- else {
- found = (BITSET_AT(cc->bs, code) == 0 ? 0 : 1);
- }
-
- if (IS_CCLASS_NOT(cc))
- return !found;
- else
- return found;
-}
-
-/* x is not included y ==> 1 : 0 */
-static int
-is_not_included(Node* x, Node* y, regex_t* reg)
-{
- int i, len;
- OnigCodePoint code;
- UChar *p, c;
- int ytype;
-
- retry:
- ytype = NTYPE(y);
- switch (NTYPE(x)) {
- case N_CTYPE:
- {
- switch (ytype) {
- case N_CTYPE:
- switch (NCTYPE(x).type) {
- case CTYPE_WORD:
- if (NCTYPE(y).type == CTYPE_NOT_WORD)
- return 1;
- else
- return 0;
- break;
- case CTYPE_NOT_WORD:
- if (NCTYPE(y).type == CTYPE_WORD)
- return 1;
- else
- return 0;
- break;
- default:
- break;
- }
- break;
-
- case N_CCLASS:
- swap:
- {
- Node* tmp;
- tmp = x; x = y; y = tmp;
- goto retry;
- }
- break;
-
- case N_STRING:
- goto swap;
- break;
-
- default:
- break;
- }
- }
- break;
-
- case N_CCLASS:
- {
- CClassNode* xc = &(NCCLASS(x));
- switch (ytype) {
- case N_CTYPE:
- switch (NCTYPE(y).type) {
- case CTYPE_WORD:
- if (IS_NULL(xc->mbuf) && !IS_CCLASS_NOT(xc)) {
- for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
- if (BITSET_AT(xc->bs, i)) {
- if (ONIGENC_IS_CODE_SB_WORD(reg->enc, i)) return 0;
- }
- }
- return 1;
- }
- return 0;
- break;
- case CTYPE_NOT_WORD:
- for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
- if (! ONIGENC_IS_CODE_SB_WORD(reg->enc, i)) {
- if (!IS_CCLASS_NOT(xc)) {
- if (BITSET_AT(xc->bs, i))
- return 0;
- }
- else {
- if (! BITSET_AT(xc->bs, i))
- return 0;
- }
- }
- }
- return 1;
- break;
-
- default:
- break;
- }
- break;
-
- case N_CCLASS:
- {
- int v;
- CClassNode* yc = &(NCCLASS(y));
-
- for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
- v = BITSET_AT(xc->bs, i);
- if ((v != 0 && !IS_CCLASS_NOT(xc)) ||
- (v == 0 && IS_CCLASS_NOT(xc))) {
- v = BITSET_AT(yc->bs, i);
- if ((v != 0 && !IS_CCLASS_NOT(yc)) ||
- (v == 0 && IS_CCLASS_NOT(yc)))
- return 0;
- }
- }
- if ((IS_NULL(xc->mbuf) && !IS_CCLASS_NOT(xc)) ||
- (IS_NULL(yc->mbuf) && !IS_CCLASS_NOT(yc)))
- return 1;
- return 0;
- }
- break;
-
- case N_STRING:
- goto swap;
- break;
-
- default:
- break;
- }
- }
- break;
-
- case N_STRING:
- {
- StrNode* xs = &(NSTRING(x));
- if (NSTRING_LEN(x) == 0)
- break;
-
- c = *(xs->s);
- switch (ytype) {
- case N_CTYPE:
- switch (NCTYPE(y).type) {
- case CTYPE_WORD:
- return (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end) ? 0 : 1);
- break;
- case CTYPE_NOT_WORD:
- return (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end) ? 1 : 0);
- break;
- default:
- break;
- }
- break;
-
- case N_CCLASS:
- {
- CClassNode* cc = &(NCCLASS(y));
-
- code = ONIGENC_MBC_TO_CODE(reg->enc, xs->s,
- xs->s + ONIGENC_MBC_MAXLEN(reg->enc));
- return (onig_is_code_in_cc(reg->enc, code, cc) != 0 ? 0 : 1);
- }
- break;
-
- case N_STRING:
- {
- UChar *q;
- StrNode* ys = &(NSTRING(y));
- len = NSTRING_LEN(x);
- if (len > NSTRING_LEN(y)) len = NSTRING_LEN(y);
- if (NSTRING_IS_AMBIG(x) || NSTRING_IS_AMBIG(y)) {
- /* tiny version */
- return 0;
- }
- else {
- for (i = 0, p = ys->s, q = xs->s; i < len; i++, p++, q++) {
- if (*p != *q) return 1;
- }
- }
- }
- break;
-
- default:
- break;
- }
- }
- break;
-
- default:
- break;
- }
-
- return 0;
-}
-
-static Node*
-get_head_value_node(Node* node, int exact, regex_t* reg)
-{
- Node* n = NULL_NODE;
-
- switch (NTYPE(node)) {
- case N_BACKREF:
- case N_ALT:
- case N_ANYCHAR:
-#ifdef USE_SUBEXP_CALL
- case N_CALL:
-#endif
- break;
-
- case N_CTYPE:
- case N_CCLASS:
- if (exact == 0) {
- n = node;
- }
- break;
-
- case N_LIST:
- n = get_head_value_node(NCONS(node).left, exact, reg);
- break;
-
- case N_STRING:
- {
- StrNode* sn = &(NSTRING(node));
-
- if (sn->end <= sn->s)
- break;
-
- if (exact != 0 &&
- !NSTRING_IS_RAW(node) && IS_IGNORECASE(reg->options)) {
-#if 0
- UChar* tmp = sn->s;
- if (! ONIGENC_IS_MBC_AMBIGUOUS(reg->enc, reg->ambig_flag,
- &tmp, sn->end))
- n = node;
-#endif
- }
- else {
- n = node;
- }
- }
- break;
-
- case N_QUALIFIER:
- {
- QualifierNode* qn = &(NQUALIFIER(node));
- if (qn->lower > 0) {
- if (IS_NOT_NULL(qn->head_exact))
- n = qn->head_exact;
- else
- n = get_head_value_node(qn->target, exact, reg);
- }
- }
- break;
-
- case N_EFFECT:
- {
- EffectNode* en = &(NEFFECT(node));
- switch (en->type) {
- case EFFECT_OPTION:
- {
- OnigOptionType options = reg->options;
-
- reg->options = NEFFECT(node).option;
- n = get_head_value_node(NEFFECT(node).target, exact, reg);
- reg->options = options;
- }
- break;
-
- case EFFECT_MEMORY:
- case EFFECT_STOP_BACKTRACK:
- n = get_head_value_node(en->target, exact, reg);
- break;
- }
- }
- break;
-
- case N_ANCHOR:
- if (NANCHOR(node).type == ANCHOR_PREC_READ)
- n = get_head_value_node(NANCHOR(node).target, exact, reg);
- break;
-
- default:
- break;
- }
-
- return n;
-}
-
-static int
-check_type_tree(Node* node, int type_mask, int effect_mask, int anchor_mask)
-{
- int type, r = 0;
-
- type = NTYPE(node);
- if ((type & type_mask) == 0)
- return 1;
-
- switch (type) {
- case N_LIST:
- case N_ALT:
- do {
- r = check_type_tree(NCONS(node).left, type_mask, effect_mask, anchor_mask);
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- case N_QUALIFIER:
- r = check_type_tree(NQUALIFIER(node).target, type_mask, effect_mask,
- anchor_mask);
- break;
-
- case N_EFFECT:
- {
- EffectNode* en = &(NEFFECT(node));
- if ((en->type & effect_mask) == 0)
- return 1;
-
- r = check_type_tree(en->target, type_mask, effect_mask, anchor_mask);
- }
- break;
-
- case N_ANCHOR:
- type = NANCHOR(node).type;
- if ((type & anchor_mask) == 0)
- return 1;
-
- if (NANCHOR(node).target)
- r = check_type_tree(NANCHOR(node).target,
- type_mask, effect_mask, anchor_mask);
- break;
-
- default:
- break;
- }
- return r;
-}
-
-#ifdef USE_SUBEXP_CALL
-
-#define RECURSION_EXIST 1
-#define RECURSION_INFINITE 2
-
-static int
-subexp_inf_recursive_check(Node* node, ScanEnv* env, int head)
-{
- int type;
- int r = 0;
-
- type = NTYPE(node);
- switch (type) {
- case N_LIST:
- {
- Node *x;
- OnigDistance min;
- int ret;
-
- x = node;
- do {
- ret = subexp_inf_recursive_check(NCONS(x).left, env, head);
- if (ret < 0 || ret == RECURSION_INFINITE) return ret;
- r |= ret;
- if (head) {
- ret = get_min_match_length(NCONS(x).left, &min, env);
- if (ret != 0) return ret;
- if (min != 0) head = 0;
- }
- } while (IS_NOT_NULL(x = NCONS(x).right));
- }
- break;
-
- case N_ALT:
- {
- int ret;
- r = RECURSION_EXIST;
- do {
- ret = subexp_inf_recursive_check(NCONS(node).left, env, head);
- if (ret < 0 || ret == RECURSION_INFINITE) return ret;
- r &= ret;
- } while (IS_NOT_NULL(node = NCONS(node).right));
- }
- break;
-
- case N_QUALIFIER:
- r = subexp_inf_recursive_check(NQUALIFIER(node).target, env, head);
- break;
-
- case N_ANCHOR:
- {
- AnchorNode* an = &(NANCHOR(node));
- switch (an->type) {
- case ANCHOR_PREC_READ:
- case ANCHOR_PREC_READ_NOT:
- case ANCHOR_LOOK_BEHIND:
- case ANCHOR_LOOK_BEHIND_NOT:
- r = subexp_inf_recursive_check(an->target, env, head);
- break;
- }
- }
- break;
-
- case N_CALL:
- r = subexp_inf_recursive_check(NCALL(node).target, env, head);
- break;
-
- case N_EFFECT:
- if (IS_EFFECT_MARK2(&(NEFFECT(node))))
- return 0;
- else if (IS_EFFECT_MARK1(&(NEFFECT(node))))
- return (head == 0 ? RECURSION_EXIST : RECURSION_INFINITE);
- else {
- SET_EFFECT_STATUS(node, NST_MARK2);
- r = subexp_inf_recursive_check(NEFFECT(node).target, env, head);
- CLEAR_EFFECT_STATUS(node, NST_MARK2);
- }
- break;
-
- default:
- break;
- }
-
- return r;
-}
-
-static int
-subexp_inf_recursive_check_trav(Node* node, ScanEnv* env)
-{
- int type;
- int r = 0;
-
- type = NTYPE(node);
- switch (type) {
- case N_LIST:
- case N_ALT:
- do {
- r = subexp_inf_recursive_check_trav(NCONS(node).left, env);
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- case N_QUALIFIER:
- r = subexp_inf_recursive_check_trav(NQUALIFIER(node).target, env);
- break;
-
- case N_ANCHOR:
- {
- AnchorNode* an = &(NANCHOR(node));
- switch (an->type) {
- case ANCHOR_PREC_READ:
- case ANCHOR_PREC_READ_NOT:
- case ANCHOR_LOOK_BEHIND:
- case ANCHOR_LOOK_BEHIND_NOT:
- r = subexp_inf_recursive_check_trav(an->target, env);
- break;
- }
- }
- break;
-
- case N_EFFECT:
- {
- EffectNode* en = &(NEFFECT(node));
-
- if (IS_EFFECT_RECURSION(en)) {
- SET_EFFECT_STATUS(node, NST_MARK1);
- r = subexp_inf_recursive_check(en->target, env, 1);
- if (r > 0) return ONIGERR_NEVER_ENDING_RECURSION;
- CLEAR_EFFECT_STATUS(node, NST_MARK1);
- }
- r = subexp_inf_recursive_check_trav(en->target, env);
- }
-
- break;
-
- default:
- break;
- }
-
- return r;
-}
-
-static int
-subexp_recursive_check(Node* node)
-{
- int type;
- int r = 0;
-
- type = NTYPE(node);
- switch (type) {
- case N_LIST:
- case N_ALT:
- do {
- r |= subexp_recursive_check(NCONS(node).left);
- } while (IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- case N_QUALIFIER:
- r = subexp_recursive_check(NQUALIFIER(node).target);
- break;
-
- case N_ANCHOR:
- {
- AnchorNode* an = &(NANCHOR(node));
- switch (an->type) {
- case ANCHOR_PREC_READ:
- case ANCHOR_PREC_READ_NOT:
- case ANCHOR_LOOK_BEHIND:
- case ANCHOR_LOOK_BEHIND_NOT:
- r = subexp_recursive_check(an->target);
- break;
- }
- }
- break;
-
- case N_CALL:
- r = subexp_recursive_check(NCALL(node).target);
- if (r != 0) SET_CALL_RECURSION(node);
- break;
-
- case N_EFFECT:
- if (IS_EFFECT_MARK2(&(NEFFECT(node))))
- return 0;
- else if (IS_EFFECT_MARK1(&(NEFFECT(node))))
- return 1; /* recursion */
- else {
- SET_EFFECT_STATUS(node, NST_MARK2);
- r = subexp_recursive_check(NEFFECT(node).target);
- CLEAR_EFFECT_STATUS(node, NST_MARK2);
- }
- break;
-
- default:
- break;
- }
-
- return r;
-}
-
-
-static int
-subexp_recursive_check_trav(Node* node, ScanEnv* env)
-{
-#define FOUND_CALLED_NODE 1
-
- int type;
- int r = 0;
-
- type = NTYPE(node);
- switch (type) {
- case N_LIST:
- case N_ALT:
- {
- int ret;
- do {
- ret = subexp_recursive_check_trav(NCONS(node).left, env);
- if (ret == FOUND_CALLED_NODE) r = FOUND_CALLED_NODE;
- else if (ret < 0) return ret;
- } while (IS_NOT_NULL(node = NCONS(node).right));
- }
- break;
-
- case N_QUALIFIER:
- r = subexp_recursive_check_trav(NQUALIFIER(node).target, env);
- if (NQUALIFIER(node).upper == 0) {
- if (r == FOUND_CALLED_NODE)
- NQUALIFIER(node).is_refered = 1;
- }
- break;
-
- case N_ANCHOR:
- {
- AnchorNode* an = &(NANCHOR(node));
- switch (an->type) {
- case ANCHOR_PREC_READ:
- case ANCHOR_PREC_READ_NOT:
- case ANCHOR_LOOK_BEHIND:
- case ANCHOR_LOOK_BEHIND_NOT:
- r = subexp_recursive_check_trav(an->target, env);
- break;
- }
- }
- break;
-
- case N_EFFECT:
- {
- EffectNode* en = &(NEFFECT(node));
-
- if (! IS_EFFECT_RECURSION(en)) {
- if (IS_EFFECT_CALLED(en)) {
- SET_EFFECT_STATUS(node, NST_MARK1);
- r = subexp_recursive_check(en->target);
- if (r != 0) SET_EFFECT_STATUS(node, NST_RECURSION);
- CLEAR_EFFECT_STATUS(node, NST_MARK1);
- }
- }
- r = subexp_recursive_check_trav(en->target, env);
- if (IS_EFFECT_CALLED(en))
- r |= FOUND_CALLED_NODE;
- }
- break;
-
- default:
- break;
- }
-
- return r;
-}
-
-static int
-setup_subexp_call(Node* node, ScanEnv* env)
-{
- int type;
- int r = 0;
-
- type = NTYPE(node);
- switch (type) {
- case N_LIST:
- do {
- r = setup_subexp_call(NCONS(node).left, env);
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- case N_ALT:
- do {
- r = setup_subexp_call(NCONS(node).left, env);
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- case N_QUALIFIER:
- r = setup_subexp_call(NQUALIFIER(node).target, env);
- break;
- case N_EFFECT:
- r = setup_subexp_call(NEFFECT(node).target, env);
- break;
-
- case N_CALL:
- {
- int n, num, *refs;
- UChar *p;
- CallNode* cn = &(NCALL(node));
- Node** nodes = SCANENV_MEM_NODES(env);
-
-#ifdef USE_NAMED_GROUP
- n = onig_name_to_group_numbers(env->reg, cn->name, cn->name_end, &refs);
-#else
- n = -1;
-#endif
- if (n <= 0) {
- /* name not found, check group number. (?*ddd) */
- p = cn->name;
- num = onig_scan_unsigned_number(&p, cn->name_end, env->enc);
- if (num <= 0 || p != cn->name_end) {
- onig_scan_env_set_error_string(env,
- ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);
- return ONIGERR_UNDEFINED_NAME_REFERENCE;
- }
-#ifdef USE_NAMED_GROUP
- if (env->num_named > 0 &&
- IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
- !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) {
- return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
- }
-#endif
- if (num > env->num_mem) {
- onig_scan_env_set_error_string(env,
- ONIGERR_UNDEFINED_GROUP_REFERENCE, cn->name, cn->name_end);
- return ONIGERR_UNDEFINED_GROUP_REFERENCE;
- }
- cn->ref_num = num;
- goto set_call_attr;
- }
- else if (n > 1) {
- onig_scan_env_set_error_string(env,
- ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL, cn->name, cn->name_end);
- return ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL;
- }
- else {
- cn->ref_num = refs[0];
- set_call_attr:
- cn->target = nodes[cn->ref_num];
- if (IS_NULL(cn->target)) {
- onig_scan_env_set_error_string(env,
- ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);
- return ONIGERR_UNDEFINED_NAME_REFERENCE;
- }
- SET_EFFECT_STATUS(cn->target, NST_CALLED);
- BIT_STATUS_ON_AT(env->bt_mem_start, cn->ref_num);
- cn->unset_addr_list = env->unset_addr_list;
- }
- }
- break;
-
- case N_ANCHOR:
- {
- AnchorNode* an = &(NANCHOR(node));
-
- switch (an->type) {
- case ANCHOR_PREC_READ:
- case ANCHOR_PREC_READ_NOT:
- case ANCHOR_LOOK_BEHIND:
- case ANCHOR_LOOK_BEHIND_NOT:
- r = setup_subexp_call(an->target, env);
- break;
- }
- }
- break;
-
- default:
- break;
- }
-
- return r;
-}
-#endif
-
-/* divide different length alternatives in look-behind.
- (?<=A|B) ==> (?<=A)|(?<=B)
- (?<!A|B) ==> (?<!A)(?<!B)
-*/
-static int
-divide_look_behind_alternatives(Node* node)
-{
- Node tmp_node;
- Node *head, *np, *insert_node;
- AnchorNode* an = &(NANCHOR(node));
- int anc_type = an->type;
-
- head = an->target;
- np = NCONS(head).left;
- tmp_node = *node; *node = *head; *head = tmp_node;
- NCONS(node).left = head;
- NANCHOR(head).target = np;
-
- np = node;
- while ((np = NCONS(np).right) != NULL_NODE) {
- insert_node = onig_node_new_anchor(anc_type);
- CHECK_NULL_RETURN_VAL(insert_node, ONIGERR_MEMORY);
- NANCHOR(insert_node).target = NCONS(np).left;
- NCONS(np).left = insert_node;
- }
-
- if (anc_type == ANCHOR_LOOK_BEHIND_NOT) {
- np = node;
- do {
- np->type = N_LIST; /* alt -> list */
- } while ((np = NCONS(np).right) != NULL_NODE);
- }
- return 0;
-}
-
-static int
-setup_look_behind(Node* node, regex_t* reg, ScanEnv* env)
-{
- int r, len;
- AnchorNode* an = &(NANCHOR(node));
-
- r = get_char_length_tree(an->target, reg, &len);
- if (r == 0)
- an->char_len = len;
- else if (r == GET_CHAR_LEN_VARLEN)
- r = ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
- else if (r == GET_CHAR_LEN_TOP_ALT_VARLEN) {
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND))
- r = divide_look_behind_alternatives(node);
- else
- r = ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
- }
-
- return r;
-}
-
-static int
-next_setup(Node* node, Node* next_node, regex_t* reg)
-{
- int type;
-
- retry:
- type = NTYPE(node);
- if (type == N_QUALIFIER) {
- QualifierNode* qn = &(NQUALIFIER(node));
- if (qn->greedy && IS_REPEAT_INFINITE(qn->upper)) {
-#ifdef USE_QUALIFIER_PEEK_NEXT
- qn->next_head_exact = get_head_value_node(next_node, 1, reg);
-#endif
- /* automatic posseivation a*b ==> (?>a*)b */
- if (qn->lower <= 1) {
- int ttype = NTYPE(qn->target);
- if (IS_NODE_TYPE_SIMPLE(ttype)) {
- Node *x, *y;
- x = get_head_value_node(qn->target, 0, reg);
- if (IS_NOT_NULL(x)) {
- y = get_head_value_node(next_node, 0, reg);
- if (IS_NOT_NULL(y) && is_not_included(x, y, reg)) {
- Node* en = onig_node_new_effect(EFFECT_STOP_BACKTRACK);
- CHECK_NULL_RETURN_VAL(en, ONIGERR_MEMORY);
- SET_EFFECT_STATUS(en, NST_STOP_BT_SIMPLE_REPEAT);
- swap_node(node, en);
- NEFFECT(node).target = en;
- }
- }
- }
- }
- }
- }
- else if (type == N_EFFECT) {
- EffectNode* en = &(NEFFECT(node));
- if (en->type == EFFECT_MEMORY) {
- node = en->target;
- goto retry;
- }
- }
- return 0;
-}
-
-static int
-divide_ambig_string_node(Node* node, regex_t* reg)
-{
- StrNode* sn = &NSTRING(node);
- int ambig, prev_ambig;
- UChar *prev, *p, *end, *prev_start, *start, *tmp, *wp;
- Node *snode;
- Node *root = NULL_NODE;
- Node **tailp = (Node** )0;
-
- start = prev_start = p = sn->s;
- end = sn->end;
- if (p >= end) return 0;
-
- prev_ambig = ONIGENC_IS_MBC_AMBIGUOUS(reg->enc, reg->ambig_flag, &p, end);
-
- while (p < end) {
- prev = p;
- if (prev_ambig != (ambig = ONIGENC_IS_MBC_AMBIGUOUS(reg->enc,
- reg->ambig_flag, &p, end))) {
-
- if (prev_ambig != 0) {
- tmp = prev_start;
- wp = prev_start;
- while (tmp < prev) {
- wp += ONIGENC_MBC_TO_NORMALIZE(reg->enc, reg->ambig_flag,
- &tmp, end, wp);
- }
- snode = onig_node_new_str(prev_start, wp);
- CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY);
- NSTRING_SET_AMBIG(snode);
- if (wp != prev) NSTRING_SET_AMBIG_REDUCE(snode);
- }
- else {
- snode = onig_node_new_str(prev_start, prev);
- CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY);
- }
-
- if (tailp == (Node** )0) {
- root = onig_node_new_list(snode, NULL);
- CHECK_NULL_RETURN_VAL(root, ONIGERR_MEMORY);
- tailp = &(NCONS(root).right);
- }
- else {
- *tailp = onig_node_new_list(snode, NULL);
- CHECK_NULL_RETURN_VAL(*tailp, ONIGERR_MEMORY);
- tailp = &(NCONS(*tailp).right);
- }
-
- prev_ambig = ambig;
- prev_start = prev;
- }
- }
-
- if (prev_start == start) {
- if (prev_ambig != 0) {
- NSTRING_SET_AMBIG(node);
- tmp = start;
- wp = start;
- while (tmp < end) {
- wp += ONIGENC_MBC_TO_NORMALIZE(reg->enc, reg->ambig_flag,
- &tmp, end, wp);
- }
- if (wp != sn->end) NSTRING_SET_AMBIG_REDUCE(node);
- sn->end = wp;
- }
- }
- else {
- if (prev_ambig != 0) {
- tmp = prev_start;
- wp = prev_start;
- while (tmp < end) {
- wp += ONIGENC_MBC_TO_NORMALIZE(reg->enc, reg->ambig_flag,
- &tmp, end, wp);
- }
- snode = onig_node_new_str(prev_start, wp);
- CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY);
- NSTRING_SET_AMBIG(snode);
- if (wp != end) NSTRING_SET_AMBIG_REDUCE(snode);
- }
- else {
- snode = onig_node_new_str(prev_start, end);
- CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY);
- }
-
- if (tailp == (Node** )0) {
- root = onig_node_new_list(snode, NULL);
- CHECK_NULL_RETURN_VAL(root, ONIGERR_MEMORY);
- tailp = &(NCONS(node).right);
- }
- else {
- *tailp = onig_node_new_list(snode, NULL);
- CHECK_NULL_RETURN_VAL(*tailp, ONIGERR_MEMORY);
- tailp = &(NCONS(*tailp).right);
- }
-
- swap_node(node, root);
- onig_node_str_clear(root); /* should be after swap! */
- onig_node_free(root); /* free original string node */
- }
-
- return 0;
-}
-
-#define IN_ALT (1<<0)
-#define IN_NOT (1<<1)
-#define IN_REPEAT (1<<2)
-#define IN_VAR_REPEAT (1<<3)
-
-/* setup_tree does the following work.
- 1. check empty loop. (set qn->target_empty_info)
- 2. expand ignore-case in char class.
- 3. set memory status bit flags. (reg->mem_stats)
- 4. set qn->head_exact for [push, exact] -> [push_or_jump_exact1, exact].
- 5. find invalid patterns in look-behind.
- 6. expand repeated string.
- */
-static int
-setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env)
-{
- int type;
- int r = 0;
-
- type = NTYPE(node);
- switch (type) {
- case N_LIST:
- {
- Node* prev = NULL_NODE;
- do {
- r = setup_tree(NCONS(node).left, reg, state, env);
- if (IS_NOT_NULL(prev) && r == 0) {
- r = next_setup(prev, NCONS(node).left, reg);
- }
- prev = NCONS(node).left;
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- }
- break;
-
- case N_ALT:
- do {
- r = setup_tree(NCONS(node).left, reg, (state | IN_ALT), env);
- } while (r == 0 && IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- case N_CCLASS:
- break;
-
- case N_STRING:
- if (IS_IGNORECASE(reg->options) && !NSTRING_IS_RAW(node)) {
- r = divide_ambig_string_node(node, reg);
- }
- break;
-
- case N_CTYPE:
- case N_ANYCHAR:
- break;
-
-#ifdef USE_SUBEXP_CALL
- case N_CALL:
- break;
-#endif
-
- case N_BACKREF:
- {
- int i;
- int* p;
- Node** nodes = SCANENV_MEM_NODES(env);
- BackrefNode* br = &(NBACKREF(node));
- p = BACKREFS_P(br);
- for (i = 0; i < br->back_num; i++) {
- if (p[i] > env->num_mem) return ONIGERR_INVALID_BACKREF;
- BIT_STATUS_ON_AT(env->backrefed_mem, p[i]);
- BIT_STATUS_ON_AT(env->bt_mem_start, p[i]);
- SET_EFFECT_STATUS(nodes[p[i]], NST_MEM_BACKREFED);
- }
- }
- break;
-
- case N_QUALIFIER:
- {
- OnigDistance d;
- QualifierNode* qn = &(NQUALIFIER(node));
- Node* target = qn->target;
-
- if ((state & IN_REPEAT) != 0) {
- qn->state |= NST_IN_REPEAT;
- }
-
- if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 1) {
- r = get_min_match_length(target, &d, env);
- if (r) break;
- if (d == 0) {
- qn->target_empty_info = NQ_TARGET_IS_EMPTY;
-#ifdef USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
- r = qualifiers_memory_node_info(target);
- if (r < 0) break;
- if (r > 0) {
- qn->target_empty_info = r;
- }
-#endif
-#if 0
- r = get_max_match_length(target, &d, env);
- if (r == 0 && d == 0) {
- /* ()* ==> ()?, ()+ ==> () */
- qn->upper = 1;
- if (qn->lower > 1) qn->lower = 1;
- if (NTYPE(target) == N_STRING) {
- qn->upper = qn->lower = 0; /* /(?:)+/ ==> // */
- }
- }
-#endif
- }
- }
-
- state |= IN_REPEAT;
- if (qn->lower != qn->upper)
- state |= IN_VAR_REPEAT;
- r = setup_tree(target, reg, state, env);
- if (r) break;
-
- /* expand string */
-#define EXPAND_STRING_MAX_LENGTH 100
- if (NTYPE(target) == N_STRING) {
- if (!IS_REPEAT_INFINITE(qn->lower) && qn->lower == qn->upper &&
- qn->lower > 1 && qn->lower <= EXPAND_STRING_MAX_LENGTH) {
- int len = NSTRING_LEN(target);
- StrNode* sn = &(NSTRING(target));
-
- if (len * qn->lower <= EXPAND_STRING_MAX_LENGTH) {
- int i, n = qn->lower;
- onig_node_conv_to_str_node(node, NSTRING(target).flag);
- for (i = 0; i < n; i++) {
- r = onig_node_str_cat(node, sn->s, sn->end);
- if (r) break;
- }
- onig_node_free(target);
- break; /* break case N_QUALIFIER: */
- }
- }
- }
-
-#ifdef USE_OP_PUSH_OR_JUMP_EXACT
- if (qn->greedy && (qn->target_empty_info != 0)) {
- if (NTYPE(target) == N_QUALIFIER) {
- QualifierNode* tqn = &(NQUALIFIER(target));
- if (IS_NOT_NULL(tqn->head_exact)) {
- qn->head_exact = tqn->head_exact;
- tqn->head_exact = NULL;
- }
- }
- else {
- qn->head_exact = get_head_value_node(qn->target, 1, reg);
- }
- }
-#endif
- }
- break;
-
- case N_EFFECT:
- {
- EffectNode* en = &(NEFFECT(node));
-
- switch (en->type) {
- case EFFECT_OPTION:
- {
- OnigOptionType options = reg->options;
- reg->options = NEFFECT(node).option;
- r = setup_tree(NEFFECT(node).target, reg, state, env);
- reg->options = options;
- }
- break;
-
- case EFFECT_MEMORY:
- if ((state & (IN_ALT | IN_NOT | IN_VAR_REPEAT)) != 0) {
- BIT_STATUS_ON_AT(env->bt_mem_start, en->regnum);
- /* SET_EFFECT_STATUS(node, NST_MEM_IN_ALT_NOT); */
- }
- r = setup_tree(en->target, reg, state, env);
- break;
-
- case EFFECT_STOP_BACKTRACK:
- {
- Node* target = en->target;
- r = setup_tree(target, reg, state, env);
- if (NTYPE(target) == N_QUALIFIER) {
- QualifierNode* tqn = &(NQUALIFIER(target));
- if (IS_REPEAT_INFINITE(tqn->upper) && tqn->lower <= 1 &&
- tqn->greedy != 0) { /* (?>a*), a*+ etc... */
- int qtype = NTYPE(tqn->target);
- if (IS_NODE_TYPE_SIMPLE(qtype))
- SET_EFFECT_STATUS(node, NST_STOP_BT_SIMPLE_REPEAT);
- }
- }
- }
- break;
- }
- }
- break;
-
- case N_ANCHOR:
- {
- AnchorNode* an = &(NANCHOR(node));
-
- switch (an->type) {
- case ANCHOR_PREC_READ:
- r = setup_tree(an->target, reg, state, env);
- break;
- case ANCHOR_PREC_READ_NOT:
- r = setup_tree(an->target, reg, (state | IN_NOT), env);
- break;
-
-/* allowed node types in look-behind */
-#define ALLOWED_TYPE_IN_LB \
- ( N_LIST | N_ALT | N_STRING | N_CCLASS | N_CTYPE | \
- N_ANYCHAR | N_ANCHOR | N_EFFECT | N_QUALIFIER | N_CALL )
-
-#define ALLOWED_EFFECT_IN_LB ( EFFECT_MEMORY )
-#define ALLOWED_EFFECT_IN_LB_NOT 0
-
-#define ALLOWED_ANCHOR_IN_LB \
-( ANCHOR_LOOK_BEHIND | ANCHOR_BEGIN_LINE | ANCHOR_END_LINE | ANCHOR_BEGIN_BUF )
-#define ALLOWED_ANCHOR_IN_LB_NOT \
-( ANCHOR_LOOK_BEHIND_NOT | ANCHOR_BEGIN_LINE | ANCHOR_END_LINE | ANCHOR_BEGIN_BUF )
- /* can't allow all anchors, because \G in look-behind through Search().
- ex. /(?<=\G)zz/.match("azz") => success. */
-
- case ANCHOR_LOOK_BEHIND:
- {
- r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,
- ALLOWED_EFFECT_IN_LB, ALLOWED_ANCHOR_IN_LB);
- if (r < 0) return r;
- if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
- r = setup_look_behind(node, reg, env);
- if (r != 0) return r;
- r = setup_tree(an->target, reg, state, env);
- }
- break;
-
- case ANCHOR_LOOK_BEHIND_NOT:
- {
- r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,
- ALLOWED_EFFECT_IN_LB_NOT, ALLOWED_ANCHOR_IN_LB_NOT);
- if (r < 0) return r;
- if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
- r = setup_look_behind(node, reg, env);
- if (r != 0) return r;
- r = setup_tree(an->target, reg, (state | IN_NOT), env);
- }
- break;
- }
- }
- break;
-
- default:
- break;
- }
-
- return r;
-}
-
-/* set skip map for Boyer-Moor search */
-static int
-set_bm_skip(UChar* s, UChar* end, OnigEncoding enc,
- UChar skip[], int** int_skip)
-{
- int i, len;
-
- len = end - s;
- if (len < ONIG_CHAR_TABLE_SIZE) {
- for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) skip[i] = len;
-
- for (i = 0; i < len - 1; i++)
- skip[s[i]] = len - 1 - i;
- }
- else {
- if (IS_NULL(*int_skip)) {
- *int_skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE);
- if (IS_NULL(*int_skip)) return ONIGERR_MEMORY;
- }
- for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) (*int_skip)[i] = len;
-
- for (i = 0; i < len - 1; i++)
- (*int_skip)[s[i]] = len - 1 - i;
- }
- return 0;
-}
-
-#define OPT_EXACT_MAXLEN 24
-
-typedef struct {
- OnigDistance min; /* min byte length */
- OnigDistance max; /* max byte length */
-} MinMaxLen;
-
-typedef struct {
- MinMaxLen mmd;
- OnigEncoding enc;
- OnigOptionType options;
- OnigAmbigType ambig_flag;
- ScanEnv* scan_env;
-} OptEnv;
-
-typedef struct {
- int left_anchor;
- int right_anchor;
-} OptAncInfo;
-
-typedef struct {
- MinMaxLen mmd; /* info position */
- OptAncInfo anc;
-
- int reach_end;
- int ignore_case;
- int len;
- UChar s[OPT_EXACT_MAXLEN];
-} OptExactInfo;
-
-typedef struct {
- MinMaxLen mmd; /* info position */
- OptAncInfo anc;
-
- int value; /* weighted value */
- UChar map[ONIG_CHAR_TABLE_SIZE];
-} OptMapInfo;
-
-typedef struct {
- MinMaxLen len;
-
- OptAncInfo anc;
- OptExactInfo exb; /* boundary */
- OptExactInfo exm; /* middle */
- OptExactInfo expr; /* prec read (?=...) */
-
- OptMapInfo map; /* boundary */
-} NodeOptInfo;
-
-
-static int
-map_position_value(OnigEncoding enc, int i)
-{
- static short int ByteValTable[] = {
- 5, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 10, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 12, 4, 7, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5,
- 5, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 5, 5, 5,
- 5, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 1
- };
-
- if (i < sizeof(ByteValTable)/sizeof(ByteValTable[0])) {
- if (i == 0 && ONIGENC_MBC_MINLEN(enc) > 1)
- return 20;
- else
- return (int )ByteValTable[i];
- }
- else
- return 4; /* Take it easy. */
-}
-
-static int
-distance_value(MinMaxLen* mm)
-{
- /* 1000 / (min-max-dist + 1) */
- static short int dist_vals[] = {
- 1000, 500, 333, 250, 200, 167, 143, 125, 111, 100,
- 91, 83, 77, 71, 67, 63, 59, 56, 53, 50,
- 48, 45, 43, 42, 40, 38, 37, 36, 34, 33,
- 32, 31, 30, 29, 29, 28, 27, 26, 26, 25,
- 24, 24, 23, 23, 22, 22, 21, 21, 20, 20,
- 20, 19, 19, 19, 18, 18, 18, 17, 17, 17,
- 16, 16, 16, 16, 15, 15, 15, 15, 14, 14,
- 14, 14, 14, 14, 13, 13, 13, 13, 13, 13,
- 12, 12, 12, 12, 12, 12, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 10, 10, 10, 10, 10
- };
-
- int d;
-
- if (mm->max == ONIG_INFINITE_DISTANCE) return 0;
-
- d = mm->max - mm->min;
- if (d < sizeof(dist_vals)/sizeof(dist_vals[0]))
- /* return dist_vals[d] * 16 / (mm->min + 12); */
- return (int )dist_vals[d];
- else
- return 1;
-}
-
-static int
-comp_distance_value(MinMaxLen* d1, MinMaxLen* d2, int v1, int v2)
-{
- if (v2 <= 0) return -1;
- if (v1 <= 0) return 1;
-
- v1 *= distance_value(d1);
- v2 *= distance_value(d2);
-
- if (v2 > v1) return 1;
- if (v2 < v1) return -1;
-
- if (d2->min < d1->min) return 1;
- if (d2->min > d1->min) return -1;
- return 0;
-}
-
-static int
-is_equal_mml(MinMaxLen* a, MinMaxLen* b)
-{
- return (a->min == b->min && a->max == b->max) ? 1 : 0;
-}
-
-
-static void
-set_mml(MinMaxLen* mml, OnigDistance min, OnigDistance max)
-{
- mml->min = min;
- mml->max = max;
-}
-
-static void
-clear_mml(MinMaxLen* mml)
-{
- mml->min = mml->max = 0;
-}
-
-static void
-copy_mml(MinMaxLen* to, MinMaxLen* from)
-{
- to->min = from->min;
- to->max = from->max;
-}
-
-static void
-add_mml(MinMaxLen* to, MinMaxLen* from)
-{
- to->min = distance_add(to->min, from->min);
- to->max = distance_add(to->max, from->max);
-}
-
-#if 0
-static void
-add_len_mml(MinMaxLen* to, OnigDistance len)
-{
- to->min = distance_add(to->min, len);
- to->max = distance_add(to->max, len);
-}
-#endif
-
-static void
-alt_merge_mml(MinMaxLen* to, MinMaxLen* from)
-{
- if (to->min > from->min) to->min = from->min;
- if (to->max < from->max) to->max = from->max;
-}
-
-static void
-copy_opt_env(OptEnv* to, OptEnv* from)
-{
- *to = *from;
-}
-
-static void
-clear_opt_anc_info(OptAncInfo* anc)
-{
- anc->left_anchor = 0;
- anc->right_anchor = 0;
-}
-
-static void
-copy_opt_anc_info(OptAncInfo* to, OptAncInfo* from)
-{
- *to = *from;
-}
-
-static void
-concat_opt_anc_info(OptAncInfo* to, OptAncInfo* left, OptAncInfo* right,
- OnigDistance left_len, OnigDistance right_len)
-{
- clear_opt_anc_info(to);
-
- to->left_anchor = left->left_anchor;
- if (left_len == 0) {
- to->left_anchor |= right->left_anchor;
- }
-
- to->right_anchor = right->right_anchor;
- if (right_len == 0) {
- to->right_anchor |= left->right_anchor;
- }
-}
-
-static int
-is_left_anchor(int anc)
-{
- if (anc == ANCHOR_END_BUF || anc == ANCHOR_SEMI_END_BUF ||
- anc == ANCHOR_END_LINE || anc == ANCHOR_PREC_READ ||
- anc == ANCHOR_PREC_READ_NOT)
- return 0;
-
- return 1;
-}
-
-static int
-is_set_opt_anc_info(OptAncInfo* to, int anc)
-{
- if ((to->left_anchor & anc) != 0) return 1;
-
- return ((to->right_anchor & anc) != 0 ? 1 : 0);
-}
-
-static void
-add_opt_anc_info(OptAncInfo* to, int anc)
-{
- if (is_left_anchor(anc))
- to->left_anchor |= anc;
- else
- to->right_anchor |= anc;
-}
-
-static void
-remove_opt_anc_info(OptAncInfo* to, int anc)
-{
- if (is_left_anchor(anc))
- to->left_anchor &= ~anc;
- else
- to->right_anchor &= ~anc;
-}
-
-static void
-alt_merge_opt_anc_info(OptAncInfo* to, OptAncInfo* add)
-{
- to->left_anchor &= add->left_anchor;
- to->right_anchor &= add->right_anchor;
-}
-
-static int
-is_full_opt_exact_info(OptExactInfo* ex)
-{
- return (ex->len >= OPT_EXACT_MAXLEN ? 1 : 0);
-}
-
-static void
-clear_opt_exact_info(OptExactInfo* ex)
-{
- clear_mml(&ex->mmd);
- clear_opt_anc_info(&ex->anc);
- ex->reach_end = 0;
- ex->ignore_case = 0;
- ex->len = 0;
- ex->s[0] = '\0';
-}
-
-static void
-copy_opt_exact_info(OptExactInfo* to, OptExactInfo* from)
-{
- *to = *from;
-}
-
-static void
-concat_opt_exact_info(OptExactInfo* to, OptExactInfo* add)
-{
- int i, n;
- OptAncInfo tanc;
-
- if (! to->ignore_case && add->ignore_case) {
- if (to->len >= add->len) return ; /* avoid */
-
- to->ignore_case = 1;
- }
-
- for (i = to->len, n = 0; n < add->len && i < OPT_EXACT_MAXLEN; i++, n++)
- to->s[i] = add->s[n];
-
- to->len = i;
- to->reach_end = (n == add->len ? add->reach_end : 0);
-
- concat_opt_anc_info(&tanc, &to->anc, &add->anc, 1, 1);
- if (! to->reach_end) tanc.right_anchor = 0;
- copy_opt_anc_info(&to->anc, &tanc);
-}
-
-static void
-concat_opt_exact_info_str(OptExactInfo* to,
- UChar* s, UChar* end, int raw, OnigEncoding enc)
-{
- int i, j, len;
- UChar *p;
-
- for (i = to->len, p = s; p < end && i < OPT_EXACT_MAXLEN; ) {
- if (raw) {
- to->s[i++] = *p++;
- }
- else {
- len = enc_len(enc, p);
- if (i + len > OPT_EXACT_MAXLEN) break;
- for (j = 0; j < len; j++)
- to->s[i++] = *p++;
- }
- }
-
- to->len = i;
-}
-
-static void
-alt_merge_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OptEnv* env)
-{
- int i, j, len;
-
- if (add->len == 0 || to->len == 0) {
- clear_opt_exact_info(to);
- return ;
- }
-
- if (! is_equal_mml(&to->mmd, &add->mmd)) {
- clear_opt_exact_info(to);
- return ;
- }
-
- for (i = 0; i < to->len && i < add->len; ) {
- if (to->s[i] != add->s[i]) break;
- len = enc_len(env->enc, to->s + i);
-
- for (j = 1; j < len; j++) {
- if (to->s[i+j] != add->s[i+j]) break;
- }
- if (j < len) break;
- i += len;
- }
-
- if (! add->reach_end || i < add->len || i < to->len) {
- to->reach_end = 0;
- }
- to->len = i;
- to->ignore_case |= add->ignore_case;
-
- alt_merge_opt_anc_info(&to->anc, &add->anc);
- if (! to->reach_end) to->anc.right_anchor = 0;
-}
-
-static void
-select_opt_exact_info(OnigEncoding enc, OptExactInfo* now, OptExactInfo* alt)
-{
- int v1, v2;
-
- v1 = now->len;
- v2 = alt->len;
-
- if (v1 <= 2 && v2 <= 2) {
- /* ByteValTable[x] is big value --> low price */
- v2 = map_position_value(enc, now->s[0]);
- v1 = map_position_value(enc, alt->s[0]);
-
- if (now->len > 1) v1 += 5;
- if (alt->len > 1) v2 += 5;
- }
-
- if (now->ignore_case == 0) v1 *= 2;
- if (alt->ignore_case == 0) v2 *= 2;
-
- if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0)
- copy_opt_exact_info(now, alt);
-}
-
-static void
-clear_opt_map_info(OptMapInfo* map)
-{
- static OptMapInfo clean_info = {
- {0, 0}, {0, 0}, 0,
- {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- }
- };
-
- xmemcpy(map, &clean_info, sizeof(OptMapInfo));
-}
-
-static void
-copy_opt_map_info(OptMapInfo* to, OptMapInfo* from)
-{
- *to = *from;
-}
-
-static void
-add_char_opt_map_info(OptMapInfo* map, UChar c, OnigEncoding enc)
-{
- if (map->map[c] == 0) {
- map->map[c] = 1;
- map->value += map_position_value(enc, c);
- }
-}
-
-static int
-add_char_amb_opt_map_info(OptMapInfo* map, UChar* p, UChar* end,
- OnigEncoding enc, OnigAmbigType ambig_flag)
-{
- int i, j, n, len;
- UChar buf[ONIGENC_MBC_NORMALIZE_MAXLEN];
- OnigCodePoint code, ccode;
- OnigCompAmbigCodes* ccs;
- OnigPairAmbigCodes* pccs;
- OnigAmbigType amb;
-
- add_char_opt_map_info(map, p[0], enc);
- code = ONIGENC_MBC_TO_CODE(enc, p, end);
-
- for (amb = 0x01; amb <= ONIGENC_AMBIGUOUS_MATCH_LIMIT; amb <<= 1) {
- if ((amb & ambig_flag) == 0) continue;
-
- n = ONIGENC_GET_ALL_PAIR_AMBIG_CODES(enc, amb, &pccs);
- for (i = 0; i < n; i++) {
- if (pccs[i].from == code) {
- len = ONIGENC_CODE_TO_MBC(enc, pccs[i].to, buf);
- if (len < 0) return len;
- add_char_opt_map_info(map, buf[0], enc);
- }
- }
-
- if ((ambig_flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) {
- n = ONIGENC_GET_ALL_COMP_AMBIG_CODES(enc, amb, &ccs);
- for (i = 0; i < n; i++) {
- if (ccs[i].code == code) {
- for (j = 0; j < ccs[i].n; j++) {
- ccode = ccs[i].items[j].code[0];
- len = ONIGENC_CODE_TO_MBC(enc, ccode, buf);
- if (len < 0) return len;
- add_char_opt_map_info(map, buf[0], enc);
- }
- break;
- }
- }
- }
- }
- return 0;
-}
-
-static void
-select_opt_map_info(OptMapInfo* now, OptMapInfo* alt)
-{
- static int z = 1<<15; /* 32768: something big value */
-
- int v1, v2;
-
- if (alt->value == 0) return ;
- if (now->value == 0) {
- copy_opt_map_info(now, alt);
- return ;
- }
-
- v1 = z / now->value;
- v2 = z / alt->value;
- if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0)
- copy_opt_map_info(now, alt);
-}
-
-static int
-comp_opt_exact_or_map_info(OptExactInfo* e, OptMapInfo* m)
-{
-#define COMP_EM_BASE 20
- int ve, vm;
-
- if (m->value <= 0) return -1;
-
- ve = COMP_EM_BASE * e->len * (e->ignore_case ? 1 : 2);
- vm = COMP_EM_BASE * 5 * 2 / m->value;
- return comp_distance_value(&e->mmd, &m->mmd, ve, vm);
-}
-
-static void
-alt_merge_opt_map_info(OnigEncoding enc, OptMapInfo* to, OptMapInfo* add)
-{
- int i, val;
-
- /* if (! is_equal_mml(&to->mmd, &add->mmd)) return ; */
- if (to->value == 0) return ;
- if (add->value == 0 || to->mmd.max < add->mmd.min) {
- clear_opt_map_info(to);
- return ;
- }
-
- alt_merge_mml(&to->mmd, &add->mmd);
-
- val = 0;
- for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) {
- if (add->map[i])
- to->map[i] = 1;
-
- if (to->map[i])
- val += map_position_value(enc, i);
- }
- to->value = val;
-
- alt_merge_opt_anc_info(&to->anc, &add->anc);
-}
-
-static void
-set_bound_node_opt_info(NodeOptInfo* opt, MinMaxLen* mmd)
-{
- copy_mml(&(opt->exb.mmd), mmd);
- copy_mml(&(opt->expr.mmd), mmd);
- copy_mml(&(opt->map.mmd), mmd);
-}
-
-static void
-clear_node_opt_info(NodeOptInfo* opt)
-{
- clear_mml(&opt->len);
- clear_opt_anc_info(&opt->anc);
- clear_opt_exact_info(&opt->exb);
- clear_opt_exact_info(&opt->exm);
- clear_opt_exact_info(&opt->expr);
- clear_opt_map_info(&opt->map);
-}
-
-static void
-copy_node_opt_info(NodeOptInfo* to, NodeOptInfo* from)
-{
- *to = *from;
-}
-
-static void
-concat_left_node_opt_info(OnigEncoding enc, NodeOptInfo* to, NodeOptInfo* add)
-{
- int exb_reach, exm_reach;
- OptAncInfo tanc;
-
- concat_opt_anc_info(&tanc, &to->anc, &add->anc, to->len.max, add->len.max);
- copy_opt_anc_info(&to->anc, &tanc);
-
- if (add->exb.len > 0 && to->len.max == 0) {
- concat_opt_anc_info(&tanc, &to->anc, &add->exb.anc,
- to->len.max, add->len.max);
- copy_opt_anc_info(&add->exb.anc, &tanc);
- }
-
- if (add->map.value > 0 && to->len.max == 0) {
- if (add->map.mmd.max == 0)
- add->map.anc.left_anchor |= to->anc.left_anchor;
- }
-
- exb_reach = to->exb.reach_end;
- exm_reach = to->exm.reach_end;
-
- if (add->len.max != 0)
- to->exb.reach_end = to->exm.reach_end = 0;
-
- if (add->exb.len > 0) {
- if (exb_reach) {
- concat_opt_exact_info(&to->exb, &add->exb);
- clear_opt_exact_info(&add->exb);
- }
- else if (exm_reach) {
- concat_opt_exact_info(&to->exm, &add->exb);
- clear_opt_exact_info(&add->exb);
- }
- }
- select_opt_exact_info(enc, &to->exm, &add->exb);
- select_opt_exact_info(enc, &to->exm, &add->exm);
-
- if (to->expr.len > 0) {
- if (add->len.max > 0) {
- if (to->expr.len > (int )add->len.max)
- to->expr.len = add->len.max;
-
- if (to->expr.mmd.max == 0)
- select_opt_exact_info(enc, &to->exb, &to->expr);
- else
- select_opt_exact_info(enc, &to->exm, &to->expr);
- }
- }
- else if (add->expr.len > 0) {
- copy_opt_exact_info(&to->expr, &add->expr);
- }
-
- select_opt_map_info(&to->map, &add->map);
-
- add_mml(&to->len, &add->len);
-}
-
-static void
-alt_merge_node_opt_info(NodeOptInfo* to, NodeOptInfo* add, OptEnv* env)
-{
- alt_merge_opt_anc_info (&to->anc, &add->anc);
- alt_merge_opt_exact_info(&to->exb, &add->exb, env);
- alt_merge_opt_exact_info(&to->exm, &add->exm, env);
- alt_merge_opt_exact_info(&to->expr, &add->expr, env);
- alt_merge_opt_map_info(env->enc, &to->map, &add->map);
-
- alt_merge_mml(&to->len, &add->len);
-}
-
-
-#define MAX_NODE_OPT_INFO_REF_COUNT 5
-
-static int
-optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
-{
- int type;
- int r = 0;
-
- clear_node_opt_info(opt);
- set_bound_node_opt_info(opt, &env->mmd);
-
- type = NTYPE(node);
- switch (type) {
- case N_LIST:
- {
- OptEnv nenv;
- NodeOptInfo nopt;
- Node* nd = node;
-
- copy_opt_env(&nenv, env);
- do {
- r = optimize_node_left(NCONS(nd).left, &nopt, &nenv);
- if (r == 0) {
- add_mml(&nenv.mmd, &nopt.len);
- concat_left_node_opt_info(env->enc, opt, &nopt);
- }
- } while (r == 0 && IS_NOT_NULL(nd = NCONS(nd).right));
- }
- break;
-
- case N_ALT:
- {
- NodeOptInfo nopt;
- Node* nd = node;
-
- do {
- r = optimize_node_left(NCONS(nd).left, &nopt, env);
- if (r == 0) {
- if (nd == node) copy_node_opt_info(opt, &nopt);
- else alt_merge_node_opt_info(opt, &nopt, env);
- }
- } while ((r == 0) && IS_NOT_NULL(nd = NCONS(nd).right));
- }
- break;
-
- case N_STRING:
- {
- StrNode* sn = &(NSTRING(node));
- int slen = sn->end - sn->s;
- int is_raw = NSTRING_IS_RAW(node);
-
- if (! NSTRING_IS_AMBIG(node)) {
- concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
- NSTRING_IS_RAW(node), env->enc);
- if (slen > 0) {
- add_char_opt_map_info(&opt->map, *(sn->s), env->enc);
- }
- set_mml(&opt->len, slen, slen);
- }
- else {
- int n, max;
-
- concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
- is_raw, env->enc);
- opt->exb.ignore_case = 1;
-
- if (slen > 0) {
- r = add_char_amb_opt_map_info(&opt->map, sn->s, sn->end,
- env->enc, env->ambig_flag);
- if (r != 0) break;
- }
-
- if (NSTRING_IS_AMBIG_REDUCE(node)) {
- n = onigenc_strlen(env->enc, sn->s, sn->end);
- max = ONIGENC_MBC_MAXLEN_DIST(env->enc) * n;
- }
- else {
- max = slen;
- }
- set_mml(&opt->len, slen, max);
- }
-
- if (opt->exb.len == slen)
- opt->exb.reach_end = 1;
- }
- break;
-
- case N_CCLASS:
- {
- int i, z;
- CClassNode* cc = &(NCCLASS(node));
-
- /* no need to check ignore case. (setted in setup_tree()) */
-
- if (IS_NOT_NULL(cc->mbuf) || IS_CCLASS_NOT(cc)) {
- OnigDistance min = ONIGENC_MBC_MINLEN(env->enc);
- OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
-
- set_mml(&opt->len, min, max);
- }
- else {
- for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
- z = BITSET_AT(cc->bs, i);
- if ((z && !IS_CCLASS_NOT(cc)) || (!z && IS_CCLASS_NOT(cc))) {
- add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
- }
- }
- set_mml(&opt->len, 1, 1);
- }
- }
- break;
-
- case N_CTYPE:
- {
- int i, min, max;
-
- max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
-
- if (max == 1) {
- min = 1;
-
- switch (NCTYPE(node).type) {
- case CTYPE_NOT_WORD:
- for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
- if (! ONIGENC_IS_CODE_WORD(env->enc, i)) {
- add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
- }
- }
- break;
-
- case CTYPE_WORD:
- for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
- if (ONIGENC_IS_CODE_WORD(env->enc, i)) {
- add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
- }
- }
- break;
- }
- }
- else {
- min = ONIGENC_MBC_MINLEN(env->enc);
- }
- set_mml(&opt->len, min, max);
- }
- break;
-
- case N_ANYCHAR:
- {
- OnigDistance min = ONIGENC_MBC_MINLEN(env->enc);
- OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
- set_mml(&opt->len, min, max);
- }
- break;
-
- case N_ANCHOR:
- switch (NANCHOR(node).type) {
- case ANCHOR_BEGIN_BUF:
- case ANCHOR_BEGIN_POSITION:
- case ANCHOR_BEGIN_LINE:
- case ANCHOR_END_BUF:
- case ANCHOR_SEMI_END_BUF:
- case ANCHOR_END_LINE:
- add_opt_anc_info(&opt->anc, NANCHOR(node).type);
- break;
-
- case ANCHOR_PREC_READ:
- {
- NodeOptInfo nopt;
-
- r = optimize_node_left(NANCHOR(node).target, &nopt, env);
- if (r == 0) {
- if (nopt.exb.len > 0)
- copy_opt_exact_info(&opt->expr, &nopt.exb);
- else if (nopt.exm.len > 0)
- copy_opt_exact_info(&opt->expr, &nopt.exm);
-
- opt->expr.reach_end = 0;
-
- if (nopt.map.value > 0)
- copy_opt_map_info(&opt->map, &nopt.map);
- }
- }
- break;
-
- case ANCHOR_PREC_READ_NOT:
- case ANCHOR_LOOK_BEHIND: /* Sorry, I can't make use of it. */
- case ANCHOR_LOOK_BEHIND_NOT:
- break;
- }
- break;
-
- case N_BACKREF:
- {
- int i;
- int* backs;
- OnigDistance min, max, tmin, tmax;
- Node** nodes = SCANENV_MEM_NODES(env->scan_env);
- BackrefNode* br = &(NBACKREF(node));
-
- if (br->state & NST_RECURSION) {
- set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
- break;
- }
- backs = BACKREFS_P(br);
- r = get_min_match_length(nodes[backs[0]], &min, env->scan_env);
- if (r != 0) break;
- r = get_max_match_length(nodes[backs[0]], &max, env->scan_env);
- if (r != 0) break;
- for (i = 1; i < br->back_num; i++) {
- r = get_min_match_length(nodes[backs[i]], &tmin, env->scan_env);
- if (r != 0) break;
- r = get_max_match_length(nodes[backs[i]], &tmax, env->scan_env);
- if (r != 0) break;
- if (min > tmin) min = tmin;
- if (max < tmax) max = tmax;
- }
- if (r == 0) set_mml(&opt->len, min, max);
- }
- break;
-
-#ifdef USE_SUBEXP_CALL
- case N_CALL:
- if (IS_CALL_RECURSION(&(NCALL(node))))
- set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
- else {
- OnigOptionType save = env->options;
- env->options = NEFFECT(NCALL(node).target).option;
- r = optimize_node_left(NCALL(node).target, opt, env);
- env->options = save;
- }
- break;
-#endif
-
- case N_QUALIFIER:
- {
- int i;
- OnigDistance min, max;
- NodeOptInfo nopt;
- QualifierNode* qn = &(NQUALIFIER(node));
-
- r = optimize_node_left(qn->target, &nopt, env);
- if (r) break;
-
- if (qn->lower == 0 && IS_REPEAT_INFINITE(qn->upper)) {
- if (env->mmd.max == 0 &&
- NTYPE(qn->target) == N_ANYCHAR && qn->greedy) {
- if (IS_POSIXLINE(env->options))
- add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_PL);
- else
- add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR);
- }
- }
- else {
- if (qn->lower > 0) {
- copy_node_opt_info(opt, &nopt);
- if (nopt.exb.len > 0) {
- if (nopt.exb.reach_end) {
- for (i = 2; i < qn->lower &&
- ! is_full_opt_exact_info(&opt->exb); i++) {
- concat_opt_exact_info(&opt->exb, &nopt.exb);
- }
- if (i < qn->lower) {
- opt->exb.reach_end = 0;
- }
- }
- }
-
- if (qn->lower != qn->upper) {
- opt->exb.reach_end = 0;
- opt->exm.reach_end = 0;
- }
- if (qn->lower > 1)
- opt->exm.reach_end = 0;
- }
- }
-
- min = distance_multiply(nopt.len.min, qn->lower);
- if (IS_REPEAT_INFINITE(qn->upper))
- max = (nopt.len.max > 0 ? ONIG_INFINITE_DISTANCE : 0);
- else
- max = distance_multiply(nopt.len.max, qn->upper);
-
- set_mml(&opt->len, min, max);
- }
- break;
-
- case N_EFFECT:
- {
- EffectNode* en = &(NEFFECT(node));
-
- switch (en->type) {
- case EFFECT_OPTION:
- {
- OnigOptionType save = env->options;
-
- env->options = en->option;
- r = optimize_node_left(en->target, opt, env);
- env->options = save;
- }
- break;
-
- case EFFECT_MEMORY:
-#ifdef USE_SUBEXP_CALL
- en->opt_count++;
- if (en->opt_count > MAX_NODE_OPT_INFO_REF_COUNT) {
- OnigDistance min, max;
-
- min = 0;
- max = ONIG_INFINITE_DISTANCE;
- if (IS_EFFECT_MIN_FIXED(en)) min = en->min_len;
- if (IS_EFFECT_MAX_FIXED(en)) max = en->max_len;
- set_mml(&opt->len, min, max);
- }
- else
-#endif
- {
- r = optimize_node_left(en->target, opt, env);
-
- if (is_set_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK)) {
- if (BIT_STATUS_AT(env->scan_env->backrefed_mem, en->regnum))
- remove_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK);
- }
- }
- break;
-
- case EFFECT_STOP_BACKTRACK:
- r = optimize_node_left(en->target, opt, env);
- break;
- }
- }
- break;
-
- default:
-#ifdef ONIG_DEBUG
- fprintf(stderr, "optimize_node_left: undefined node type %d\n",
- NTYPE(node));
-#endif
- r = ONIGERR_TYPE_BUG;
- break;
- }
-
- return r;
-}
-
-static int
-set_optimize_exact_info(regex_t* reg, OptExactInfo* e)
-{
- int r;
-
- if (e->len == 0) return 0;
-
- if (e->ignore_case) {
- reg->exact = (UChar* )xmalloc(e->len);
- CHECK_NULL_RETURN_VAL(reg->exact, ONIGERR_MEMORY);
- xmemcpy(reg->exact, e->s, e->len);
- reg->exact_end = reg->exact + e->len;
- reg->optimize = ONIG_OPTIMIZE_EXACT_IC;
- }
- else {
- int allow_reverse;
-
- reg->exact = k_strdup(e->s, e->s + e->len);
- CHECK_NULL_RETURN_VAL(reg->exact, ONIGERR_MEMORY);
- reg->exact_end = reg->exact + e->len;
-
- if (e->anc.left_anchor & ANCHOR_BEGIN_LINE)
- allow_reverse = 1;
- else
- allow_reverse =
- ONIGENC_IS_ALLOWED_REVERSE_MATCH(reg->enc, reg->exact, reg->exact_end);
-
- if (e->len >= 3 || (e->len >= 2 && allow_reverse)) {
- r = set_bm_skip(reg->exact, reg->exact_end, reg->enc,
- reg->map, &(reg->int_map));
- if (r) return r;
-
- reg->optimize = (allow_reverse != 0
- ? ONIG_OPTIMIZE_EXACT_BM : ONIG_OPTIMIZE_EXACT_BM_NOT_REV);
- }
- else {
- reg->optimize = ONIG_OPTIMIZE_EXACT;
- }
- }
-
- reg->dmin = e->mmd.min;
- reg->dmax = e->mmd.max;
-
- if (reg->dmin != ONIG_INFINITE_DISTANCE) {
- reg->threshold_len = reg->dmin + (reg->exact_end - reg->exact);
- }
-
- return 0;
-}
-
-static void
-set_optimize_map_info(regex_t* reg, OptMapInfo* m)
-{
- int i;
-
- for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
- reg->map[i] = m->map[i];
-
- reg->optimize = ONIG_OPTIMIZE_MAP;
- reg->dmin = m->mmd.min;
- reg->dmax = m->mmd.max;
-
- if (reg->dmin != ONIG_INFINITE_DISTANCE) {
- reg->threshold_len = reg->dmin + 1;
- }
-}
-
-static void
-set_sub_anchor(regex_t* reg, OptAncInfo* anc)
-{
- reg->sub_anchor |= anc->left_anchor & ANCHOR_BEGIN_LINE;
- reg->sub_anchor |= anc->right_anchor & ANCHOR_END_LINE;
-}
-
-#ifdef ONIG_DEBUG
-static void print_optimize_info(FILE* f, regex_t* reg);
-#endif
-
-static int
-set_optimize_info_from_tree(Node* node, regex_t* reg, ScanEnv* scan_env)
-{
-
- int r;
- NodeOptInfo opt;
- OptEnv env;
-
- env.enc = reg->enc;
- env.options = reg->options;
- env.ambig_flag = reg->ambig_flag;
- env.scan_env = scan_env;
- clear_mml(&env.mmd);
-
- r = optimize_node_left(node, &opt, &env);
- if (r) return r;
-
- reg->anchor = opt.anc.left_anchor & (ANCHOR_BEGIN_BUF |
- ANCHOR_BEGIN_POSITION | ANCHOR_ANYCHAR_STAR | ANCHOR_ANYCHAR_STAR_PL);
-
- reg->anchor |= opt.anc.right_anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF);
-
- if (reg->anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF)) {
- reg->anchor_dmin = opt.len.min;
- reg->anchor_dmax = opt.len.max;
- }
-
- if (opt.exb.len > 0 || opt.exm.len > 0) {
- select_opt_exact_info(reg->enc, &opt.exb, &opt.exm);
- if (opt.map.value > 0 &&
- comp_opt_exact_or_map_info(&opt.exb, &opt.map) > 0) {
- goto set_map;
- }
- else {
- r = set_optimize_exact_info(reg, &opt.exb);
- set_sub_anchor(reg, &opt.exb.anc);
- }
- }
- else if (opt.map.value > 0) {
- set_map:
- set_optimize_map_info(reg, &opt.map);
- set_sub_anchor(reg, &opt.map.anc);
- }
- else {
- reg->sub_anchor |= opt.anc.left_anchor & ANCHOR_BEGIN_LINE;
- if (opt.len.max == 0)
- reg->sub_anchor |= opt.anc.right_anchor & ANCHOR_END_LINE;
- }
-
-#if defined(ONIG_DEBUG_COMPILE) || defined(ONIG_DEBUG_MATCH)
- print_optimize_info(stderr, reg);
-#endif
- return r;
-}
-
-static void
-clear_optimize_info(regex_t* reg)
-{
- reg->optimize = ONIG_OPTIMIZE_NONE;
- reg->anchor = 0;
- reg->anchor_dmin = 0;
- reg->anchor_dmax = 0;
- reg->sub_anchor = 0;
- reg->exact_end = (UChar* )NULL;
- reg->threshold_len = 0;
- if (IS_NOT_NULL(reg->exact)) {
- xfree(reg->exact);
- reg->exact = (UChar* )NULL;
- }
-}
-
-#ifdef ONIG_DEBUG
-
-static void
-print_distance_range(FILE* f, OnigDistance a, OnigDistance b)
-{
- if (a == ONIG_INFINITE_DISTANCE)
- fputs("inf", f);
- else
- fprintf(f, "(%u)", a);
-
- fputs("-", f);
-
- if (b == ONIG_INFINITE_DISTANCE)
- fputs("inf", f);
- else
- fprintf(f, "(%u)", b);
-}
-
-static void
-print_anchor(FILE* f, int anchor)
-{
- int q = 0;
-
- fprintf(f, "[");
-
- if (anchor & ANCHOR_BEGIN_BUF) {
- fprintf(f, "begin-buf");
- q = 1;
- }
- if (anchor & ANCHOR_BEGIN_LINE) {
- if (q) fprintf(f, ", ");
- q = 1;
- fprintf(f, "begin-line");
- }
- if (anchor & ANCHOR_BEGIN_POSITION) {
- if (q) fprintf(f, ", ");
- q = 1;
- fprintf(f, "begin-pos");
- }
- if (anchor & ANCHOR_END_BUF) {
- if (q) fprintf(f, ", ");
- q = 1;
- fprintf(f, "end-buf");
- }
- if (anchor & ANCHOR_SEMI_END_BUF) {
- if (q) fprintf(f, ", ");
- q = 1;
- fprintf(f, "semi-end-buf");
- }
- if (anchor & ANCHOR_END_LINE) {
- if (q) fprintf(f, ", ");
- q = 1;
- fprintf(f, "end-line");
- }
- if (anchor & ANCHOR_ANYCHAR_STAR) {
- if (q) fprintf(f, ", ");
- q = 1;
- fprintf(f, "anychar-star");
- }
- if (anchor & ANCHOR_ANYCHAR_STAR_PL) {
- if (q) fprintf(f, ", ");
- fprintf(f, "anychar-star-pl");
- }
-
- fprintf(f, "]");
-}
-
-static void
-print_optimize_info(FILE* f, regex_t* reg)
-{
- static char* on[] = { "NONE", "EXACT", "EXACT_BM", "EXACT_BM_NOT_REV",
- "EXACT_IC", "MAP" };
-
- fprintf(f, "optimize: %s\n", on[reg->optimize]);
- fprintf(f, " anchor: "); print_anchor(f, reg->anchor);
- if ((reg->anchor & ANCHOR_END_BUF_MASK) != 0)
- print_distance_range(f, reg->anchor_dmin, reg->anchor_dmax);
- fprintf(f, "\n");
-
- if (reg->optimize) {
- fprintf(f, " sub anchor: "); print_anchor(f, reg->sub_anchor);
- fprintf(f, "\n");
- }
- fprintf(f, "\n");
-
- if (reg->exact) {
- UChar *p;
- fprintf(f, "exact: [");
- for (p = reg->exact; p < reg->exact_end; p++) {
- fputc(*p, f);
- }
- fprintf(f, "]: length: %d\n", (reg->exact_end - reg->exact));
- }
- else if (reg->optimize & ONIG_OPTIMIZE_MAP) {
- int c, i, n = 0;
-
- for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
- if (reg->map[i]) n++;
-
- fprintf(f, "map: n=%d\n", n);
- if (n > 0) {
- c = 0;
- fputc('[', f);
- for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) {
- if (reg->map[i] != 0) {
- if (c > 0) fputs(", ", f);
- c++;
- if (ONIGENC_MBC_MAXLEN(reg->enc) == 1 &&
- ONIGENC_IS_CODE_PRINT(reg->enc, (OnigCodePoint )i))
- fputc(i, f);
- else
- fprintf(f, "%d", i);
- }
- }
- fprintf(f, "]\n");
- }
- }
-}
-#endif /* ONIG_DEBUG */
-
-
-static void
-onig_free_body(regex_t* reg)
-{
- if (IS_NOT_NULL(reg->p)) xfree(reg->p);
- if (IS_NOT_NULL(reg->exact)) xfree(reg->exact);
- if (IS_NOT_NULL(reg->int_map)) xfree(reg->int_map);
- if (IS_NOT_NULL(reg->int_map_backward)) xfree(reg->int_map_backward);
- if (IS_NOT_NULL(reg->repeat_range)) xfree(reg->repeat_range);
- if (IS_NOT_NULL(reg->chain)) onig_free(reg->chain);
-
-#ifdef USE_NAMED_GROUP
- onig_names_free(reg);
-#endif
-}
-
-extern void
-onig_free(regex_t* reg)
-{
- if (IS_NOT_NULL(reg)) {
- onig_free_body(reg);
- xfree(reg);
- }
-}
-
-#define REGEX_TRANSFER(to,from) do {\
- (to)->state = ONIG_STATE_MODIFY;\
- onig_free_body(to);\
- xmemcpy(to, from, sizeof(regex_t));\
- xfree(from);\
-} while (0)
-
-extern void
-onig_transfer(regex_t* to, regex_t* from)
-{
- THREAD_ATOMIC_START;
- REGEX_TRANSFER(to, from);
- THREAD_ATOMIC_END;
-}
-
-#define REGEX_CHAIN_HEAD(reg) do {\
- while (IS_NOT_NULL((reg)->chain)) {\
- (reg) = (reg)->chain;\
- }\
-} while (0)
-
-extern void
-onig_chain_link_add(regex_t* to, regex_t* add)
-{
- THREAD_ATOMIC_START;
- REGEX_CHAIN_HEAD(to);
- to->chain = add;
- THREAD_ATOMIC_END;
-}
-
-extern void
-onig_chain_reduce(regex_t* reg)
-{
- regex_t *head, *prev;
-
- THREAD_ATOMIC_START;
- prev = reg;
- head = prev->chain;
- if (IS_NOT_NULL(head)) {
- reg->state = ONIG_STATE_MODIFY;
- while (IS_NOT_NULL(head->chain)) {
- prev = head;
- head = head->chain;
- }
- prev->chain = (regex_t* )NULL;
- REGEX_TRANSFER(reg, head);
- }
- THREAD_ATOMIC_END;
-}
-
-#if 0
-extern int
-onig_clone(regex_t** to, regex_t* from)
-{
- int r, size;
- regex_t* reg;
-
-#ifdef USE_MULTI_THREAD_SYSTEM
- if (ONIG_STATE(from) >= ONIG_STATE_NORMAL) {
- ONIG_STATE_INC(from);
- if (IS_NOT_NULL(from->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) {
- onig_chain_reduce(from);
- ONIG_STATE_INC(from);
- }
- }
- else {
- int n = 0;
- while (ONIG_STATE(from) < ONIG_STATE_NORMAL) {
- if (++n > THREAD_PASS_LIMIT_COUNT)
- return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT;
- THREAD_PASS;
- }
- ONIG_STATE_INC(from);
- }
-#endif /* USE_MULTI_THREAD_SYSTEM */
-
- r = onig_alloc_init(&reg, ONIG_OPTION_NONE, ONIGENC_AMBIGUOUS_MATCH_DEFAULT,
- from->enc, ONIG_SYNTAX_DEFAULT);
- if (r != 0) {
- ONIG_STATE_DEC(from);
- return r;
- }
-
- xmemcpy(reg, from, sizeof(onig_t));
- reg->chain = (regex_t* )NULL;
- reg->state = ONIG_STATE_NORMAL;
-
- if (from->p) {
- reg->p = (UChar* )xmalloc(reg->alloc);
- if (IS_NULL(reg->p)) goto mem_error;
- xmemcpy(reg->p, from->p, reg->alloc);
- }
-
- if (from->exact) {
- reg->exact = (UChar* )xmalloc(from->exact_end - from->exact);
- if (IS_NULL(reg->exact)) goto mem_error;
- reg->exact_end = reg->exact + (from->exact_end - from->exact);
- xmemcpy(reg->exact, from->exact, reg->exact_end - reg->exact);
- }
-
- if (from->int_map) {
- size = sizeof(int) * ONIG_CHAR_TABLE_SIZE;
- reg->int_map = (int* )xmalloc(size);
- if (IS_NULL(reg->int_map)) goto mem_error;
- xmemcpy(reg->int_map, from->int_map, size);
- }
-
- if (from->int_map_backward) {
- size = sizeof(int) * ONIG_CHAR_TABLE_SIZE;
- reg->int_map_backward = (int* )xmalloc(size);
- if (IS_NULL(reg->int_map_backward)) goto mem_error;
- xmemcpy(reg->int_map_backward, from->int_map_backward, size);
- }
-
-#ifdef USE_NAMED_GROUP
- reg->name_table = names_clone(from); /* names_clone is not implemented */
-#endif
-
- ONIG_STATE_DEC(from);
- *to = reg;
- return 0;
-
- mem_error:
- ONIG_STATE_DEC(from);
- return ONIGERR_MEMORY;
-}
-#endif
-
-#ifdef ONIG_DEBUG
-static void print_compiled_byte_code_list P_((FILE* f, regex_t* reg));
-#endif
-#ifdef ONIG_DEBUG_PARSE_TREE
-static void print_tree P_((FILE* f, Node* node));
-#endif
-
-extern int
-onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
- OnigErrorInfo* einfo)
-{
-#define COMPILE_INIT_SIZE 20
-
- int r, init_size;
- Node* root;
- ScanEnv scan_env;
-#ifdef USE_SUBEXP_CALL
- UnsetAddrList uslist;
-#endif
-
- reg->state = ONIG_STATE_COMPILING;
-
- if (reg->alloc == 0) {
- init_size = (pattern_end - pattern) * 2;
- if (init_size <= 0) init_size = COMPILE_INIT_SIZE;
- r = BBUF_INIT(reg, init_size);
- if (r != 0) goto end;
- }
- else
- reg->used = 0;
-
- reg->num_mem = 0;
- reg->num_repeat = 0;
- reg->num_null_check = 0;
- reg->repeat_range_alloc = 0;
- reg->repeat_range = (OnigRepeatRange* )NULL;
-
- r = onig_parse_make_tree(&root, pattern, pattern_end, reg, &scan_env);
- if (r != 0) goto err;
-
-#ifdef USE_NAMED_GROUP
- /* mixed use named group and no-named group */
- if (scan_env.num_named > 0 &&
- IS_SYNTAX_BV(scan_env.syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
- !ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_CAPTURE_GROUP)) {
- if (scan_env.num_named != scan_env.num_mem)
- r = disable_noname_group_capture(&root, reg, &scan_env);
- else
- r = numbered_ref_check(root);
-
- if (r != 0) goto err;
- }
-#endif
-
-#ifdef ONIG_DEBUG_PARSE_TREE
- print_tree(stderr, root);
-#endif
-
-#ifdef USE_SUBEXP_CALL
- if (scan_env.num_call > 0) {
- r = unset_addr_list_init(&uslist, scan_env.num_call);
- if (r != 0) goto err;
- scan_env.unset_addr_list = &uslist;
- r = setup_subexp_call(root, &scan_env);
- if (r != 0) goto err_unset;
- r = subexp_recursive_check_trav(root, &scan_env);
- if (r < 0) goto err_unset;
- r = subexp_inf_recursive_check_trav(root, &scan_env);
- if (r != 0) goto err_unset;
-
- reg->num_call = scan_env.num_call;
- }
- else
- reg->num_call = 0;
-#endif
-
- r = setup_tree(root, reg, 0, &scan_env);
- if (r != 0) goto err_unset;
-
- reg->capture_history = scan_env.capture_history;
- reg->bt_mem_start = scan_env.bt_mem_start;
- reg->bt_mem_start |= reg->capture_history;
- if (IS_FIND_CONDITION(reg->options))
- BIT_STATUS_ON_ALL(reg->bt_mem_end);
- else {
- reg->bt_mem_end = scan_env.bt_mem_end;
- reg->bt_mem_end |= reg->capture_history;
- }
-
- clear_optimize_info(reg);
-#ifndef ONIG_DONT_OPTIMIZE
- r = set_optimize_info_from_tree(root, reg, &scan_env);
- if (r != 0) goto err_unset;
-#endif
-
- if (IS_NOT_NULL(scan_env.mem_nodes_dynamic)) {
- xfree(scan_env.mem_nodes_dynamic);
- scan_env.mem_nodes_dynamic = (Node** )NULL;
- }
-
- r = compile_tree(root, reg);
- if (r == 0) {
- r = add_opcode(reg, OP_END);
-#ifdef USE_SUBEXP_CALL
- if (scan_env.num_call > 0) {
- r = unset_addr_list_fix(&uslist, reg);
- unset_addr_list_end(&uslist);
- if (r) goto err;
- }
-#endif
-
- if ((reg->num_repeat != 0) || (reg->bt_mem_end != 0))
- reg->stack_pop_level = STACK_POP_LEVEL_ALL;
- else {
- if (reg->bt_mem_start != 0)
- reg->stack_pop_level = STACK_POP_LEVEL_MEM_START;
- else
- reg->stack_pop_level = STACK_POP_LEVEL_FREE;
- }
- }
-#ifdef USE_SUBEXP_CALL
- else if (scan_env.num_call > 0) {
- unset_addr_list_end(&uslist);
- }
-#endif
- onig_node_free(root);
-
-#ifdef ONIG_DEBUG_COMPILE
-#ifdef USE_NAMED_GROUP
- onig_print_names(stderr, reg);
-#endif
- print_compiled_byte_code_list(stderr, reg);
-#endif
-
- end:
- reg->state = ONIG_STATE_NORMAL;
- return r;
-
- err_unset:
-#ifdef USE_SUBEXP_CALL
- if (scan_env.num_call > 0) {
- unset_addr_list_end(&uslist);
- }
-#endif
- err:
- if (IS_NOT_NULL(scan_env.error)) {
- if (IS_NOT_NULL(einfo)) {
- einfo->par = scan_env.error;
- einfo->par_end = scan_env.error_end;
- }
- }
-
- if (IS_NOT_NULL(root)) onig_node_free(root);
- if (IS_NOT_NULL(scan_env.mem_nodes_dynamic))
- xfree(scan_env.mem_nodes_dynamic);
- return r;
-}
-
-extern int
-onig_recompile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
- OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax,
- OnigErrorInfo* einfo)
-{
- int r;
- regex_t *new_reg;
-
- r = onig_new(&new_reg, pattern, pattern_end, option, enc, syntax, einfo);
- if (r) return r;
- if (ONIG_STATE(reg) == ONIG_STATE_NORMAL) {
- onig_transfer(reg, new_reg);
- }
- else {
- onig_chain_link_add(reg, new_reg);
- }
- return 0;
-}
-
-static int onig_inited = 0;
-
-extern int
-onig_alloc_init(regex_t** reg, OnigOptionType option, OnigAmbigType ambig_flag,
- OnigEncoding enc, OnigSyntaxType* syntax)
-{
- if (! onig_inited)
- onig_init();
-
- if (ONIGENC_IS_UNDEF(enc))
- return ONIGERR_DEFAULT_ENCODING_IS_NOT_SETTED;
-
- *reg = (regex_t* )xmalloc(sizeof(regex_t));
- if (IS_NULL(*reg)) return ONIGERR_MEMORY;
- (*reg)->state = ONIG_STATE_MODIFY;
-
- if ((option & ONIG_OPTION_NEGATE_SINGLELINE) != 0) {
- option |= syntax->options;
- option &= ~ONIG_OPTION_SINGLELINE;
- }
- else
- option |= syntax->options;
-
- (*reg)->enc = enc;
- (*reg)->options = option;
- (*reg)->syntax = syntax;
- (*reg)->optimize = 0;
- (*reg)->exact = (UChar* )NULL;
- (*reg)->int_map = (int* )NULL;
- (*reg)->int_map_backward = (int* )NULL;
- (*reg)->chain = (regex_t* )NULL;
-
- (*reg)->p = (UChar* )NULL;
- (*reg)->alloc = 0;
- (*reg)->used = 0;
- (*reg)->name_table = (void* )NULL;
-
- (*reg)->ambig_flag = ambig_flag;
- (*reg)->ambig_flag &= ONIGENC_SUPPORT_AMBIG_FLAG(enc);
-
- return 0;
-}
-
-extern int
-onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end,
- OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax,
- OnigErrorInfo* einfo)
-{
- int r;
-
- if (IS_NOT_NULL(einfo)) einfo->par = (UChar* )NULL;
-
- r = onig_alloc_init(reg, option, ONIGENC_AMBIGUOUS_MATCH_DEFAULT,
- enc, syntax);
- if (r) return r;
-
- r = onig_compile(*reg, pattern, pattern_end, einfo);
- if (r) {
- onig_free(*reg);
- *reg = NULL;
- }
- return r;
-}
-
-extern int
-onig_init()
-{
- if (onig_inited != 0)
- return 0;
-
- onig_inited = 1;
-
- THREAD_ATOMIC_START;
-
- onigenc_init();
- onigenc_set_default_caseconv_table((UChar* )0);
-
-#ifdef ONIG_DEBUG_STATISTICS
- onig_statistics_init();
-#endif
-
- THREAD_ATOMIC_END;
- return 0;
-}
-
-
-extern int
-onig_end()
-{
- extern int onig_free_shared_cclass_table();
-
- THREAD_ATOMIC_START;
-
-#ifdef ONIG_DEBUG_STATISTICS
- onig_print_statistics(stderr);
-#endif
-
-#ifdef USE_RECYCLE_NODE
- onig_free_node_list();
-#endif
-
-#ifdef USE_SHARED_CCLASS_TABLE
- onig_free_shared_cclass_table();
-#endif
-
- onig_inited = 0;
-
- THREAD_ATOMIC_END;
- return 0;
-}
-
-
-#ifdef ONIG_DEBUG
-
-OnigOpInfoType OnigOpInfo[] = {
- { OP_FINISH, "finish", ARG_NON },
- { OP_END, "end", ARG_NON },
- { OP_EXACT1, "exact1", ARG_SPECIAL },
- { OP_EXACT2, "exact2", ARG_SPECIAL },
- { OP_EXACT3, "exact3", ARG_SPECIAL },
- { OP_EXACT4, "exact4", ARG_SPECIAL },
- { OP_EXACT5, "exact5", ARG_SPECIAL },
- { OP_EXACTN, "exactn", ARG_SPECIAL },
- { OP_EXACTMB2N1, "exactmb2-n1", ARG_SPECIAL },
- { OP_EXACTMB2N2, "exactmb2-n2", ARG_SPECIAL },
- { OP_EXACTMB2N3, "exactmb2-n3", ARG_SPECIAL },
- { OP_EXACTMB2N, "exactmb2-n", ARG_SPECIAL },
- { OP_EXACTMB3N, "exactmb3n" , ARG_SPECIAL },
- { OP_EXACTMBN, "exactmbn", ARG_SPECIAL },
- { OP_EXACT1_IC, "exact1-ic", ARG_SPECIAL },
- { OP_EXACTN_IC, "exactn-ic", ARG_SPECIAL },
- { OP_CCLASS, "cclass", ARG_SPECIAL },
- { OP_CCLASS_MB, "cclass-mb", ARG_SPECIAL },
- { OP_CCLASS_MIX, "cclass-mix", ARG_SPECIAL },
- { OP_CCLASS_NOT, "cclass-not", ARG_SPECIAL },
- { OP_CCLASS_MB_NOT, "cclass-mb-not", ARG_SPECIAL },
- { OP_CCLASS_MIX_NOT, "cclass-mix-not", ARG_SPECIAL },
- { OP_CCLASS_NODE, "cclass-node", ARG_SPECIAL },
- { OP_ANYCHAR, "anychar", ARG_NON },
- { OP_ANYCHAR_ML, "anychar-ml", ARG_NON },
- { OP_ANYCHAR_STAR, "anychar*", ARG_NON },
- { OP_ANYCHAR_ML_STAR, "anychar-ml*", ARG_NON },
- { OP_ANYCHAR_STAR_PEEK_NEXT, "anychar*-peek-next", ARG_SPECIAL },
- { OP_ANYCHAR_ML_STAR_PEEK_NEXT, "anychar-ml*-peek-next", ARG_SPECIAL },
- { OP_WORD, "word", ARG_NON },
- { OP_NOT_WORD, "not-word", ARG_NON },
- { OP_WORD_SB, "word-sb", ARG_NON },
- { OP_WORD_MB, "word-mb", ARG_NON },
- { OP_WORD_BOUND, "word-bound", ARG_NON },
- { OP_NOT_WORD_BOUND, "not-word-bound", ARG_NON },
- { OP_WORD_BEGIN, "word-begin", ARG_NON },
- { OP_WORD_END, "word-end", ARG_NON },
- { OP_BEGIN_BUF, "begin-buf", ARG_NON },
- { OP_END_BUF, "end-buf", ARG_NON },
- { OP_BEGIN_LINE, "begin-line", ARG_NON },
- { OP_END_LINE, "end-line", ARG_NON },
- { OP_SEMI_END_BUF, "semi-end-buf", ARG_NON },
- { OP_BEGIN_POSITION, "begin-position", ARG_NON },
- { OP_BACKREF1, "backref1", ARG_NON },
- { OP_BACKREF2, "backref2", ARG_NON },
- { OP_BACKREF3, "backref3", ARG_NON },
- { OP_BACKREFN, "backrefn", ARG_MEMNUM },
- { OP_BACKREFN_IC, "backrefn-ic", ARG_SPECIAL },
- { OP_BACKREF_MULTI, "backref_multi", ARG_SPECIAL },
- { OP_BACKREF_MULTI_IC, "backref_multi-ic",ARG_SPECIAL },
- { OP_MEMORY_START_PUSH, "mem-start-push", ARG_MEMNUM },
- { OP_MEMORY_START, "mem-start", ARG_MEMNUM },
- { OP_MEMORY_END_PUSH, "mem-end-push", ARG_MEMNUM },
- { OP_MEMORY_END_PUSH_REC, "mem-end-push-rec", ARG_MEMNUM },
- { OP_MEMORY_END, "mem-end", ARG_MEMNUM },
- { OP_MEMORY_END_REC, "mem-end-rec", ARG_MEMNUM },
- { OP_SET_OPTION_PUSH, "set-option-push", ARG_OPTION },
- { OP_SET_OPTION, "set-option", ARG_OPTION },
- { OP_FAIL, "fail", ARG_NON },
- { OP_JUMP, "jump", ARG_RELADDR },
- { OP_PUSH, "push", ARG_RELADDR },
- { OP_POP, "pop", ARG_NON },
- { OP_PUSH_OR_JUMP_EXACT1, "push-or-jump-e1", ARG_SPECIAL },
- { OP_PUSH_IF_PEEK_NEXT, "push-if-peek-next", ARG_SPECIAL },
- { OP_REPEAT, "repeat", ARG_SPECIAL },
- { OP_REPEAT_NG, "repeat-ng", ARG_SPECIAL },
- { OP_REPEAT_INC, "repeat-inc", ARG_MEMNUM },
- { OP_REPEAT_INC_NG, "repeat-inc-ng", ARG_MEMNUM },
- { OP_REPEAT_INC_SG, "repeat-inc-sg", ARG_MEMNUM },
- { OP_REPEAT_INC_NG_SG, "repeat-inc-ng-sg", ARG_MEMNUM },
- { OP_NULL_CHECK_START, "null-check-start",ARG_MEMNUM },
- { OP_NULL_CHECK_END, "null-check-end", ARG_MEMNUM },
- { OP_NULL_CHECK_END_MEMST,"null-check-end-memst", ARG_MEMNUM },
- { OP_NULL_CHECK_END_MEMST_PUSH,"null-check-end-memst-push", ARG_MEMNUM },
- { OP_PUSH_POS, "push-pos", ARG_NON },
- { OP_POP_POS, "pop-pos", ARG_NON },
- { OP_PUSH_POS_NOT, "push-pos-not", ARG_RELADDR },
- { OP_FAIL_POS, "fail-pos", ARG_NON },
- { OP_PUSH_STOP_BT, "push-stop-bt", ARG_NON },
- { OP_POP_STOP_BT, "pop-stop-bt", ARG_NON },
- { OP_LOOK_BEHIND, "look-behind", ARG_SPECIAL },
- { OP_PUSH_LOOK_BEHIND_NOT, "push-look-behind-not", ARG_SPECIAL },
- { OP_FAIL_LOOK_BEHIND_NOT, "fail-look-behind-not", ARG_NON },
- { OP_CALL, "call", ARG_ABSADDR },
- { OP_RETURN, "return", ARG_NON },
- { -1, "", ARG_NON }
-};
-
-static char*
-op2name(int opcode)
-{
- int i;
-
- for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {
- if (opcode == OnigOpInfo[i].opcode)
- return OnigOpInfo[i].name;
- }
- return "";
-}
-
-static int
-op2arg_type(int opcode)
-{
- int i;
-
- for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {
- if (opcode == OnigOpInfo[i].opcode)
- return OnigOpInfo[i].arg_type;
- }
- return ARG_SPECIAL;
-}
-
-static void
-Indent(FILE* f, int indent)
-{
- int i;
- for (i = 0; i < indent; i++) putc(' ', f);
-}
-
-static void
-p_string(FILE* f, int len, UChar* s)
-{
- fputs(":", f);
- while (len-- > 0) { fputc(*s++, f); }
-}
-
-static void
-p_len_string(FILE* f, LengthType len, int mb_len, UChar* s)
-{
- int x = len * mb_len;
-
- fprintf(f, ":%d:", len);
- while (x-- > 0) { fputc(*s++, f); }
-}
-
-extern void
-onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp,
- OnigEncoding enc)
-{
- int i, n, arg_type;
- RelAddrType addr;
- LengthType len;
- MemNumType mem;
- OnigCodePoint code;
- UChar *q;
-
- fprintf(f, "[%s", op2name(*bp));
- arg_type = op2arg_type(*bp);
- if (arg_type != ARG_SPECIAL) {
- bp++;
- switch (arg_type) {
- case ARG_NON:
- break;
- case ARG_RELADDR:
- GET_RELADDR_INC(addr, bp);
- fprintf(f, ":(%d)", addr);
- break;
- case ARG_ABSADDR:
- GET_ABSADDR_INC(addr, bp);
- fprintf(f, ":(%d)", addr);
- break;
- case ARG_LENGTH:
- GET_LENGTH_INC(len, bp);
- fprintf(f, ":%d", len);
- break;
- case ARG_MEMNUM:
- mem = *((MemNumType* )bp);
- bp += SIZE_MEMNUM;
- fprintf(f, ":%d", mem);
- break;
- case ARG_OPTION:
- {
- OnigOptionType option = *((OnigOptionType* )bp);
- bp += SIZE_OPTION;
- fprintf(f, ":%d", option);
- }
- break;
- }
- }
- else {
- switch (*bp++) {
- case OP_EXACT1:
- case OP_ANYCHAR_STAR_PEEK_NEXT:
- case OP_ANYCHAR_ML_STAR_PEEK_NEXT:
- p_string(f, 1, bp++); break;
- case OP_EXACT2:
- p_string(f, 2, bp); bp += 2; break;
- case OP_EXACT3:
- p_string(f, 3, bp); bp += 3; break;
- case OP_EXACT4:
- p_string(f, 4, bp); bp += 4; break;
- case OP_EXACT5:
- p_string(f, 5, bp); bp += 5; break;
- case OP_EXACTN:
- GET_LENGTH_INC(len, bp);
- p_len_string(f, len, 1, bp);
- bp += len;
- break;
-
- case OP_EXACTMB2N1:
- p_string(f, 2, bp); bp += 2; break;
- case OP_EXACTMB2N2:
- p_string(f, 4, bp); bp += 4; break;
- case OP_EXACTMB2N3:
- p_string(f, 6, bp); bp += 6; break;
- case OP_EXACTMB2N:
- GET_LENGTH_INC(len, bp);
- p_len_string(f, len, 2, bp);
- bp += len * 2;
- break;
- case OP_EXACTMB3N:
- GET_LENGTH_INC(len, bp);
- p_len_string(f, len, 3, bp);
- bp += len * 3;
- break;
- case OP_EXACTMBN:
- {
- int mb_len;
-
- GET_LENGTH_INC(mb_len, bp);
- GET_LENGTH_INC(len, bp);
- fprintf(f, ":%d:%d:", mb_len, len);
- n = len * mb_len;
- while (n-- > 0) { fputc(*bp++, f); }
- }
- break;
-
- case OP_EXACT1_IC:
- len = enc_len(enc, bp);
- p_string(f, len, bp);
- bp += len;
- break;
- case OP_EXACTN_IC:
- GET_LENGTH_INC(len, bp);
- p_len_string(f, len, 1, bp);
- bp += len;
- break;
-
- case OP_CCLASS:
- n = bitset_on_num((BitSetRef )bp);
- bp += SIZE_BITSET;
- fprintf(f, ":%d", n);
- break;
-
- case OP_CCLASS_NOT:
- n = bitset_on_num((BitSetRef )bp);
- bp += SIZE_BITSET;
- fprintf(f, ":%d", n);
- break;
-
- case OP_CCLASS_MB:
- case OP_CCLASS_MB_NOT:
- GET_LENGTH_INC(len, bp);
- q = bp;
-#ifndef PLATFORM_UNALIGNED_WORD_ACCESS
- ALIGNMENT_RIGHT(q);
-#endif
- GET_CODE_POINT(code, q);
- bp += len;
- fprintf(f, ":%d:%d", (int )code, len);
- break;
-
- case OP_CCLASS_MIX:
- case OP_CCLASS_MIX_NOT:
- n = bitset_on_num((BitSetRef )bp);
- bp += SIZE_BITSET;
- GET_LENGTH_INC(len, bp);
- q = bp;
-#ifndef PLATFORM_UNALIGNED_WORD_ACCESS
- ALIGNMENT_RIGHT(q);
-#endif
- GET_CODE_POINT(code, q);
- bp += len;
- fprintf(f, ":%d:%d:%d", n, (int )code, len);
- break;
-
- case OP_CCLASS_NODE:
- {
- CClassNode *cc;
-
- GET_POINTER_INC(cc, bp);
- n = bitset_on_num(cc->bs);
- fprintf(f, ":%u:%d", (unsigned int )cc, n);
- }
- break;
-
- case OP_BACKREFN_IC:
- mem = *((MemNumType* )bp);
- bp += SIZE_MEMNUM;
- fprintf(f, ":%d", mem);
- break;
-
- case OP_BACKREF_MULTI_IC:
- case OP_BACKREF_MULTI:
- fputs(" ", f);
- GET_LENGTH_INC(len, bp);
- for (i = 0; i < len; i++) {
- GET_MEMNUM_INC(mem, bp);
- if (i > 0) fputs(", ", f);
- fprintf(f, "%d", mem);
- }
- break;
-
- case OP_REPEAT:
- case OP_REPEAT_NG:
- {
- mem = *((MemNumType* )bp);
- bp += SIZE_MEMNUM;
- addr = *((RelAddrType* )bp);
- bp += SIZE_RELADDR;
- fprintf(f, ":%d:%d", mem, addr);
- }
- break;
-
- case OP_PUSH_OR_JUMP_EXACT1:
- case OP_PUSH_IF_PEEK_NEXT:
- addr = *((RelAddrType* )bp);
- bp += SIZE_RELADDR;
- fprintf(f, ":(%d)", addr);
- p_string(f, 1, bp);
- bp += 1;
- break;
-
- case OP_LOOK_BEHIND:
- GET_LENGTH_INC(len, bp);
- fprintf(f, ":%d", len);
- break;
-
- case OP_PUSH_LOOK_BEHIND_NOT:
- GET_RELADDR_INC(addr, bp);
- GET_LENGTH_INC(len, bp);
- fprintf(f, ":%d:(%d)", len, addr);
- break;
-
- default:
- fprintf(stderr, "onig_print_compiled_byte_code: undefined code %d\n",
- *--bp);
- }
- }
- fputs("]", f);
- if (nextp) *nextp = bp;
-}
-
-static void
-print_compiled_byte_code_list(FILE* f, regex_t* reg)
-{
- int ncode;
- UChar* bp = reg->p;
- UChar* end = reg->p + reg->used;
-
- fprintf(f, "code length: %d\n", reg->used);
-
- ncode = 0;
- while (bp < end) {
- ncode++;
- if (bp > reg->p) {
- if (ncode % 5 == 0)
- fprintf(f, "\n");
- else
- fputs(" ", f);
- }
- onig_print_compiled_byte_code(f, bp, &bp, reg->enc);
- }
-
- fprintf(f, "\n");
-}
-
-static void
-print_indent_tree(FILE* f, Node* node, int indent)
-{
- int i, type;
- int add = 3;
- UChar* p;
-
- Indent(f, indent);
- if (IS_NULL(node)) {
- fprintf(f, "ERROR: null node!!!\n");
- exit (0);
- }
-
- type = NTYPE(node);
- switch (type) {
- case N_LIST:
- case N_ALT:
- if (NTYPE(node) == N_LIST)
- fprintf(f, "<list:%x>\n", (int )node);
- else
- fprintf(f, "<alt:%x>\n", (int )node);
-
- print_indent_tree(f, NCONS(node).left, indent + add);
- while (IS_NOT_NULL(node = NCONS(node).right)) {
- if (NTYPE(node) != type) {
- fprintf(f, "ERROR: list/alt right is not a cons. %d\n", NTYPE(node));
- exit(0);
- }
- print_indent_tree(f, NCONS(node).left, indent + add);
- }
- break;
-
- case N_STRING:
- fprintf(f, "<string%s:%x>",
- (NSTRING_IS_RAW(node) ? "-raw" : ""), (int )node);
- for (p = NSTRING(node).s; p < NSTRING(node).end; p++) {
- if (*p >= 0x20 && *p < 0x7f)
- fputc(*p, f);
- else {
- fprintf(f, " 0x%02x", *p);
- }
- }
- break;
-
- case N_CCLASS:
- fprintf(f, "<cclass:%x>", (int )node);
- if (IS_CCLASS_NOT(&NCCLASS(node))) fputs(" not", f);
- if (NCCLASS(node).mbuf) {
- BBuf* bbuf = NCCLASS(node).mbuf;
- for (i = 0; i < bbuf->used; i++) {
- if (i > 0) fprintf(f, ",");
- fprintf(f, "%0x", bbuf->p[i]);
- }
- }
- break;
-
- case N_CTYPE:
- fprintf(f, "<ctype:%x> ", (int )node);
- switch (NCTYPE(node).type) {
- case CTYPE_WORD: fputs("word", f); break;
- case CTYPE_NOT_WORD: fputs("not word", f); break;
- default:
- fprintf(f, "ERROR: undefined ctype.\n");
- exit(0);
- }
- break;
-
- case N_ANYCHAR:
- fprintf(f, "<anychar:%x>", (int )node);
- break;
-
- case N_ANCHOR:
- fprintf(f, "<anchor:%x> ", (int )node);
- switch (NANCHOR(node).type) {
- case ANCHOR_BEGIN_BUF: fputs("begin buf", f); break;
- case ANCHOR_END_BUF: fputs("end buf", f); break;
- case ANCHOR_BEGIN_LINE: fputs("begin line", f); break;
- case ANCHOR_END_LINE: fputs("end line", f); break;
- case ANCHOR_SEMI_END_BUF: fputs("semi end buf", f); break;
- case ANCHOR_BEGIN_POSITION: fputs("begin position", f); break;
-
- case ANCHOR_WORD_BOUND: fputs("word bound", f); break;
- case ANCHOR_NOT_WORD_BOUND: fputs("not word bound", f); break;
-#ifdef USE_WORD_BEGIN_END
- case ANCHOR_WORD_BEGIN: fputs("word begin", f); break;
- case ANCHOR_WORD_END: fputs("word end", f); break;
-#endif
- case ANCHOR_PREC_READ: fputs("prec read", f); break;
- case ANCHOR_PREC_READ_NOT: fputs("prec read not", f); break;
- case ANCHOR_LOOK_BEHIND: fputs("look_behind", f); break;
- case ANCHOR_LOOK_BEHIND_NOT: fputs("look_behind_not",f); break;
-
- default:
- fprintf(f, "ERROR: undefined anchor type.\n");
- break;
- }
- break;
-
- case N_BACKREF:
- {
- int* p;
- BackrefNode* br = &(NBACKREF(node));
- p = BACKREFS_P(br);
- fprintf(f, "<backref:%x>", (int )node);
- for (i = 0; i < br->back_num; i++) {
- if (i > 0) fputs(", ", f);
- fprintf(f, "%d", p[i]);
- }
- }
- break;
-
-#ifdef USE_SUBEXP_CALL
- case N_CALL:
- {
- CallNode* cn = &(NCALL(node));
- fprintf(f, "<call:%x>", (int )node);
- p_string(f, cn->name_end - cn->name, cn->name);
- }
- break;
-#endif
-
- case N_QUALIFIER:
- fprintf(f, "<qualifier:%x>{%d,%d}%s\n", (int )node,
- NQUALIFIER(node).lower, NQUALIFIER(node).upper,
- (NQUALIFIER(node).greedy ? "" : "?"));
- print_indent_tree(f, NQUALIFIER(node).target, indent + add);
- break;
-
- case N_EFFECT:
- fprintf(f, "<effect:%x> ", (int )node);
- switch (NEFFECT(node).type) {
- case EFFECT_OPTION:
- fprintf(f, "option:%d\n", NEFFECT(node).option);
- print_indent_tree(f, NEFFECT(node).target, indent + add);
- break;
- case EFFECT_MEMORY:
- fprintf(f, "memory:%d", NEFFECT(node).regnum);
- break;
- case EFFECT_STOP_BACKTRACK:
- fprintf(f, "stop-bt");
- break;
-
- default:
- break;
- }
- fprintf(f, "\n");
- print_indent_tree(f, NEFFECT(node).target, indent + add);
- break;
-
- default:
- fprintf(f, "print_indent_tree: undefined node type %d\n", NTYPE(node));
- break;
- }
-
- if (type != N_LIST && type != N_ALT && type != N_QUALIFIER &&
- type != N_EFFECT)
- fprintf(f, "\n");
- fflush(f);
-}
-#endif /* ONIG_DEBUG */
-
-#ifdef ONIG_DEBUG_PARSE_TREE
-static void
-print_tree(FILE* f, Node* node)
-{
- print_indent_tree(f, node, 0);
-}
-#endif
-/**********************************************************************
- regenc.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 "regint.h"
-
-OnigEncoding OnigEncDefaultCharEncoding = ONIG_ENCODING_INIT_DEFAULT;
-
-extern int
-onigenc_init()
-{
- return 0;
-}
-
-extern OnigEncoding
-onigenc_get_default_encoding()
-{
- return OnigEncDefaultCharEncoding;
-}
-
-extern int
-onigenc_set_default_encoding(OnigEncoding enc)
-{
- OnigEncDefaultCharEncoding = enc;
- return 0;
-}
-
-extern UChar*
-onigenc_get_right_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s)
-{
- UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s);
- if (p < s) {
- p += enc_len(enc, p);
- }
- return p;
-}
-
-extern UChar*
-onigenc_get_right_adjust_char_head_with_prev(OnigEncoding enc,
- const UChar* start, const UChar* s, const UChar** prev)
-{
- UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s);
-
- if (p < s) {
- if (prev) *prev = (const UChar* )p;
- p += enc_len(enc, p);
- }
- else {
- if (prev) *prev = (const UChar* )NULL; /* Sorry */
- }
- return p;
-}
-
-extern UChar*
-onigenc_get_prev_char_head(OnigEncoding enc, const UChar* start, const UChar* s)
-{
- if (s <= start)
- return (UChar* )NULL;
-
- return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1);
-}
-
-extern UChar*
-onigenc_step_back(OnigEncoding enc, const UChar* start, const UChar* s, int n)
-{
- while (ONIG_IS_NOT_NULL(s) && n-- > 0) {
- if (s <= start)
- return (UChar* )NULL;
-
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1);
- }
- return (UChar* )s;
-}
-
-extern UChar*
-onigenc_step(OnigEncoding enc, const UChar* p, const UChar* end, int n)
-{
- UChar* q = (UChar* )p;
- while (n-- > 0) {
- q += ONIGENC_MBC_ENC_LEN(enc, q);
- }
- return (q <= end ? q : NULL);
-}
-
-extern int
-onigenc_strlen(OnigEncoding enc, const UChar* p, const UChar* end)
-{
- int n = 0;
- UChar* q = (UChar* )p;
-
- while (q < end) {
- q += ONIGENC_MBC_ENC_LEN(enc, q);
- n++;
- }
- return n;
-}
-
-extern int
-onigenc_strlen_null(OnigEncoding enc, const UChar* s)
-{
- int n = 0;
- UChar* p = (UChar* )s;
-
- while (1) {
- if (*p == '\0') {
- UChar* q;
- int len = ONIGENC_MBC_MINLEN(enc);
-
- if (len == 1) return n;
- q = p + 1;
- while (len > 1) {
- if (*q != '\0') break;
- q++;
- len--;
- }
- if (len == 1) return n;
- }
- p += ONIGENC_MBC_ENC_LEN(enc, p);
- n++;
- }
-}
-
-extern int
-onigenc_str_bytelen_null(OnigEncoding enc, const UChar* s)
-{
- UChar* start = (UChar* )s;
- UChar* p = (UChar* )s;
-
- while (1) {
- if (*p == '\0') {
- UChar* q;
- int len = ONIGENC_MBC_MINLEN(enc);
-
- if (len == 1) return (int )(p - start);
- q = p + 1;
- while (len > 1) {
- if (*q != '\0') break;
- q++;
- len--;
- }
- if (len == 1) return (int )(p - start);
- }
- p += ONIGENC_MBC_ENC_LEN(enc, p);
- }
-}
-
-#ifndef ONIG_RUBY_M17N
-
-#ifndef NOT_RUBY
-
-#define USE_APPLICATION_TO_LOWER_CASE_TABLE
-
-unsigned short OnigEnc_Unicode_ISO_8859_1_CtypeTable[256] = {
- 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008,
- 0x2008, 0x228c, 0x2289, 0x2288, 0x2288, 0x2288, 0x2008, 0x2008,
- 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008,
- 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008,
- 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0,
- 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0,
- 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0,
- 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0,
- 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2,
- 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2,
- 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2,
- 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x31a0,
- 0x21a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2,
- 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2,
- 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2,
- 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x2008,
- 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0288, 0x0008, 0x0008,
- 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
- 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
- 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
- 0x0284, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0,
- 0x00a0, 0x00a0, 0x10e2, 0x01a0, 0x00a0, 0x00a8, 0x00a0, 0x00a0,
- 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x00a0, 0x10e2, 0x00a0, 0x01a0,
- 0x00a0, 0x10a0, 0x10e2, 0x01a0, 0x10a0, 0x10a0, 0x10a0, 0x01a0,
- 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2,
- 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2,
- 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x00a0,
- 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2,
- 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2,
- 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2,
- 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0,
- 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2
-};
-#endif
-
-const UChar* OnigEncAsciiToLowerCaseTable = (const UChar* )0;
-
-#ifndef USE_APPLICATION_TO_LOWER_CASE_TABLE
-static const UChar BuiltInAsciiToLowerCaseTable[] = {
- '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
- '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
- '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
- '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
- '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
- '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
- '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
- '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
- '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
- '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
- '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
- '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
- '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
- '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
- '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
- '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
- '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
- '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
- '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
- '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
- '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
- '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
- '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
-};
-#endif /* not USE_APPLICATION_TO_LOWER_CASE_TABLE */
-
-#ifdef USE_UPPER_CASE_TABLE
-UChar OnigEncAsciiToUpperCaseTable[256] = {
- '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
- '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
- '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
- '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
- '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
- '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
- '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
- '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
- '\100', '\101', '\102', '\103', '\104', '\105', '\106', '\107',
- '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117',
- '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127',
- '\130', '\131', '\132', '\133', '\134', '\135', '\136', '\137',
- '\140', '\101', '\102', '\103', '\104', '\105', '\106', '\107',
- '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117',
- '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127',
- '\130', '\131', '\132', '\173', '\174', '\175', '\176', '\177',
- '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
- '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
- '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
- '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
- '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
- '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
- '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
- '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
- '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
- '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
- '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
- '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
- '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
-};
-#endif
-
-unsigned short OnigEncAsciiCtypeTable[256] = {
- 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008,
- 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008,
- 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008,
- 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008,
- 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0,
- 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0,
- 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0,
- 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0,
- 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2,
- 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2,
- 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2,
- 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x31a0,
- 0x21a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2,
- 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2,
- 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2,
- 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x2008,
-
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
-};
-
-UChar OnigEncISO_8859_1_ToLowerCaseTable[256] = {
- '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
- '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
- '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
- '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
- '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
- '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
- '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
- '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
- '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
- '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
- '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
- '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
- '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
- '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
- '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
- '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
- '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
- '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
- '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\327',
- '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337',
- '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377'
-};
-
-#ifdef USE_UPPER_CASE_TABLE
-UChar OnigEncISO_8859_1_ToUpperCaseTable[256] = {
- '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
- '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
- '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
- '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
- '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
- '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
- '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
- '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
- '\100', '\101', '\102', '\103', '\104', '\105', '\106', '\107',
- '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117',
- '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127',
- '\130', '\131', '\132', '\133', '\134', '\135', '\136', '\137',
- '\140', '\101', '\102', '\103', '\104', '\105', '\106', '\107',
- '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117',
- '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127',
- '\130', '\131', '\132', '\173', '\174', '\175', '\176', '\177',
- '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
- '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
- '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
- '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
- '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
- '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
- '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
- '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
- '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
- '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
- '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
- '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
- '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
- '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
- '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\367',
- '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\377',
-};
-#endif
-
-extern void
-onigenc_set_default_caseconv_table(const UChar* table)
-{
- if (table == (const UChar* )0) {
-#ifndef USE_APPLICATION_TO_LOWER_CASE_TABLE
- table = BuiltInAsciiToLowerCaseTable;
-#else
- return ;
-#endif
- }
-
- if (table != OnigEncAsciiToLowerCaseTable) {
- OnigEncAsciiToLowerCaseTable = table;
- }
-}
-
-extern UChar*
-onigenc_get_left_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s)
-{
- return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s);
-}
-
-OnigPairAmbigCodes OnigAsciiPairAmbigCodes[] = {
- { 0x41, 0x61 },
- { 0x42, 0x62 },
- { 0x43, 0x63 },
- { 0x44, 0x64 },
- { 0x45, 0x65 },
- { 0x46, 0x66 },
- { 0x47, 0x67 },
- { 0x48, 0x68 },
- { 0x49, 0x69 },
- { 0x4a, 0x6a },
- { 0x4b, 0x6b },
- { 0x4c, 0x6c },
- { 0x4d, 0x6d },
- { 0x4e, 0x6e },
- { 0x4f, 0x6f },
- { 0x50, 0x70 },
- { 0x51, 0x71 },
- { 0x52, 0x72 },
- { 0x53, 0x73 },
- { 0x54, 0x74 },
- { 0x55, 0x75 },
- { 0x56, 0x76 },
- { 0x57, 0x77 },
- { 0x58, 0x78 },
- { 0x59, 0x79 },
- { 0x5a, 0x7a },
-
- { 0x61, 0x41 },
- { 0x62, 0x42 },
- { 0x63, 0x43 },
- { 0x64, 0x44 },
- { 0x65, 0x45 },
- { 0x66, 0x46 },
- { 0x67, 0x47 },
- { 0x68, 0x48 },
- { 0x69, 0x49 },
- { 0x6a, 0x4a },
- { 0x6b, 0x4b },
- { 0x6c, 0x4c },
- { 0x6d, 0x4d },
- { 0x6e, 0x4e },
- { 0x6f, 0x4f },
- { 0x70, 0x50 },
- { 0x71, 0x51 },
- { 0x72, 0x52 },
- { 0x73, 0x53 },
- { 0x74, 0x54 },
- { 0x75, 0x55 },
- { 0x76, 0x56 },
- { 0x77, 0x57 },
- { 0x78, 0x58 },
- { 0x79, 0x59 },
- { 0x7a, 0x5a }
-};
-
-extern int
-onigenc_ascii_get_all_pair_ambig_codes(OnigAmbigType flag,
- OnigPairAmbigCodes** ccs)
-{
- if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) {
- *ccs = OnigAsciiPairAmbigCodes;
- return (sizeof(OnigAsciiPairAmbigCodes) / sizeof(OnigPairAmbigCodes));
- }
- else {
- return 0;
- }
-}
-
-extern int
-onigenc_nothing_get_all_comp_ambig_codes(OnigAmbigType flag,
- OnigCompAmbigCodes** ccs)
-{
- return 0;
-}
-
-extern int
-onigenc_iso_8859_1_get_all_pair_ambig_codes(OnigAmbigType flag,
- OnigPairAmbigCodes** ccs)
-{
- static OnigPairAmbigCodes cc[] = {
- { 0xc0, 0xe0 },
- { 0xc1, 0xe1 },
- { 0xc2, 0xe2 },
- { 0xc3, 0xe3 },
- { 0xc4, 0xe4 },
- { 0xc5, 0xe5 },
- { 0xc6, 0xe6 },
- { 0xc7, 0xe7 },
- { 0xc8, 0xe8 },
- { 0xc9, 0xe9 },
- { 0xca, 0xea },
- { 0xcb, 0xeb },
- { 0xcc, 0xec },
- { 0xcd, 0xed },
- { 0xce, 0xee },
- { 0xcf, 0xef },
-
- { 0xd0, 0xf0 },
- { 0xd1, 0xf1 },
- { 0xd2, 0xf2 },
- { 0xd3, 0xf3 },
- { 0xd4, 0xf4 },
- { 0xd5, 0xf5 },
- { 0xd6, 0xf6 },
- { 0xd8, 0xf8 },
- { 0xd9, 0xf9 },
- { 0xda, 0xfa },
- { 0xdb, 0xfb },
- { 0xdc, 0xfc },
- { 0xdd, 0xfd },
- { 0xde, 0xfe },
-
- { 0xe0, 0xc0 },
- { 0xe1, 0xc1 },
- { 0xe2, 0xc2 },
- { 0xe3, 0xc3 },
- { 0xe4, 0xc4 },
- { 0xe5, 0xc5 },
- { 0xe6, 0xc6 },
- { 0xe7, 0xc7 },
- { 0xe8, 0xc8 },
- { 0xe9, 0xc9 },
- { 0xea, 0xca },
- { 0xeb, 0xcb },
- { 0xec, 0xcc },
- { 0xed, 0xcd },
- { 0xee, 0xce },
- { 0xef, 0xcf },
-
- { 0xf0, 0xd0 },
- { 0xf1, 0xd1 },
- { 0xf2, 0xd2 },
- { 0xf3, 0xd3 },
- { 0xf4, 0xd4 },
- { 0xf5, 0xd5 },
- { 0xf6, 0xd6 },
- { 0xf8, 0xd8 },
- { 0xf9, 0xd9 },
- { 0xfa, 0xda },
- { 0xfb, 0xdb },
- { 0xfc, 0xdc },
- { 0xfd, 0xdd },
- { 0xfe, 0xde }
- };
-
- if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) {
- *ccs = OnigAsciiPairAmbigCodes;
- return (sizeof(OnigAsciiPairAmbigCodes) / sizeof(OnigPairAmbigCodes));
- }
- else if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) {
- *ccs = cc;
- return sizeof(cc) / sizeof(OnigPairAmbigCodes);
- }
- else
- return 0;
-}
-
-extern int
-onigenc_ess_tsett_get_all_comp_ambig_codes(OnigAmbigType flag,
- OnigCompAmbigCodes** ccs)
-{
- static OnigCompAmbigCodes folds[] = {
- { 2, 0xdf, {{ 2, { 0x53, 0x53 } }, { 2, { 0x73, 0x73} } } }
- };
-
- if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) {
- *ccs = folds;
- return sizeof(folds) / sizeof(OnigCompAmbigCodes);
- }
- else
- return 0;
-}
-
-extern int
-onigenc_not_support_get_ctype_code_range(int ctype,
- OnigCodePoint* sbr[], OnigCodePoint* mbr[])
-{
- return ONIG_NO_SUPPORT_CONFIG;
-}
-
-extern int
-onigenc_is_mbc_newline_0x0a(const UChar* p, const UChar* end)
-{
- if (p < end) {
- if (*p == 0x0a) return 1;
- }
- return 0;
-}
-
-/* for single byte encodings */
-extern int
-onigenc_ascii_mbc_to_normalize(OnigAmbigType flag, const UChar** p, const UChar*end,
- UChar* lower)
-{
- if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) {
- *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(**p);
- }
- else {
- *lower = **p;
- }
-
- (*p)++;
- return 1; /* return byte length of converted char to lower */
-}
-
-extern int
-onigenc_ascii_is_mbc_ambiguous(OnigAmbigType flag,
- const UChar** pp, const UChar* end)
-{
- const UChar* p = *pp;
-
- (*pp)++;
- if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) {
- return ONIGENC_IS_ASCII_CODE_CASE_AMBIG(*p);
- }
- else {
- return FALSE;
- }
-}
-
-extern int
-onigenc_single_byte_mbc_enc_len(const UChar* p)
-{
- return 1;
-}
-
-extern OnigCodePoint
-onigenc_single_byte_mbc_to_code(const UChar* p, const UChar* end)
-{
- return (OnigCodePoint )(*p);
-}
-
-extern int
-onigenc_single_byte_code_to_mbclen(OnigCodePoint code)
-{
- return 1;
-}
-
-extern int
-onigenc_single_byte_code_to_mbc_first(OnigCodePoint code)
-{
- return (code & 0xff);
-}
-
-extern int
-onigenc_single_byte_code_to_mbc(OnigCodePoint code, UChar *buf)
-{
- *buf = (UChar )(code & 0xff);
- return 1;
-}
-
-extern UChar*
-onigenc_single_byte_left_adjust_char_head(const UChar* start, const UChar* s)
-{
- return (UChar* )s;
-}
-
-extern int
-onigenc_always_true_is_allowed_reverse_match(const UChar* s, const UChar* end)
-{
- return TRUE;
-}
-
-extern int
-onigenc_always_false_is_allowed_reverse_match(const UChar* s, const UChar* end)
-{
- return FALSE;
-}
-
-extern OnigCodePoint
-onigenc_mbn_mbc_to_code(OnigEncoding enc, const UChar* p, const UChar* end)
-{
- int c, i, len;
- OnigCodePoint n;
-
- len = enc_len(enc, 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;
-}
-
-extern int
-onigenc_mbn_mbc_to_normalize(OnigEncoding enc, 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(enc, p);
- if (lower != p) {
- int i;
- for (i = 0; i < len; i++) {
- *lower++ = *p++;
- }
- }
- (*pp) += len;
- return len; /* return byte length of converted to lower char */
- }
-}
-
-extern int
-onigenc_mbn_is_mbc_ambiguous(OnigEncoding enc, OnigAmbigType flag,
- const UChar** pp, const UChar* end)
-{
- const UChar* p = *pp;
-
- if (ONIGENC_IS_MBC_ASCII(p)) {
- (*pp)++;
- if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) {
- return ONIGENC_IS_ASCII_CODE_CASE_AMBIG(*p);
- }
- else {
- return FALSE;
- }
- }
-
- (*pp) += enc_len(enc, p);
- return FALSE;
-}
-
-extern int
-onigenc_mb2_code_to_mbclen(OnigCodePoint code)
-{
- if ((code & 0xff00) != 0) return 2;
- else return 1;
-}
-
-extern int
-onigenc_mb4_code_to_mbclen(OnigCodePoint code)
-{
- if ((code & 0xff000000) != 0) return 4;
- else if ((code & 0xff0000) != 0) return 3;
- else if ((code & 0xff00) != 0) return 2;
- else return 1;
-}
-
-extern int
-onigenc_mb2_code_to_mbc_first(OnigCodePoint code)
-{
- int first;
-
- if ((code & 0xff00) != 0) {
- first = (code >> 8) & 0xff;
- }
- else {
- return (int )code;
- }
- return first;
-}
-
-extern int
-onigenc_mb4_code_to_mbc_first(OnigCodePoint code)
-{
- int first;
-
- if ((code & 0xff000000) != 0) {
- first = (code >> 24) & 0xff;
- }
- else if ((code & 0xff0000) != 0) {
- first = (code >> 16) & 0xff;
- }
- else if ((code & 0xff00) != 0) {
- first = (code >> 8) & 0xff;
- }
- else {
- return (int )code;
- }
- return first;
-}
-
-extern int
-onigenc_mb2_code_to_mbc(OnigEncoding enc, OnigCodePoint code, UChar *buf)
-{
- UChar *p = buf;
-
- if ((code & 0xff00) != 0) {
- *p++ = (UChar )((code >> 8) & 0xff);
- }
- *p++ = (UChar )(code & 0xff);
-
-#if 1
- if (enc_len(enc, buf) != (p - buf))
- return ONIGENCERR_INVALID_WIDE_CHAR_VALUE;
-#endif
- return p - buf;
-}
-
-extern int
-onigenc_mb4_code_to_mbc(OnigEncoding enc, OnigCodePoint code, UChar *buf)
-{
- UChar *p = buf;
-
- if ((code & 0xff000000) != 0) {
- *p++ = (UChar )((code >> 24) & 0xff);
- }
- 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(enc, buf) != (p - buf))
- return ONIGENCERR_INVALID_WIDE_CHAR_VALUE;
-#endif
- return p - buf;
-}
-
-extern int
-onigenc_mb2_is_code_ctype(OnigEncoding enc, OnigCodePoint code,
- unsigned int ctype)
-{
- if ((ctype & ONIGENC_CTYPE_WORD) != 0) {
- if (code < 128)
- return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype);
- else
- return (ONIGENC_CODE_TO_MBCLEN(enc, 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;
-}
-
-extern int
-onigenc_mb4_is_code_ctype(OnigEncoding enc, OnigCodePoint code,
- unsigned int ctype)
-{
- if ((ctype & ONIGENC_CTYPE_WORD) != 0) {
- if (code < 128)
- return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype);
- else
- return (ONIGENC_CODE_TO_MBCLEN(enc, 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;
-}
-
-extern int
-onigenc_with_ascii_strncmp(OnigEncoding enc, const UChar* p, const UChar* end,
- const UChar* sascii /* ascii */, int n)
-{
- int x, c;
-
- while (n-- > 0) {
- if (p >= end) return (int )(*sascii);
-
- c = (int )ONIGENC_MBC_TO_CODE(enc, p, end);
- x = *sascii - c;
- if (x) return x;
-
- sascii++;
- p += enc_len(enc, p);
- }
- return 0;
-}
-
-#else /* ONIG_RUBY_M17N */
-
-extern int
-onigenc_is_code_ctype(OnigEncoding enc, OnigCodePoint code, int ctype)
-{
- switch (ctype) {
- case ONIGENC_CTYPE_NEWLINE:
- if (code == 0x0a) return 1;
- break;
-
- case ONIGENC_CTYPE_ALPHA:
- return m17n_isalpha(enc, code);
- break;
- case ONIGENC_CTYPE_BLANK:
- return ONIGENC_IS_CODE_BLANK(enc, (int )(code));
- break;
- case ONIGENC_CTYPE_CNTRL:
- return m17n_iscntrl(enc, code);
- break;
- case ONIGENC_CTYPE_DIGIT:
- return m17n_isdigit(enc, code);
- break;
- case ONIGENC_CTYPE_GRAPH:
- return ONIGENC_IS_CODE_GRAPH(enc, (int )(code));
- break;
- case ONIGENC_CTYPE_LOWER:
- return m17n_islower(enc, code);
- break;
- case ONIGENC_CTYPE_PRINT:
- return m17n_isprint(enc, code);
- break;
- case ONIGENC_CTYPE_PUNCT:
- return m17n_ispunct(enc, code);
- break;
- case ONIGENC_CTYPE_SPACE:
- return m17n_isspace(enc, code);
- break;
- case ONIGENC_CTYPE_UPPER:
- return m17n_isupper(enc, code);
- break;
- case ONIGENC_CTYPE_XDIGIT:
- return m17n_isxdigit(enc, code);
- break;
- case ONIGENC_CTYPE_WORD:
- return m17n_iswchar(enc, code);
- break;
- case ONIGENC_CTYPE_ASCII:
- return (code < 128 ? TRUE : FALSE);
- break;
- case ONIGENC_CTYPE_ALNUM:
- return m17n_isalnum(enc, code);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-extern int
-onigenc_code_to_mbc(OnigEncoding enc, OnigCodePoint code, UChar *buf)
-{
- int c, len;
-
- m17n_mbcput(enc, code, buf);
- c = m17n_firstbyte(enc, code);
- len = enc_len(enc, c);
- return len;
-}
-
-extern int
-onigenc_mbc_to_lower(OnigEncoding enc, UChar* p, UChar* buf)
-{
- unsigned int c, low;
-
- c = m17n_codepoint(enc, p, p + enc_len(enc, *p));
- low = m17n_tolower(enc, c);
- m17n_mbcput(enc, low, buf);
-
- return m17n_codelen(enc, low);
-}
-
-extern int
-onigenc_is_mbc_ambiguous(OnigEncoding enc, OnigAmbigType flag,
- UChar** pp, UChar* end)
-{
- int len;
- unsigned int c;
- UChar* p = *pp;
-
- len = enc_len(enc, *p);
- (*pp) += len;
- c = m17n_codepoint(enc, p, p + len);
-
- if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) {
- if (m17n_isupper(enc, c) || m17n_islower(enc, c))
- return TRUE;
- }
-
- return FALSE;
-}
-
-extern UChar*
-onigenc_get_left_adjust_char_head(OnigEncoding enc, UChar* start, UChar* s)
-{
- UChar *p;
- int len;
-
- if (s <= start) return s;
- p = s;
-
- while (!m17n_islead(enc, *p) && p > start) p--;
- while (p + (len = enc_len(enc, *p)) < s) {
- p += len;
- }
- if (p + len == s) return s;
- return p;
-}
-
-extern int
-onigenc_is_allowed_reverse_match(OnigEncoding enc,
- const UChar* s, const UChar* end)
-{
- return ONIGENC_IS_SINGLEBYTE(enc);
-}
-
-extern void
-onigenc_set_default_caseconv_table(UChar* table) { }
-
-#endif /* ONIG_RUBY_M17N */
-/**********************************************************************
- regerror.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 "regint.h"
-#include <stdio.h> /* for vsnprintf() */
-
-#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
-
-extern char*
-onig_error_code_to_format(int code)
-{
- char *p;
-
- if (code >= 0) return (char* )0;
-
- switch (code) {
- case ONIG_MISMATCH:
- p = "mismatch"; break;
- case ONIG_NO_SUPPORT_CONFIG:
- p = "no support in this configuration"; break;
- case ONIGERR_MEMORY:
- p = "fail to memory allocation"; break;
- case ONIGERR_MATCH_STACK_LIMIT_OVER:
- p = "match-stack limit over"; break;
- case ONIGERR_TYPE_BUG:
- p = "undefined type (bug)"; break;
- case ONIGERR_PARSER_BUG:
- p = "internal parser error (bug)"; break;
- case ONIGERR_STACK_BUG:
- p = "stack error (bug)"; break;
- case ONIGERR_UNDEFINED_BYTECODE:
- p = "undefined bytecode (bug)"; break;
- case ONIGERR_UNEXPECTED_BYTECODE:
- p = "unexpected bytecode (bug)"; break;
- case ONIGERR_DEFAULT_ENCODING_IS_NOT_SETTED:
- p = "default multibyte-encoding is not setted"; break;
- case ONIGERR_SPECIFIED_ENCODING_CANT_CONVERT_TO_WIDE_CHAR:
- p = "can't convert to wide-char on specified multibyte-encoding"; break;
- case ONIGERR_INVALID_ARGUMENT:
- p = "invalid argument"; break;
- case ONIGERR_END_PATTERN_AT_LEFT_BRACE:
- p = "end pattern at left brace"; break;
- case ONIGERR_END_PATTERN_AT_LEFT_BRACKET:
- p = "end pattern at left bracket"; break;
- case ONIGERR_EMPTY_CHAR_CLASS:
- p = "empty char-class"; break;
- case ONIGERR_PREMATURE_END_OF_CHAR_CLASS:
- p = "premature end of char-class"; break;
- case ONIGERR_END_PATTERN_AT_ESCAPE:
- p = "end pattern at escape"; break;
- case ONIGERR_END_PATTERN_AT_META:
- p = "end pattern at meta"; break;
- case ONIGERR_END_PATTERN_AT_CONTROL:
- p = "end pattern at control"; break;
- case ONIGERR_META_CODE_SYNTAX:
- p = "illegal meta-code syntax"; break;
- case ONIGERR_CONTROL_CODE_SYNTAX:
- p = "illegal control-code syntax"; break;
- case ONIGERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE:
- p = "char-class value at end of range"; break;
- case ONIGERR_CHAR_CLASS_VALUE_AT_START_OF_RANGE:
- p = "char-class value at start of range"; break;
- case ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS:
- p = "unmatched range specifier in char-class"; break;
- case ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED:
- p = "target of repeat operator is not specified"; break;
- case ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID:
- p = "target of repeat operator is invalid"; break;
- case ONIGERR_NESTED_REPEAT_OPERATOR:
- p = "nested repeat operator"; break;
- case ONIGERR_UNMATCHED_CLOSE_PARENTHESIS:
- p = "unmatched close parenthesis"; break;
- case ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS:
- p = "end pattern with unmatched parenthesis"; break;
- case ONIGERR_END_PATTERN_IN_GROUP:
- p = "end pattern in group"; break;
- case ONIGERR_UNDEFINED_GROUP_OPTION:
- p = "undefined group option"; break;
- case ONIGERR_INVALID_POSIX_BRACKET_TYPE:
- p = "invalid POSIX bracket type"; break;
- case ONIGERR_INVALID_LOOK_BEHIND_PATTERN:
- p = "invalid pattern in look-behind"; break;
- case ONIGERR_INVALID_REPEAT_RANGE_PATTERN:
- p = "invalid repeat range {lower,upper}"; break;
- case ONIGERR_TOO_BIG_NUMBER:
- p = "too big number"; break;
- case ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE:
- p = "too big number for repeat range"; break;
- case ONIGERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE:
- p = "upper is smaller than lower in repeat range"; break;
- case ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS:
- p = "empty range in char class"; break;
- case ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE:
- p = "mismatch multibyte code length in char-class range"; break;
- case ONIGERR_TOO_MANY_MULTI_BYTE_RANGES:
- p = "too many multibyte code ranges are specified"; break;
- case ONIGERR_TOO_SHORT_MULTI_BYTE_STRING:
- p = "too short multibyte code string"; break;
- case ONIGERR_TOO_BIG_BACKREF_NUMBER:
- p = "too big backref number"; break;
- case ONIGERR_INVALID_BACKREF:
-#ifdef USE_NAMED_GROUP
- p = "invalid backref number/name"; break;
-#else
- p = "invalid backref number"; break;
-#endif
- case ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED:
- p = "numbered backref/call is not allowed. (use name)"; break;
- case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
- p = "too big wide-char value"; break;
- case ONIGERR_TOO_LONG_WIDE_CHAR_VALUE:
- p = "too long wide-char value"; break;
- case ONIGERR_INVALID_WIDE_CHAR_VALUE:
- p = "invalid wide-char value"; break;
- case ONIGERR_EMPTY_GROUP_NAME:
- p = "group name is empty"; break;
- case ONIGERR_INVALID_GROUP_NAME:
- p = "invalid group name <%n>"; break;
- case ONIGERR_INVALID_CHAR_IN_GROUP_NAME:
-#ifdef USE_NAMED_GROUP
- p = "invalid char in group name <%n>"; break;
-#else
- p = "invalid char in group number <%n>"; break;
-#endif
- case ONIGERR_UNDEFINED_NAME_REFERENCE:
- p = "undefined name <%n> reference"; break;
- case ONIGERR_UNDEFINED_GROUP_REFERENCE:
- p = "undefined group <%n> reference"; break;
- case ONIGERR_MULTIPLEX_DEFINED_NAME:
- p = "multiplex defined name <%n>"; break;
- case ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL:
- p = "multiplex definition name <%n> call"; break;
- case ONIGERR_NEVER_ENDING_RECURSION:
- p = "never ending recursion"; break;
- case ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY:
- p = "group number is too big for capture history"; break;
- case ONIGERR_INVALID_CHAR_PROPERTY_NAME:
- p = "invalid character property name {%n}"; break;
- case ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION:
- p = "not supported encoding combination"; break;
- case ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT:
- p = "over thread pass limit count"; break;
-
- default:
- p = "undefined error code"; break;
- }
-
- return p;
-}
-
-
-/* for ONIG_MAX_ERROR_MESSAGE_LEN */
-#define MAX_ERROR_PAR_LEN 30
-
-extern int
-#ifdef HAVE_STDARG_PROTOTYPES
-onig_error_code_to_str(UChar* s, int code, ...)
-#else
-onig_error_code_to_str(s, code, va_alist)
- UChar* s;
- int code;
- va_dcl
-#endif
-{
- UChar *p, *q;
- OnigErrorInfo* einfo;
- int len;
- va_list vargs;
-
- va_init_list(vargs, code);
-
- switch (code) {
- case ONIGERR_UNDEFINED_NAME_REFERENCE:
- case ONIGERR_UNDEFINED_GROUP_REFERENCE:
- case ONIGERR_MULTIPLEX_DEFINED_NAME:
- case ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL:
- case ONIGERR_INVALID_GROUP_NAME:
- case ONIGERR_INVALID_CHAR_IN_GROUP_NAME:
- case ONIGERR_INVALID_CHAR_PROPERTY_NAME:
- einfo = va_arg(vargs, OnigErrorInfo*);
- len = einfo->par_end - einfo->par;
- q = onig_error_code_to_format(code);
- p = s;
- while (*q != '\0') {
- if (*q == '%') {
- q++;
- if (*q == 'n') { /* '%n': name */
- if (len > MAX_ERROR_PAR_LEN) {
- xmemcpy(p, einfo->par, MAX_ERROR_PAR_LEN - 3);
- p += (MAX_ERROR_PAR_LEN - 3);
- xmemcpy(p, "...", 3);
- p += 3;
- }
- else {
- xmemcpy(p, einfo->par, len);
- p += len;
- }
- q++;
- }
- else
- goto normal_char;
- }
- else {
- normal_char:
- *p++ = *q++;
- }
- }
- *p = '\0';
- len = p - s;
- break;
-
- default:
- q = onig_error_code_to_format(code);
- len = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, q);
- xmemcpy(s, q, len);
- s[len] = '\0';
- break;
- }
-
- va_end(vargs);
- return len;
-}
-
-
-void
-#ifdef HAVE_STDARG_PROTOTYPES
-onig_snprintf_with_pattern(char buf[], int bufsize, OnigEncoding enc,
- char* pat, char* pat_end, char *fmt, ...)
-#else
-onig_snprintf_with_pattern(buf, bufsize, enc, pat, pat_end, fmt, va_alist)
- char buf[];
- int bufsize;
- OnigEncoding enc;
- char* pat;
- char* pat_end;
- const char *fmt;
- va_dcl
-#endif
-{
- int n, need, len;
- UChar *p, *s, *bp;
- char bs[6];
- va_list args;
-
- va_init_list(args, fmt);
- n = vsnprintf(buf, bufsize, fmt, args);
- va_end(args);
-
- need = (pat_end - pat) * 4 + 4;
-
- if (n + need < bufsize) {
- strcat(buf, ": /");
- s = buf + onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, buf);
-
- p = pat;
- while (p < (UChar* )pat_end) {
- if (*p == MC_ESC(enc)) {
- *s++ = *p++;
- len = enc_len(enc, p);
- while (len-- > 0) *s++ = *p++;
- }
- else if (*p == '/') {
- *s++ = (unsigned char )MC_ESC(enc);
- *s++ = *p++;
- }
- else if (ONIGENC_IS_MBC_HEAD(enc, p)) {
- len = enc_len(enc, p);
- if (ONIGENC_MBC_MINLEN(enc) == 1) {
- while (len-- > 0) *s++ = *p++;
- }
- else { /* for UTF16 */
- int blen;
-
- while (len-- > 0) {
- sprintf(bs, "\\%03o", *p++ & 0377);
- blen = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, bs);
- bp = bs;
- while (blen-- > 0) *s++ = *bp++;
- }
- }
- }
- else if (!ONIGENC_IS_CODE_PRINT(enc, *p) &&
- !ONIGENC_IS_CODE_SPACE(enc, *p)) {
- sprintf(bs, "\\%03o", *p++ & 0377);
- len = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, bs);
- bp = bs;
- while (len-- > 0) *s++ = *bp++;
- }
- else {
- *s++ = *p++;
- }
- }
-
- *s++ = '/';
- *s = '\0';
- }
-}
-/**********************************************************************
- regexec.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 "regint.h"
-
-#ifdef USE_CAPTURE_HISTORY
-static void history_tree_free(OnigCaptureTreeNode* node);
-
-static void
-history_tree_clear(OnigCaptureTreeNode* node)
-{
- int i;
-
- if (IS_NOT_NULL(node)) {
- for (i = 0; i < node->num_childs; i++) {
- if (IS_NOT_NULL(node->childs[i])) {
- history_tree_free(node->childs[i]);
- }
- }
- for (i = 0; i < node->allocated; i++) {
- node->childs[i] = (OnigCaptureTreeNode* )0;
- }
- node->num_childs = 0;
- node->beg = ONIG_REGION_NOTPOS;
- node->end = ONIG_REGION_NOTPOS;
- node->group = -1;
- }
-}
-
-static void
-history_tree_free(OnigCaptureTreeNode* node)
-{
- history_tree_clear(node);
- xfree(node);
-}
-
-static void
-history_root_free(OnigRegion* r)
-{
- if (IS_NOT_NULL(r->history_root)) {
- history_tree_free(r->history_root);
- r->history_root = (OnigCaptureTreeNode* )0;
- }
-}
-
-static OnigCaptureTreeNode*
-history_node_new()
-{
- OnigCaptureTreeNode* node;
-
- node = (OnigCaptureTreeNode* )xmalloc(sizeof(OnigCaptureTreeNode));
- CHECK_NULL_RETURN(node);
- node->childs = (OnigCaptureTreeNode** )0;
- node->allocated = 0;
- node->num_childs = 0;
- node->group = -1;
- node->beg = ONIG_REGION_NOTPOS;
- node->end = ONIG_REGION_NOTPOS;
-
- return node;
-}
-
-static int
-history_tree_add_child(OnigCaptureTreeNode* parent, OnigCaptureTreeNode* child)
-{
-#define HISTORY_TREE_INIT_ALLOC_SIZE 8
-
- if (parent->num_childs >= parent->allocated) {
- int n, i;
-
- if (IS_NULL(parent->childs)) {
- n = HISTORY_TREE_INIT_ALLOC_SIZE;
- parent->childs =
- (OnigCaptureTreeNode** )xmalloc(sizeof(OnigCaptureTreeNode*) * n);
- }
- else {
- n = parent->allocated * 2;
- parent->childs =
- (OnigCaptureTreeNode** )xrealloc(parent->childs,
- sizeof(OnigCaptureTreeNode*) * n);
- }
- CHECK_NULL_RETURN_VAL(parent->childs, ONIGERR_MEMORY);
- for (i = parent->allocated; i < n; i++) {
- parent->childs[i] = (OnigCaptureTreeNode* )0;
- }
- parent->allocated = n;
- }
-
- parent->childs[parent->num_childs] = child;
- parent->num_childs++;
- return 0;
-}
-
-static OnigCaptureTreeNode*
-history_tree_clone(OnigCaptureTreeNode* node)
-{
- int i;
- OnigCaptureTreeNode *clone, *child;
-
- clone = history_node_new();
- CHECK_NULL_RETURN(clone);
-
- clone->beg = node->beg;
- clone->end = node->end;
- for (i = 0; i < node->num_childs; i++) {
- child = history_tree_clone(node->childs[i]);
- if (IS_NULL(child)) {
- history_tree_free(clone);
- return (OnigCaptureTreeNode* )0;
- }
- history_tree_add_child(clone, child);
- }
-
- return clone;
-}
-
-extern OnigCaptureTreeNode*
-onig_get_capture_tree(OnigRegion* region)
-{
- return region->history_root;
-}
-#endif /* USE_CAPTURE_HISTORY */
-
-extern void
-onig_region_clear(OnigRegion* region)
-{
- int i;
-
- for (i = 0; i < region->num_regs; i++) {
- region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS;
- }
-#ifdef USE_CAPTURE_HISTORY
- history_root_free(region);
-#endif
-}
-
-extern int
-onig_region_resize(OnigRegion* region, int n)
-{
- region->num_regs = n;
-
- if (n < ONIG_NREGION)
- n = ONIG_NREGION;
-
- if (region->allocated == 0) {
- region->beg = (int* )xmalloc(n * sizeof(int));
- region->end = (int* )xmalloc(n * sizeof(int));
-
- if (region->beg == 0 || region->end == 0)
- return ONIGERR_MEMORY;
-
- region->allocated = n;
- }
- else if (region->allocated < n) {
- region->beg = (int* )xrealloc(region->beg, n * sizeof(int));
- region->end = (int* )xrealloc(region->end, n * sizeof(int));
-
- if (region->beg == 0 || region->end == 0)
- return ONIGERR_MEMORY;
-
- region->allocated = n;
- }
-
- return 0;
-}
-
-extern int
-onig_region_resize_clear(OnigRegion* region, int n)
-{
- int r;
-
- r = onig_region_resize(region, n);
- if (r != 0) return r;
- onig_region_clear(region);
- return 0;
-}
-
-extern int
-onig_region_set(OnigRegion* region, int at, int beg, int end)
-{
- if (at < 0) return ONIGERR_INVALID_ARGUMENT;
-
- if (at >= region->allocated) {
- int r = onig_region_resize(region, at + 1);
- if (r < 0) return r;
- }
-
- region->beg[at] = beg;
- region->end[at] = end;
- return 0;
-}
-
-extern void
-onig_region_init(OnigRegion* region)
-{
- region->num_regs = 0;
- region->allocated = 0;
- region->beg = (int* )0;
- region->end = (int* )0;
- region->history_root = (OnigCaptureTreeNode* )0;
-}
-
-extern OnigRegion*
-onig_region_new()
-{
- OnigRegion* r;
-
- r = (OnigRegion* )xmalloc(sizeof(OnigRegion));
- onig_region_init(r);
- return r;
-}
-
-extern void
-onig_region_free(OnigRegion* r, int free_self)
-{
- if (r) {
- if (r->allocated > 0) {
- if (r->beg) xfree(r->beg);
- if (r->end) xfree(r->end);
- r->allocated = 0;
- }
-#ifdef USE_CAPTURE_HISTORY
- history_root_free(r);
-#endif
- if (free_self) xfree(r);
- }
-}
-
-extern void
-onig_region_copy(OnigRegion* to, OnigRegion* from)
-{
-#define RREGC_SIZE (sizeof(int) * from->num_regs)
- int i;
-
- if (to == from) return;
-
- if (to->allocated == 0) {
- if (from->num_regs > 0) {
- to->beg = (int* )xmalloc(RREGC_SIZE);
- to->end = (int* )xmalloc(RREGC_SIZE);
- to->allocated = from->num_regs;
- }
- }
- else if (to->allocated < from->num_regs) {
- to->beg = (int* )xrealloc(to->beg, RREGC_SIZE);
- to->end = (int* )xrealloc(to->end, RREGC_SIZE);
- to->allocated = from->num_regs;
- }
-
- for (i = 0; i < from->num_regs; i++) {
- to->beg[i] = from->beg[i];
- to->end[i] = from->end[i];
- }
- to->num_regs = from->num_regs;
-
-#ifdef USE_CAPTURE_HISTORY
- history_root_free(to);
-
- if (IS_NOT_NULL(from->history_root)) {
- to->history_root = history_tree_clone(from->history_root);
- }
-#endif
-}
-
-
-/** stack **/
-#define INVALID_STACK_INDEX -1
-typedef long StackIndex;
-
-typedef struct _StackType {
- unsigned int type;
- union {
- struct {
- UChar *pcode; /* byte code position */
- UChar *pstr; /* string position */
- UChar *pstr_prev; /* previous char position of pstr */
- } state;
- struct {
- int count; /* for OP_REPEAT_INC, OP_REPEAT_INC_NG */
- UChar *pcode; /* byte code position (head of repeated target) */
- int num; /* repeat id */
- } repeat;
- struct {
- StackIndex si; /* index of stack */
- } repeat_inc;
- struct {
- int num; /* memory num */
- UChar *pstr; /* start/end position */
- /* Following information is setted, if this stack type is MEM-START */
- StackIndex start; /* prev. info (for backtrack "(...)*" ) */
- StackIndex end; /* prev. info (for backtrack "(...)*" ) */
- } mem;
- struct {
- int num; /* null check id */
- UChar *pstr; /* start position */
- } null_check;
-#ifdef USE_SUBEXP_CALL
- struct {
- UChar *ret_addr; /* byte code position */
- int num; /* null check id */
- UChar *pstr; /* string position */
- } call_frame;
-#endif
- } u;
-} StackType;
-
-/* stack type */
-/* used by normal-POP */
-#define STK_ALT 0x0001
-#define STK_LOOK_BEHIND_NOT 0x0003
-#define STK_POS_NOT 0x0005
-/* avoided by normal-POP, but value should be small */
-#define STK_NULL_CHECK_START 0x0100
-/* handled by normal-POP */
-#define STK_MEM_START 0x0200
-#define STK_MEM_END 0x0300
-#define STK_REPEAT_INC 0x0400
-/* avoided by normal-POP */
-#define STK_POS 0x0500 /* used when POP-POS */
-#define STK_STOP_BT 0x0600 /* mark for "(?>...)" */
-#define STK_REPEAT 0x0700
-#define STK_CALL_FRAME 0x0800
-#define STK_RETURN 0x0900
-#define STK_MEM_END_MARK 0x0a00
-#define STK_VOID 0x0b00 /* for fill a blank */
-#define STK_NULL_CHECK_END 0x0c00 /* for recursive call */
-
-/* stack type check mask */
-#define STK_MASK_POP_USED 0x00ff
-#define IS_TO_VOID_TARGET(stk) \
- (((stk)->type & STK_MASK_POP_USED) || (stk)->type == STK_NULL_CHECK_START)
-
-typedef struct {
- void* stack_p;
- int stack_n;
- OnigOptionType options;
- OnigRegion* region;
- const UChar* start; /* search start position (for \G: BEGIN_POSITION) */
-} MatchArg;
-
-#define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start) do {\
- (msa).stack_p = (void* )0;\
- (msa).options = (arg_option);\
- (msa).region = (arg_region);\
- (msa).start = (arg_start);\
-} while (0)
-
-#define MATCH_ARG_FREE(msa) if ((msa).stack_p) xfree((msa).stack_p)
-
-
-#define STACK_INIT(alloc_addr, ptr_num, stack_num) do {\
- if (msa->stack_p) {\
- alloc_addr = (char* )xalloca(sizeof(char*) * (ptr_num));\
- stk_alloc = (StackType* )(msa->stack_p);\
- stk_base = stk_alloc;\
- stk = stk_base;\
- stk_end = stk_base + msa->stack_n;\
- }\
- else {\
- alloc_addr = (char* )xalloca(sizeof(char*) * (ptr_num)\
- + sizeof(StackType) * (stack_num));\
- stk_alloc = (StackType* )(alloc_addr + sizeof(char*) * (ptr_num));\
- stk_base = stk_alloc;\
- stk = stk_base;\
- stk_end = stk_base + (stack_num);\
- }\
-} while(0)
-
-#define STACK_SAVE do{\
- if (stk_base != stk_alloc) {\
- msa->stack_p = stk_base;\
- msa->stack_n = stk_end - stk_base;\
- };\
-} while(0)
-
-static unsigned int MatchStackLimitSize = DEFAULT_MATCH_STACK_LIMIT_SIZE;
-
-extern unsigned int
-onig_get_match_stack_limit_size(void)
-{
- return MatchStackLimitSize;
-}
-
-extern int
-onig_set_match_stack_limit_size(unsigned int size)
-{
- MatchStackLimitSize = size;
- return 0;
-}
-
-static int
-stack_double(StackType** arg_stk_base, StackType** arg_stk_end,
- StackType** arg_stk, StackType* stk_alloc, MatchArg* msa)
-{
- unsigned int n;
- StackType *x, *stk_base, *stk_end, *stk;
-
- stk_base = *arg_stk_base;
- stk_end = *arg_stk_end;
- stk = *arg_stk;
-
- n = stk_end - stk_base;
- if (stk_base == stk_alloc && IS_NULL(msa->stack_p)) {
- x = (StackType* )xmalloc(sizeof(StackType) * n * 2);
- if (IS_NULL(x)) {
- STACK_SAVE;
- return ONIGERR_MEMORY;
- }
- xmemcpy(x, stk_base, n * sizeof(StackType));
- n *= 2;
- }
- else {
- n *= 2;
- if (MatchStackLimitSize != 0 && n > MatchStackLimitSize) {
- if ((unsigned int )(stk_end - stk_base) == MatchStackLimitSize)
- return ONIGERR_MATCH_STACK_LIMIT_OVER;
- else
- n = MatchStackLimitSize;
- }
- x = (StackType* )xrealloc(stk_base, sizeof(StackType) * n);
- if (IS_NULL(x)) {
- STACK_SAVE;
- return ONIGERR_MEMORY;
- }
- }
- *arg_stk = x + (stk - stk_base);
- *arg_stk_base = x;
- *arg_stk_end = x + n;
- return 0;
-}
-
-#define STACK_ENSURE(n) do {\
- if (stk_end - stk < (n)) {\
- int r = stack_double(&stk_base, &stk_end, &stk, stk_alloc, msa);\
- if (r != 0) { STACK_SAVE; return r; } \
- }\
-} while(0)
-
-#define STACK_AT(index) (stk_base + (index))
-#define GET_STACK_INDEX(stk) ((stk) - stk_base)
-
-#define STACK_PUSH(stack_type,pat,s,sprev) do {\
- STACK_ENSURE(1);\
- stk->type = (stack_type);\
- stk->u.state.pcode = (pat);\
- stk->u.state.pstr = (s);\
- stk->u.state.pstr_prev = (sprev);\
- STACK_INC;\
-} while(0)
-
-#define STACK_PUSH_ENSURED(stack_type,pat) do {\
- stk->type = (stack_type);\
- stk->u.state.pcode = (pat);\
- STACK_INC;\
-} while(0)
-
-#define STACK_PUSH_TYPE(stack_type) do {\
- STACK_ENSURE(1);\
- stk->type = (stack_type);\
- STACK_INC;\
-} while(0)
-
-#define STACK_PUSH_ALT(pat,s,sprev) STACK_PUSH(STK_ALT,pat,s,sprev)
-#define STACK_PUSH_POS(s,sprev) STACK_PUSH(STK_POS,NULL_UCHARP,s,sprev)
-#define STACK_PUSH_POS_NOT(pat,s,sprev) STACK_PUSH(STK_POS_NOT,pat,s,sprev)
-#define STACK_PUSH_STOP_BT STACK_PUSH_TYPE(STK_STOP_BT)
-#define STACK_PUSH_LOOK_BEHIND_NOT(pat,s,sprev) \
- STACK_PUSH(STK_LOOK_BEHIND_NOT,pat,s,sprev)
-
-#define STACK_PUSH_REPEAT(id, pat) do {\
- STACK_ENSURE(1);\
- stk->type = STK_REPEAT;\
- stk->u.repeat.num = (id);\
- stk->u.repeat.pcode = (pat);\
- stk->u.repeat.count = 0;\
- STACK_INC;\
-} while(0)
-
-#define STACK_PUSH_REPEAT_INC(sindex) do {\
- STACK_ENSURE(1);\
- stk->type = STK_REPEAT_INC;\
- stk->u.repeat_inc.si = (sindex);\
- STACK_INC;\
-} while(0)
-
-#define STACK_PUSH_MEM_START(mnum, s) do {\
- STACK_ENSURE(1);\
- stk->type = STK_MEM_START;\
- stk->u.mem.num = (mnum);\
- stk->u.mem.pstr = (s);\
- stk->u.mem.start = mem_start_stk[mnum];\
- stk->u.mem.end = mem_end_stk[mnum];\
- mem_start_stk[mnum] = GET_STACK_INDEX(stk);\
- mem_end_stk[mnum] = INVALID_STACK_INDEX;\
- STACK_INC;\
-} while(0)
-
-#define STACK_PUSH_MEM_END(mnum, s) do {\
- STACK_ENSURE(1);\
- stk->type = STK_MEM_END;\
- stk->u.mem.num = (mnum);\
- stk->u.mem.pstr = (s);\
- stk->u.mem.start = mem_start_stk[mnum];\
- stk->u.mem.end = mem_end_stk[mnum];\
- mem_end_stk[mnum] = GET_STACK_INDEX(stk);\
- STACK_INC;\
-} while(0)
-
-#define STACK_PUSH_MEM_END_MARK(mnum) do {\
- STACK_ENSURE(1);\
- stk->type = STK_MEM_END_MARK;\
- stk->u.mem.num = (mnum);\
- STACK_INC;\
-} while(0)
-
-#define STACK_GET_MEM_START(mnum, k) do {\
- int level = 0;\
- k = stk;\
- while (k > stk_base) {\
- k--;\
- if ((k->type == STK_MEM_END_MARK || k->type == STK_MEM_END) \
- && k->u.mem.num == (mnum)) {\
- level++;\
- }\
- else if (k->type == STK_MEM_START && k->u.mem.num == (mnum)) {\
- if (level == 0) break;\
- level--;\
- }\
- }\
-} while (0)
-
-#define STACK_GET_MEM_RANGE(k, mnum, start, end) do {\
- int level = 0;\
- while (k < stk) {\
- if (k->type == STK_MEM_START && k->u.mem.num == (mnum)) {\
- if (level == 0) (start) = k->u.mem.pstr;\
- level++;\
- }\
- else if (k->type == STK_MEM_END && k->u.mem.num == (mnum)) {\
- level--;\
- if (level == 0) {\
- (end) = k->u.mem.pstr;\
- break;\
- }\
- }\
- k++;\
- }\
-} while (0)
-
-#define STACK_PUSH_NULL_CHECK_START(cnum, s) do {\
- STACK_ENSURE(1);\
- stk->type = STK_NULL_CHECK_START;\
- stk->u.null_check.num = (cnum);\
- stk->u.null_check.pstr = (s);\
- STACK_INC;\
-} while(0)
-
-#define STACK_PUSH_NULL_CHECK_END(cnum) do {\
- STACK_ENSURE(1);\
- stk->type = STK_NULL_CHECK_END;\
- stk->u.null_check.num = (cnum);\
- STACK_INC;\
-} while(0)
-
-#define STACK_PUSH_CALL_FRAME(pat) do {\
- STACK_ENSURE(1);\
- stk->type = STK_CALL_FRAME;\
- stk->u.call_frame.ret_addr = (pat);\
- STACK_INC;\
-} while(0)
-
-#define STACK_PUSH_RETURN do {\
- STACK_ENSURE(1);\
- stk->type = STK_RETURN;\
- STACK_INC;\
-} while(0)
-
-
-#ifdef ONIG_DEBUG
-#define STACK_BASE_CHECK(p) \
- if ((p) < stk_base) goto stack_error;
-#else
-#define STACK_BASE_CHECK(p)
-#endif
-
-#define STACK_POP_ONE do {\
- stk--;\
- STACK_BASE_CHECK(stk); \
-} while(0)
-
-#define STACK_POP do {\
- switch (pop_level) {\
- case STACK_POP_LEVEL_FREE:\
- while (1) {\
- stk--;\
- STACK_BASE_CHECK(stk); \
- if ((stk->type & STK_MASK_POP_USED) != 0) break;\
- }\
- break;\
- case STACK_POP_LEVEL_MEM_START:\
- while (1) {\
- stk--;\
- STACK_BASE_CHECK(stk); \
- if ((stk->type & STK_MASK_POP_USED) != 0) break;\
- else if (stk->type == STK_MEM_START) {\
- mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
- mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
- }\
- }\
- break;\
- default:\
- while (1) {\
- stk--;\
- STACK_BASE_CHECK(stk); \
- if ((stk->type & STK_MASK_POP_USED) != 0) break;\
- else if (stk->type == STK_MEM_START) {\
- mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
- mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
- }\
- else if (stk->type == STK_REPEAT_INC) {\
- STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\
- }\
- else if (stk->type == STK_MEM_END) {\
- mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
- mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
- }\
- }\
- break;\
- }\
-} while(0)
-
-#define STACK_POP_TIL_POS_NOT do {\
- while (1) {\
- stk--;\
- STACK_BASE_CHECK(stk); \
- if (stk->type == STK_POS_NOT) break;\
- else if (stk->type == STK_MEM_START) {\
- mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
- mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
- }\
- else if (stk->type == STK_REPEAT_INC) {\
- STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\
- }\
- else if (stk->type == STK_MEM_END) {\
- mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
- mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
- }\
- }\
-} while(0)
-
-#define STACK_POP_TIL_LOOK_BEHIND_NOT do {\
- while (1) {\
- stk--;\
- STACK_BASE_CHECK(stk); \
- if (stk->type == STK_LOOK_BEHIND_NOT) break;\
- else if (stk->type == STK_MEM_START) {\
- mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
- mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
- }\
- else if (stk->type == STK_REPEAT_INC) {\
- STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\
- }\
- else if (stk->type == STK_MEM_END) {\
- mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\
- mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\
- }\
- }\
-} while(0)
-
-#define STACK_POS_END(k) do {\
- k = stk;\
- while (1) {\
- k--;\
- STACK_BASE_CHECK(k); \
- if (IS_TO_VOID_TARGET(k)) {\
- k->type = STK_VOID;\
- }\
- else if (k->type == STK_POS) {\
- k->type = STK_VOID;\
- break;\
- }\
- }\
-} while(0)
-
-#define STACK_STOP_BT_END do {\
- StackType *k = stk;\
- while (1) {\
- k--;\
- STACK_BASE_CHECK(k); \
- if (IS_TO_VOID_TARGET(k)) {\
- k->type = STK_VOID;\
- }\
- else if (k->type == STK_STOP_BT) {\
- k->type = STK_VOID;\
- break;\
- }\
- }\
-} while(0)
-
-#define STACK_NULL_CHECK(isnull,id,s) do {\
- StackType* k = stk;\
- while (1) {\
- k--;\
- STACK_BASE_CHECK(k); \
- if (k->type == STK_NULL_CHECK_START) {\
- if (k->u.null_check.num == (id)) {\
- (isnull) = (k->u.null_check.pstr == (s));\
- break;\
- }\
- }\
- }\
-} while(0)
-
-#define STACK_NULL_CHECK_REC(isnull,id,s) do {\
- int level = 0;\
- StackType* k = stk;\
- while (1) {\
- k--;\
- STACK_BASE_CHECK(k); \
- if (k->type == STK_NULL_CHECK_START) {\
- if (k->u.null_check.num == (id)) {\
- if (level == 0) {\
- (isnull) = (k->u.null_check.pstr == (s));\
- break;\
- }\
- else level--;\
- }\
- }\
- else if (k->type == STK_NULL_CHECK_END) {\
- level++;\
- }\
- }\
-} while(0)
-
-#define STACK_NULL_CHECK_MEMST(isnull,id,s,reg) do {\
- StackType* k = stk;\
- while (1) {\
- k--;\
- STACK_BASE_CHECK(k); \
- if (k->type == STK_NULL_CHECK_START) {\
- if (k->u.null_check.num == (id)) {\
- if (k->u.null_check.pstr != (s)) {\
- (isnull) = 0;\
- break;\
- }\
- else {\
- UChar* endp;\
- (isnull) = 1;\
- while (k < stk) {\
- if (k->type == STK_MEM_START) {\
- if (k->u.mem.end == INVALID_STACK_INDEX) {\
- (isnull) = 0; break;\
- }\
- if (BIT_STATUS_AT(reg->bt_mem_end, k->u.mem.num))\
- endp = STACK_AT(k->u.mem.end)->u.mem.pstr;\
- else\
- endp = (UChar* )k->u.mem.end;\
- if (STACK_AT(k->u.mem.start)->u.mem.pstr != endp) {\
- (isnull) = 0; break;\
- }\
- else if (endp != s) {\
- (isnull) = -1; /* empty, but position changed */ \
- }\
- }\
- k++;\
- }\
- break;\
- }\
- }\
- }\
- }\
-} while(0)
-
-#define STACK_NULL_CHECK_MEMST_REC(isnull,id,s,reg) do {\
- int level = 0;\
- StackType* k = stk;\
- while (1) {\
- k--;\
- STACK_BASE_CHECK(k); \
- if (k->type == STK_NULL_CHECK_START) {\
- if (k->u.null_check.num == (id)) {\
- if (level == 0) {\
- if (k->u.null_check.pstr != (s)) {\
- (isnull) = 0;\
- break;\
- }\
- else {\
- UChar* endp;\
- (isnull) = 1;\
- while (k < stk) {\
- if (k->type == STK_MEM_START) {\
- if (k->u.mem.end == INVALID_STACK_INDEX) {\
- (isnull) = 0; break;\
- }\
- if (BIT_STATUS_AT(reg->bt_mem_end, k->u.mem.num))\
- endp = STACK_AT(k->u.mem.end)->u.mem.pstr;\
- else\
- endp = (UChar* )k->u.mem.end;\
- if (STACK_AT(k->u.mem.start)->u.mem.pstr != endp) {\
- (isnull) = 0; break;\
- }\
- else if (endp != s) {\
- (isnull) = -1; /* empty, but position changed */ \
- }\
- }\
- k++;\
- }\
- break;\
- }\
- }\
- else {\
- level--;\
- }\
- }\
- }\
- else if (k->type == STK_NULL_CHECK_END) {\
- if (k->u.null_check.num == (id)) level++;\
- }\
- }\
-} while(0)
-
-#define STACK_GET_REPEAT(id, k) do {\
- int level = 0;\
- k = stk;\
- while (1) {\
- k--;\
- STACK_BASE_CHECK(k); \
- if (k->type == STK_REPEAT) {\
- if (level == 0) {\
- if (k->u.repeat.num == (id)) {\
- break;\
- }\
- }\
- }\
- else if (k->type == STK_CALL_FRAME) level--;\
- else if (k->type == STK_RETURN) level++;\
- }\
-} while (0)
-
-#define STACK_RETURN(addr) do {\
- int level = 0;\
- StackType* k = stk;\
- while (1) {\
- k--;\
- STACK_BASE_CHECK(k); \
- if (k->type == STK_CALL_FRAME) {\
- if (level == 0) {\
- (addr) = k->u.call_frame.ret_addr;\
- break;\
- }\
- else level--;\
- }\
- else if (k->type == STK_RETURN)\
- level++;\
- }\
-} while(0)
-
-
-#define STRING_CMP(s1,s2,len) do {\
- while (len-- > 0) {\
- if (*s1++ != *s2++) goto fail;\
- }\
-} while(0)
-
-#define STRING_CMP_IC(ambig_flag,s1,ps2,len) do {\
- if (string_cmp_ic(encode, ambig_flag, s1, ps2, len) == 0) \
- goto fail; \
-} while(0)
-
-static int string_cmp_ic(OnigEncoding enc, int ambig_flag,
- UChar* s1, UChar** ps2, int mblen)
-{
- UChar buf1[ONIGENC_MBC_NORMALIZE_MAXLEN];
- UChar buf2[ONIGENC_MBC_NORMALIZE_MAXLEN];
- UChar *p1, *p2, *end, *s2, *end2;
- int len1, len2;
-
- s2 = *ps2;
- end = s1 + mblen;
- end2 = s2 + mblen;
- while (s1 < end) {
- len1 = ONIGENC_MBC_TO_NORMALIZE(enc, ambig_flag, &s1, end, buf1);
- len2 = ONIGENC_MBC_TO_NORMALIZE(enc, ambig_flag, &s2, end2, buf2);
- if (len1 != len2) return 0;
- p1 = buf1;
- p2 = buf2;
- while (len1-- > 0) {
- if (*p1 != *p2) return 0;
- p1++;
- p2++;
- }
- }
-
- *ps2 = s2;
- return 1;
-}
-
-#define STRING_CMP_VALUE(s1,s2,len,is_fail) do {\
- is_fail = 0;\
- while (len-- > 0) {\
- if (*s1++ != *s2++) {\
- is_fail = 1; break;\
- }\
- }\
-} while(0)
-
-#define STRING_CMP_VALUE_IC(ambig_flag,s1,ps2,len,is_fail) do {\
- if (string_cmp_ic(encode, ambig_flag, s1, ps2, len) == 0) \
- is_fail = 1; \
- else \
- is_fail = 0; \
-} while(0)
-
-#define ON_STR_BEGIN(s) ((s) == str)
-#define ON_STR_END(s) ((s) == end)
-#define IS_EMPTY_STR (str == end)
-
-#define DATA_ENSURE(n) \
- if (s + (n) > end) goto fail
-
-#define DATA_ENSURE_CHECK(n) (s + (n) <= end)
-
-#ifdef USE_CAPTURE_HISTORY
-static int
-make_capture_history_tree(OnigCaptureTreeNode* node, StackType** kp,
- StackType* stk_top, UChar* str, regex_t* reg)
-{
- int n, r;
- OnigCaptureTreeNode* child;
- StackType* k = *kp;
-
- while (k < stk_top) {
- if (k->type == STK_MEM_START) {
- n = k->u.mem.num;
- if (n <= ONIG_MAX_CAPTURE_HISTORY_GROUP &&
- BIT_STATUS_AT(reg->capture_history, n) != 0) {
- child = history_node_new();
- CHECK_NULL_RETURN_VAL(child, ONIGERR_MEMORY);
- child->group = n;
- child->beg = (int )(k->u.mem.pstr - str);
- r = history_tree_add_child(node, child);
- if (r != 0) return r;
- *kp = (k + 1);
- r = make_capture_history_tree(child, kp, stk_top, str, reg);
- if (r != 0) return r;
-
- k = *kp;
- child->end = (int )(k->u.mem.pstr - str);
- }
- }
- else if (k->type == STK_MEM_END) {
- if (k->u.mem.num == node->group) {
- node->end = (int )(k->u.mem.pstr - str);
- *kp = k;
- return 0;
- }
- }
- k++;
- }
-
- return 1; /* 1: root node ending. */
-}
-#endif
-
-#ifdef RUBY_PLATFORM
-
-typedef struct {
- int state;
- regex_t* reg;
- MatchArg* msa;
- StackType* stk_base;
-} TrapEnsureArg;
-
-static VALUE
-trap_ensure(VALUE arg)
-{
- TrapEnsureArg* ta = (TrapEnsureArg* )arg;
-
- if (ta->state == 0) { /* trap_exec() is not normal return */
- ONIG_STATE_DEC(ta->reg);
- if (! IS_NULL(ta->msa->stack_p) && ta->stk_base != ta->msa->stack_p)
- xfree(ta->stk_base);
-
- MATCH_ARG_FREE(*(ta->msa));
- }
-
- return Qnil;
-}
-
-static VALUE
-trap_exec(VALUE arg)
-{
- TrapEnsureArg* ta;
-
- rb_trap_exec();
-
- ta = (TrapEnsureArg* )arg;
- ta->state = 1; /* normal return */
- return Qnil;
-}
-
-extern void
-onig_exec_trap(regex_t* reg, MatchArg* msa, StackType* stk_base)
-{
- VALUE arg;
- TrapEnsureArg ta;
-
- ta.state = 0;
- ta.reg = reg;
- ta.msa = msa;
- ta.stk_base = stk_base;
- arg = (VALUE )(&ta);
- rb_ensure(trap_exec, arg, trap_ensure, arg);
-}
-
-#define CHECK_INTERRUPT_IN_MATCH_AT do {\
- if (rb_trap_pending) {\
- if (! rb_prohibit_interrupt) {\
- onig_exec_trap(reg, msa, stk_base);\
- }\
- }\
-} while (0)
-#else
-#define CHECK_INTERRUPT_IN_MATCH_AT
-#endif /* RUBY_PLATFORM */
-
-#ifdef ONIG_DEBUG_STATISTICS
-
-#define USE_TIMEOFDAY
-
-#ifdef USE_TIMEOFDAY
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-static struct timeval ts, te;
-#define GETTIME(t) gettimeofday(&(t), (struct timezone* )0)
-#define TIMEDIFF(te,ts) (((te).tv_usec - (ts).tv_usec) + \
- (((te).tv_sec - (ts).tv_sec)*1000000))
-#else
-#ifdef HAVE_SYS_TIMES_H
-#include <sys/times.h>
-#endif
-static struct tms ts, te;
-#define GETTIME(t) times(&(t))
-#define TIMEDIFF(te,ts) ((te).tms_utime - (ts).tms_utime)
-#endif
-
-static int OpCounter[256];
-static int OpPrevCounter[256];
-static unsigned long OpTime[256];
-static int OpCurr = OP_FINISH;
-static int OpPrevTarget = OP_FAIL;
-static int MaxStackDepth = 0;
-
-#define STAT_OP_IN(opcode) do {\
- if (opcode == OpPrevTarget) OpPrevCounter[OpCurr]++;\
- OpCurr = opcode;\
- OpCounter[opcode]++;\
- GETTIME(ts);\
-} while (0)
-
-#define STAT_OP_OUT do {\
- GETTIME(te);\
- OpTime[OpCurr] += TIMEDIFF(te, ts);\
-} while (0)
-
-#ifdef RUBY_PLATFORM
-
-/*
- * :nodoc:
- */
-static VALUE onig_stat_print()
-{
- onig_print_statistics(stderr);
- return Qnil;
-}
-#endif
-
-extern void onig_statistics_init()
-{
- int i;
- for (i = 0; i < 256; i++) {
- OpCounter[i] = OpPrevCounter[i] = 0; OpTime[i] = 0;
- }
- MaxStackDepth = 0;
-
-#ifdef RUBY_PLATFORM
- rb_define_global_function("onig_stat_print", onig_stat_print, 0);
-#endif
-}
-
-extern void
-onig_print_statistics(FILE* f)
-{
- int i;
- fprintf(f, " count prev time\n");
- for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {
- fprintf(f, "%8d: %8d: %10ld: %s\n",
- OpCounter[i], OpPrevCounter[i], OpTime[i], OnigOpInfo[i].name);
- }
- fprintf(f, "\nmax stack depth: %d\n", MaxStackDepth);
-}
-
-#define STACK_INC do {\
- stk++;\
- if (stk - stk_base > MaxStackDepth) \
- MaxStackDepth = stk - stk_base;\
-} while (0)
-
-#else
-#define STACK_INC stk++
-
-#define STAT_OP_IN(opcode)
-#define STAT_OP_OUT
-#endif
-
-extern int
-onig_is_in_code_range(const UChar* p, OnigCodePoint code)
-{
- OnigCodePoint n, *data;
- OnigCodePoint low, high, x;
-
- GET_CODE_POINT(n, p);
- data = (OnigCodePoint* )p;
- data++;
-
- for (low = 0, high = n; low < high; ) {
- x = (low + high) >> 1;
- if (code > data[x * 2 + 1])
- low = x + 1;
- else
- high = x;
- }
-
- return ((low < n && code >= data[low * 2]) ? 1 : 0);
-}
-
-static int
-code_is_in_cclass_node(void* node, OnigCodePoint code, int enclen)
-{
- unsigned int in_cc;
- CClassNode* cc = (CClassNode* )node;
-
- if (enclen == 1) {
- in_cc = BITSET_AT(cc->bs, code);
- }
- else {
- UChar* p = ((BBuf* )(cc->mbuf))->p;
- in_cc = onig_is_in_code_range(p, code);
- }
-
- if (IS_CCLASS_NOT(cc)) {
- return (in_cc ? 0 : 1);
- }
- else {
- return (in_cc ? 1 : 0);
- }
-}
-
-/* matching region of POSIX API */
-typedef int regoff_t;
-
-typedef struct {
- regoff_t rm_so;
- regoff_t rm_eo;
-} posix_regmatch_t;
-
-/* match data(str - end) from position (sstart). */
-/* if sstart == str then set sprev to NULL. */
-static int
-match_at(regex_t* reg, const UChar* str, const UChar* end, const UChar* sstart,
- UChar* sprev, MatchArg* msa)
-{
- static UChar FinishCode[] = { OP_FINISH };
-
- int i, n, num_mem, best_len, pop_level;
- LengthType tlen, tlen2;
- MemNumType mem;
- RelAddrType addr;
- OnigOptionType option = reg->options;
- OnigEncoding encode = reg->enc;
- OnigAmbigType ambig_flag = reg->ambig_flag;
- UChar *s, *q, *sbegin;
- UChar *p = reg->p;
- char *alloca_base;
- StackType *stk_alloc, *stk_base, *stk, *stk_end;
- StackType *stkp; /* used as any purpose. */
- StackIndex si;
- StackIndex *repeat_stk;
- StackIndex *mem_start_stk, *mem_end_stk;
- n = reg->num_repeat + reg->num_mem * 2;
-
- STACK_INIT(alloca_base, n, INIT_MATCH_STACK_SIZE);
- pop_level = reg->stack_pop_level;
- num_mem = reg->num_mem;
- repeat_stk = (StackIndex* )alloca_base;
-
- mem_start_stk = (StackIndex* )(repeat_stk + reg->num_repeat);
- mem_end_stk = mem_start_stk + num_mem;
- mem_start_stk--; /* for index start from 1,
- mem_start_stk[1]..mem_start_stk[num_mem] */
- mem_end_stk--; /* for index start from 1,
- mem_end_stk[1]..mem_end_stk[num_mem] */
- for (i = 1; i <= num_mem; i++) {
- mem_start_stk[i] = mem_end_stk[i] = INVALID_STACK_INDEX;
- }
-
-#ifdef ONIG_DEBUG_MATCH
- fprintf(stderr, "match_at: str: %d, end: %d, start: %d, sprev: %d\n",
- (int )str, (int )end, (int )sstart, (int )sprev);
- fprintf(stderr, "size: %d, start offset: %d\n",
- (int )(end - str), (int )(sstart - str));
-#endif
-
- STACK_PUSH_ENSURED(STK_ALT, FinishCode); /* bottom stack */
- best_len = ONIG_MISMATCH;
- s = (UChar* )sstart;
- while (1) {
-#ifdef ONIG_DEBUG_MATCH
- {
- UChar *q, *bp, buf[50];
- int len;
- fprintf(stderr, "%4d> \"", (int )(s - str));
- bp = buf;
- for (i = 0, q = s; i < 7 && q < end; i++) {
- len = enc_len(encode, q);
- while (len-- > 0) *bp++ = *q++;
- }
- if (q < end) { xmemcpy(bp, "...\"", 4); bp += 4; }
- else { xmemcpy(bp, "\"", 1); bp += 1; }
- *bp = 0;
- fputs(buf, stderr);
- for (i = 0; i < 20 - (bp - buf); i++) fputc(' ', stderr);
- onig_print_compiled_byte_code(stderr, p, NULL, encode);
- fprintf(stderr, "\n");
- }
-#endif
-
- sbegin = s;
- switch (*p++) {
- case OP_END: STAT_OP_IN(OP_END);
- n = s - sstart;
- if (n > best_len) {
- OnigRegion* region = msa->region;
- best_len = n;
- if (region) {
-#ifdef USE_POSIX_REGION_OPTION
- if (IS_POSIX_REGION(msa->options)) {
- posix_regmatch_t* rmt = (posix_regmatch_t* )region;
-
- rmt[0].rm_so = sstart - str;
- rmt[0].rm_eo = s - str;
- for (i = 1; i <= num_mem; i++) {
- if (mem_end_stk[i] != INVALID_STACK_INDEX) {
- if (BIT_STATUS_AT(reg->bt_mem_start, i))
- rmt[i].rm_so = STACK_AT(mem_start_stk[i])->u.mem.pstr - str;
- else
- rmt[i].rm_so = (UChar* )((void* )(mem_start_stk[i])) - str;
-
- rmt[i].rm_eo = (BIT_STATUS_AT(reg->bt_mem_end, i)
- ? STACK_AT(mem_end_stk[i])->u.mem.pstr
- : (UChar* )((void* )mem_end_stk[i])) - str;
- }
- else {
- rmt[i].rm_so = rmt[i].rm_eo = ONIG_REGION_NOTPOS;
- }
- }
- }
- else {
-#endif /* USE_POSIX_REGION_OPTION */
- region->beg[0] = sstart - str;
- region->end[0] = s - str;
- for (i = 1; i <= num_mem; i++) {
- if (mem_end_stk[i] != INVALID_STACK_INDEX) {
- if (BIT_STATUS_AT(reg->bt_mem_start, i))
- region->beg[i] = STACK_AT(mem_start_stk[i])->u.mem.pstr - str;
- else
- region->beg[i] = (UChar* )((void* )mem_start_stk[i]) - str;
-
- region->end[i] = (BIT_STATUS_AT(reg->bt_mem_end, i)
- ? STACK_AT(mem_end_stk[i])->u.mem.pstr
- : (UChar* )((void* )mem_end_stk[i])) - str;
- }
- else {
- region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS;
- }
- }
-
-#ifdef USE_CAPTURE_HISTORY
- if (reg->capture_history != 0) {
- int r;
- OnigCaptureTreeNode* node;
-
- if (IS_NULL(region->history_root)) {
- region->history_root = node = history_node_new();
- CHECK_NULL_RETURN_VAL(node, ONIGERR_MEMORY);
- }
- else {
- node = region->history_root;
- history_tree_clear(node);
- }
-
- node->group = 0;
- node->beg = sstart - str;
- node->end = s - str;
-
- stkp = stk_base;
- r = make_capture_history_tree(region->history_root, &stkp,
- stk, (UChar* )str, reg);
- if (r < 0) {
- best_len = r; /* error code */
- goto finish;
- }
- }
-#endif /* USE_CAPTURE_HISTORY */
-#ifdef USE_POSIX_REGION_OPTION
- } /* else IS_POSIX_REGION() */
-#endif
- } /* if (region) */
- } /* n > best_len */
- STAT_OP_OUT;
-
- if (IS_FIND_CONDITION(option)) {
- if (IS_FIND_NOT_EMPTY(option) && s == sstart) {
- best_len = ONIG_MISMATCH;
- goto fail; /* for retry */
- }
- if (IS_FIND_LONGEST(option) && s < end) {
- goto fail; /* for retry */
- }
- }
-
- /* default behavior: return first-matching result. */
- goto finish;
- break;
-
- case OP_EXACT1: STAT_OP_IN(OP_EXACT1);
-#if 0
- DATA_ENSURE(1);
- if (*p != *s) goto fail;
- p++; s++;
-#endif
- if (*p != *s++) goto fail;
- DATA_ENSURE(0);
- p++;
- STAT_OP_OUT;
- break;
-
- case OP_EXACT1_IC: STAT_OP_IN(OP_EXACT1_IC);
- {
- int len;
- UChar *q, *ss, *sp, lowbuf[ONIGENC_MBC_NORMALIZE_MAXLEN];
-
- DATA_ENSURE(1);
- ss = s;
- sp = p;
-
- exact1_ic_retry:
- len = ONIGENC_MBC_TO_NORMALIZE(encode, ambig_flag, &s, end, lowbuf);
- DATA_ENSURE(0);
- q = lowbuf;
- while (len-- > 0) {
- if (*p != *q) {
-#if 1
- if ((ambig_flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) {
- ambig_flag &= ~ONIGENC_AMBIGUOUS_MATCH_COMPOUND;
- s = ss;
- p = sp;
- goto exact1_ic_retry;
- }
- else
- goto fail;
-#else
- goto fail;
-#endif
- }
- p++; q++;
- }
- }
- STAT_OP_OUT;
- break;
-
- case OP_EXACT2: STAT_OP_IN(OP_EXACT2);
- DATA_ENSURE(2);
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- sprev = s;
- p++; s++;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_EXACT3: STAT_OP_IN(OP_EXACT3);
- DATA_ENSURE(3);
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- sprev = s;
- p++; s++;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_EXACT4: STAT_OP_IN(OP_EXACT4);
- DATA_ENSURE(4);
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- sprev = s;
- p++; s++;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_EXACT5: STAT_OP_IN(OP_EXACT5);
- DATA_ENSURE(5);
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- sprev = s;
- p++; s++;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_EXACTN: STAT_OP_IN(OP_EXACTN);
- GET_LENGTH_INC(tlen, p);
- DATA_ENSURE(tlen);
- while (tlen-- > 0) {
- if (*p++ != *s++) goto fail;
- }
- sprev = s - 1;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_EXACTN_IC: STAT_OP_IN(OP_EXACTN_IC);
- {
- int len;
- UChar *ss, *sp, *q, *endp, lowbuf[ONIGENC_MBC_NORMALIZE_MAXLEN];
-
- GET_LENGTH_INC(tlen, p);
- endp = p + tlen;
-
- while (p < endp) {
- sprev = s;
- DATA_ENSURE(1);
- ss = s;
- sp = p;
-
- exactn_ic_retry:
- len = ONIGENC_MBC_TO_NORMALIZE(encode, ambig_flag, &s, end, lowbuf);
- DATA_ENSURE(0);
- q = lowbuf;
- while (len-- > 0) {
- if (*p != *q) {
-#if 1
- if ((ambig_flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) {
- ambig_flag &= ~ONIGENC_AMBIGUOUS_MATCH_COMPOUND;
- s = ss;
- p = sp;
- goto exactn_ic_retry;
- }
- else
- goto fail;
-#else
- goto fail;
-#endif
- }
- p++; q++;
- }
- }
- }
-
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_EXACTMB2N1: STAT_OP_IN(OP_EXACTMB2N1);
- DATA_ENSURE(2);
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- STAT_OP_OUT;
- break;
-
- case OP_EXACTMB2N2: STAT_OP_IN(OP_EXACTMB2N2);
- DATA_ENSURE(4);
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- sprev = s;
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_EXACTMB2N3: STAT_OP_IN(OP_EXACTMB2N3);
- DATA_ENSURE(6);
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- sprev = s;
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_EXACTMB2N: STAT_OP_IN(OP_EXACTMB2N);
- GET_LENGTH_INC(tlen, p);
- DATA_ENSURE(tlen * 2);
- while (tlen-- > 0) {
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- }
- sprev = s - 2;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_EXACTMB3N: STAT_OP_IN(OP_EXACTMB3N);
- GET_LENGTH_INC(tlen, p);
- DATA_ENSURE(tlen * 3);
- while (tlen-- > 0) {
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- }
- sprev = s - 3;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_EXACTMBN: STAT_OP_IN(OP_EXACTMBN);
- GET_LENGTH_INC(tlen, p); /* mb-len */
- GET_LENGTH_INC(tlen2, p); /* string len */
- tlen2 *= tlen;
- DATA_ENSURE(tlen2);
- while (tlen2-- > 0) {
- if (*p != *s) goto fail;
- p++; s++;
- }
- sprev = s - tlen;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_CCLASS: STAT_OP_IN(OP_CCLASS);
- DATA_ENSURE(1);
- if (BITSET_AT(((BitSetRef )p), *s) == 0) goto fail;
- p += SIZE_BITSET;
- s += enc_len(encode, s); /* OP_CCLASS can match mb-code. \D, \S */
- STAT_OP_OUT;
- break;
-
- case OP_CCLASS_MB: STAT_OP_IN(OP_CCLASS_MB);
- if (! ONIGENC_IS_MBC_HEAD(encode, s)) goto fail;
-
- cclass_mb:
- GET_LENGTH_INC(tlen, p);
- {
- OnigCodePoint code;
- UChar *ss;
- int mb_len;
-
- DATA_ENSURE(1);
- mb_len = enc_len(encode, s);
- DATA_ENSURE(mb_len);
- ss = s;
- s += mb_len;
- code = ONIGENC_MBC_TO_CODE(encode, ss, s);
-
-#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
- if (! onig_is_in_code_range(p, code)) goto fail;
-#else
- q = p;
- ALIGNMENT_RIGHT(q);
- if (! onig_is_in_code_range(q, code)) goto fail;
-#endif
- }
- p += tlen;
- STAT_OP_OUT;
- break;
-
- case OP_CCLASS_MIX: STAT_OP_IN(OP_CCLASS_MIX);
- DATA_ENSURE(1);
- if (ONIGENC_IS_MBC_HEAD(encode, s)) {
- p += SIZE_BITSET;
- goto cclass_mb;
- }
- else {
- if (BITSET_AT(((BitSetRef )p), *s) == 0)
- goto fail;
-
- p += SIZE_BITSET;
- GET_LENGTH_INC(tlen, p);
- p += tlen;
- s++;
- }
- STAT_OP_OUT;
- break;
-
- case OP_CCLASS_NOT: STAT_OP_IN(OP_CCLASS_NOT);
- DATA_ENSURE(1);
- if (BITSET_AT(((BitSetRef )p), *s) != 0) goto fail;
- p += SIZE_BITSET;
- s += enc_len(encode, s);
- STAT_OP_OUT;
- break;
-
- case OP_CCLASS_MB_NOT: STAT_OP_IN(OP_CCLASS_MB_NOT);
- DATA_ENSURE(1);
- if (! ONIGENC_IS_MBC_HEAD(encode, s)) {
- s++;
- GET_LENGTH_INC(tlen, p);
- p += tlen;
- goto cc_mb_not_success;
- }
-
- cclass_mb_not:
- GET_LENGTH_INC(tlen, p);
- {
- OnigCodePoint code;
- UChar *ss;
- int mb_len = enc_len(encode, s);
-
- if (s + mb_len > end) {
- DATA_ENSURE(1);
- s = (UChar* )end;
- p += tlen;
- goto cc_mb_not_success;
- }
-
- ss = s;
- s += mb_len;
- code = ONIGENC_MBC_TO_CODE(encode, ss, s);
-
-#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
- if (onig_is_in_code_range(p, code)) goto fail;
-#else
- q = p;
- ALIGNMENT_RIGHT(q);
- if (onig_is_in_code_range(q, code)) goto fail;
-#endif
- }
- p += tlen;
-
- cc_mb_not_success:
- STAT_OP_OUT;
- break;
-
- case OP_CCLASS_MIX_NOT: STAT_OP_IN(OP_CCLASS_MIX_NOT);
- DATA_ENSURE(1);
- if (ONIGENC_IS_MBC_HEAD(encode, s)) {
- p += SIZE_BITSET;
- goto cclass_mb_not;
- }
- else {
- if (BITSET_AT(((BitSetRef )p), *s) != 0)
- goto fail;
-
- p += SIZE_BITSET;
- GET_LENGTH_INC(tlen, p);
- p += tlen;
- s++;
- }
- STAT_OP_OUT;
- break;
-
- case OP_CCLASS_NODE: STAT_OP_IN(OP_CCLASS_NODE);
- {
- OnigCodePoint code;
- void *node;
- int mb_len;
- UChar *ss;
-
- DATA_ENSURE(1);
- GET_POINTER_INC(node, p);
- mb_len = enc_len(encode, s);
- ss = s;
- s += mb_len;
- code = ONIGENC_MBC_TO_CODE(encode, ss, s);
- if (code_is_in_cclass_node(node, code, mb_len) == 0) goto fail;
- }
- STAT_OP_OUT;
- break;
-
- case OP_ANYCHAR: STAT_OP_IN(OP_ANYCHAR);
- DATA_ENSURE(1);
- n = enc_len(encode, s);
- DATA_ENSURE(n);
- if (ONIGENC_IS_MBC_NEWLINE(encode, s, end)) goto fail;
- s += n;
- STAT_OP_OUT;
- break;
-
- case OP_ANYCHAR_ML: STAT_OP_IN(OP_ANYCHAR_ML);
- DATA_ENSURE(1);
- n = enc_len(encode, s);
- DATA_ENSURE(n);
- s += n;
- STAT_OP_OUT;
- break;
-
- case OP_ANYCHAR_STAR: STAT_OP_IN(OP_ANYCHAR_STAR);
- while (s < end) {
- STACK_PUSH_ALT(p, s, sprev);
- n = enc_len(encode, s);
- DATA_ENSURE(n);
- if (ONIGENC_IS_MBC_NEWLINE(encode, s, end)) goto fail;
- sprev = s;
- s += n;
- }
- STAT_OP_OUT;
- break;
-
- case OP_ANYCHAR_ML_STAR: STAT_OP_IN(OP_ANYCHAR_ML_STAR);
- while (s < end) {
- STACK_PUSH_ALT(p, s, sprev);
- n = enc_len(encode, s);
- if (n > 1) {
- DATA_ENSURE(n);
- sprev = s;
- s += n;
- }
- else {
- sprev = s;
- s++;
- }
- }
- STAT_OP_OUT;
- break;
-
- case OP_ANYCHAR_STAR_PEEK_NEXT: STAT_OP_IN(OP_ANYCHAR_STAR_PEEK_NEXT);
- while (s < end) {
- if (*p == *s) {
- STACK_PUSH_ALT(p + 1, s, sprev);
- }
- n = enc_len(encode, s);
- DATA_ENSURE(n);
- if (ONIGENC_IS_MBC_NEWLINE(encode, s, end)) goto fail;
- sprev = s;
- s += n;
- }
- p++;
- STAT_OP_OUT;
- break;
-
- case OP_ANYCHAR_ML_STAR_PEEK_NEXT:STAT_OP_IN(OP_ANYCHAR_ML_STAR_PEEK_NEXT);
- while (s < end) {
- if (*p == *s) {
- STACK_PUSH_ALT(p + 1, s, sprev);
- }
- n = enc_len(encode, s);
- if (n >1) {
- DATA_ENSURE(n);
- sprev = s;
- s += n;
- }
- else {
- sprev = s;
- s++;
- }
- }
- p++;
- STAT_OP_OUT;
- break;
-
- case OP_WORD: STAT_OP_IN(OP_WORD);
- DATA_ENSURE(1);
- if (! ONIGENC_IS_MBC_WORD(encode, s, end))
- goto fail;
-
- s += enc_len(encode, s);
- STAT_OP_OUT;
- break;
-
- case OP_NOT_WORD: STAT_OP_IN(OP_NOT_WORD);
- DATA_ENSURE(1);
- if (ONIGENC_IS_MBC_WORD(encode, s, end))
- goto fail;
-
- s += enc_len(encode, s);
- STAT_OP_OUT;
- break;
-
- case OP_WORD_BOUND: STAT_OP_IN(OP_WORD_BOUND);
- if (ON_STR_BEGIN(s)) {
- DATA_ENSURE(1);
- if (! ONIGENC_IS_MBC_WORD(encode, s, end))
- goto fail;
- }
- else if (ON_STR_END(s)) {
- if (! ONIGENC_IS_MBC_WORD(encode, sprev, end))
- goto fail;
- }
- else {
- if (ONIGENC_IS_MBC_WORD(encode, s, end)
- == ONIGENC_IS_MBC_WORD(encode, sprev, end))
- goto fail;
- }
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_NOT_WORD_BOUND: STAT_OP_IN(OP_NOT_WORD_BOUND);
- if (ON_STR_BEGIN(s)) {
- if (DATA_ENSURE_CHECK(1) && ONIGENC_IS_MBC_WORD(encode, s, end))
- goto fail;
- }
- else if (ON_STR_END(s)) {
- if (ONIGENC_IS_MBC_WORD(encode, sprev, end))
- goto fail;
- }
- else {
- if (ONIGENC_IS_MBC_WORD(encode, s, end)
- != ONIGENC_IS_MBC_WORD(encode, sprev, end))
- goto fail;
- }
- STAT_OP_OUT;
- continue;
- break;
-
-#ifdef USE_WORD_BEGIN_END
- case OP_WORD_BEGIN: STAT_OP_IN(OP_WORD_BEGIN);
- if (DATA_ENSURE_CHECK(1) && ONIGENC_IS_MBC_WORD(encode, s, end)) {
- if (ON_STR_BEGIN(s) || !ONIGENC_IS_MBC_WORD(encode, sprev, end)) {
- STAT_OP_OUT;
- continue;
- }
- }
- goto fail;
- break;
-
- case OP_WORD_END: STAT_OP_IN(OP_WORD_END);
- if (!ON_STR_BEGIN(s) && ONIGENC_IS_MBC_WORD(encode, sprev, end)) {
- if (ON_STR_END(s) || !ONIGENC_IS_MBC_WORD(encode, s, end)) {
- STAT_OP_OUT;
- continue;
- }
- }
- goto fail;
- break;
-#endif
-
- case OP_BEGIN_BUF: STAT_OP_IN(OP_BEGIN_BUF);
- if (! ON_STR_BEGIN(s)) goto fail;
-
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_END_BUF: STAT_OP_IN(OP_END_BUF);
- if (! ON_STR_END(s)) goto fail;
-
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_BEGIN_LINE: STAT_OP_IN(OP_BEGIN_LINE);
- if (ON_STR_BEGIN(s)) {
- if (IS_NOTBOL(msa->options)) goto fail;
- STAT_OP_OUT;
- continue;
- }
- else if (ONIGENC_IS_MBC_NEWLINE(encode, sprev, end) && !ON_STR_END(s)) {
- STAT_OP_OUT;
- continue;
- }
- goto fail;
- break;
-
- case OP_END_LINE: STAT_OP_IN(OP_END_LINE);
- if (ON_STR_END(s)) {
-#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
- if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE(encode, sprev, end)) {
-#endif
- if (IS_NOTEOL(msa->options)) goto fail;
- STAT_OP_OUT;
- continue;
-#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
- }
-#endif
- }
- else if (ONIGENC_IS_MBC_NEWLINE(encode, s, end)) {
- STAT_OP_OUT;
- continue;
- }
- goto fail;
- break;
-
- case OP_SEMI_END_BUF: STAT_OP_IN(OP_SEMI_END_BUF);
- if (ON_STR_END(s)) {
-#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
- if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE(encode, sprev, end)) {
-#endif
- if (IS_NOTEOL(msa->options)) goto fail; /* Is it needed? */
- STAT_OP_OUT;
- continue;
-#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
- }
-#endif
- }
- else if (ONIGENC_IS_MBC_NEWLINE(encode, s, end) &&
- ON_STR_END(s + enc_len(encode, s))) {
- STAT_OP_OUT;
- continue;
- }
- goto fail;
- break;
-
- case OP_BEGIN_POSITION: STAT_OP_IN(OP_BEGIN_POSITION);
- if (s != msa->start)
- goto fail;
-
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_MEMORY_START_PUSH: STAT_OP_IN(OP_MEMORY_START_PUSH);
- GET_MEMNUM_INC(mem, p);
- STACK_PUSH_MEM_START(mem, s);
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_MEMORY_START: STAT_OP_IN(OP_MEMORY_START);
- GET_MEMNUM_INC(mem, p);
- mem_start_stk[mem] = (StackIndex )((void* )s);
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_MEMORY_END_PUSH: STAT_OP_IN(OP_MEMORY_END_PUSH);
- GET_MEMNUM_INC(mem, p);
- STACK_PUSH_MEM_END(mem, s);
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_MEMORY_END: STAT_OP_IN(OP_MEMORY_END);
- GET_MEMNUM_INC(mem, p);
- mem_end_stk[mem] = (StackIndex )((void* )s);
- STAT_OP_OUT;
- continue;
- break;
-
-#ifdef USE_SUBEXP_CALL
- case OP_MEMORY_END_PUSH_REC: STAT_OP_IN(OP_MEMORY_END_PUSH_REC);
- GET_MEMNUM_INC(mem, p);
- STACK_GET_MEM_START(mem, stkp); /* should be before push mem-end. */
- STACK_PUSH_MEM_END(mem, s);
- mem_start_stk[mem] = GET_STACK_INDEX(stkp);
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_MEMORY_END_REC: STAT_OP_IN(OP_MEMORY_END_REC);
- GET_MEMNUM_INC(mem, p);
- mem_end_stk[mem] = (StackIndex )((void* )s);
- STACK_GET_MEM_START(mem, stkp);
-
- if (BIT_STATUS_AT(reg->bt_mem_start, mem))
- mem_start_stk[mem] = GET_STACK_INDEX(stkp);
- else
- mem_start_stk[mem] = (StackIndex )((void* )stkp->u.mem.pstr);
-
- STACK_PUSH_MEM_END_MARK(mem);
- STAT_OP_OUT;
- continue;
- break;
-#endif
-
- case OP_BACKREF1: STAT_OP_IN(OP_BACKREF1);
- mem = 1;
- goto backref;
- break;
-
- case OP_BACKREF2: STAT_OP_IN(OP_BACKREF2);
- mem = 2;
- goto backref;
- break;
-
- case OP_BACKREF3: STAT_OP_IN(OP_BACKREF3);
- mem = 3;
- goto backref;
- break;
-
- case OP_BACKREFN: STAT_OP_IN(OP_BACKREFN);
- GET_MEMNUM_INC(mem, p);
- backref:
- {
- int len;
- UChar *pstart, *pend;
-
- /* if you want to remove following line,
- you should check in parse and compile time. */
- if (mem > num_mem) goto fail;
- if (mem_end_stk[mem] == INVALID_STACK_INDEX) goto fail;
- if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;
-
- if (BIT_STATUS_AT(reg->bt_mem_start, mem))
- pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
- else
- pstart = (UChar* )((void* )mem_start_stk[mem]);
-
- pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
- ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
- : (UChar* )((void* )mem_end_stk[mem]));
- n = pend - pstart;
- DATA_ENSURE(n);
- sprev = s;
- STRING_CMP(pstart, s, n);
- while (sprev + (len = enc_len(encode, sprev)) < s)
- sprev += len;
-
- STAT_OP_OUT;
- continue;
- }
- break;
-
- case OP_BACKREFN_IC: STAT_OP_IN(OP_BACKREFN_IC);
- GET_MEMNUM_INC(mem, p);
- {
- int len;
- UChar *pstart, *pend;
-
- /* if you want to remove following line,
- you should check in parse and compile time. */
- if (mem > num_mem) goto fail;
- if (mem_end_stk[mem] == INVALID_STACK_INDEX) goto fail;
- if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;
-
- if (BIT_STATUS_AT(reg->bt_mem_start, mem))
- pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
- else
- pstart = (UChar* )((void* )mem_start_stk[mem]);
-
- pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
- ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
- : (UChar* )((void* )mem_end_stk[mem]));
- n = pend - pstart;
- DATA_ENSURE(n);
- sprev = s;
- STRING_CMP_IC(ambig_flag, pstart, &s, n);
- while (sprev + (len = enc_len(encode, sprev)) < s)
- sprev += len;
-
- STAT_OP_OUT;
- continue;
- }
- break;
-
- case OP_BACKREF_MULTI: STAT_OP_IN(OP_BACKREF_MULTI);
- {
- int len, is_fail;
- UChar *pstart, *pend, *swork;
-
- GET_LENGTH_INC(tlen, p);
- for (i = 0; i < tlen; i++) {
- GET_MEMNUM_INC(mem, p);
-
- if (mem_end_stk[mem] == INVALID_STACK_INDEX) continue;
- if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;
-
- if (BIT_STATUS_AT(reg->bt_mem_start, mem))
- pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
- else
- pstart = (UChar* )((void* )mem_start_stk[mem]);
-
- pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
- ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
- : (UChar* )((void* )mem_end_stk[mem]));
- n = pend - pstart;
- DATA_ENSURE(n);
- sprev = s;
- swork = s;
- STRING_CMP_VALUE(pstart, swork, n, is_fail);
- if (is_fail) continue;
- s = swork;
- while (sprev + (len = enc_len(encode, sprev)) < s)
- sprev += len;
-
- p += (SIZE_MEMNUM * (tlen - i - 1));
- break; /* success */
- }
- if (i == tlen) goto fail;
- STAT_OP_OUT;
- continue;
- }
- break;
-
- case OP_BACKREF_MULTI_IC: STAT_OP_IN(OP_BACKREF_MULTI_IC);
- {
- int len, is_fail;
- UChar *pstart, *pend, *swork;
-
- GET_LENGTH_INC(tlen, p);
- for (i = 0; i < tlen; i++) {
- GET_MEMNUM_INC(mem, p);
-
- if (mem_end_stk[mem] == INVALID_STACK_INDEX) continue;
- if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;
-
- if (BIT_STATUS_AT(reg->bt_mem_start, mem))
- pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
- else
- pstart = (UChar* )((void* )mem_start_stk[mem]);
-
- pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
- ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
- : (UChar* )((void* )mem_end_stk[mem]));
- n = pend - pstart;
- DATA_ENSURE(n);
- sprev = s;
- swork = s;
- STRING_CMP_VALUE_IC(ambig_flag, pstart, &swork, n, is_fail);
- if (is_fail) continue;
- s = swork;
- while (sprev + (len = enc_len(encode, sprev)) < s)
- sprev += len;
-
- p += (SIZE_MEMNUM * (tlen - i - 1));
- break; /* success */
- }
- if (i == tlen) goto fail;
- STAT_OP_OUT;
- continue;
- }
- break;
-
- case OP_SET_OPTION_PUSH: STAT_OP_IN(OP_SET_OPTION_PUSH);
- GET_OPTION_INC(option, p);
- STACK_PUSH_ALT(p, s, sprev);
- p += SIZE_OP_SET_OPTION + SIZE_OP_FAIL;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_SET_OPTION: STAT_OP_IN(OP_SET_OPTION);
- GET_OPTION_INC(option, p);
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_NULL_CHECK_START: STAT_OP_IN(OP_NULL_CHECK_START);
- GET_MEMNUM_INC(mem, p); /* mem: null check id */
- STACK_PUSH_NULL_CHECK_START(mem, s);
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_NULL_CHECK_END: STAT_OP_IN(OP_NULL_CHECK_END);
- {
- int isnull;
-
- GET_MEMNUM_INC(mem, p); /* mem: null check id */
- STACK_NULL_CHECK(isnull, mem, s);
- if (isnull) {
-#ifdef ONIG_DEBUG_MATCH
- fprintf(stderr, "NULL_CHECK_END: skip id:%d, s:%d\n",
- (int )mem, (int )s);
-#endif
- null_check_found:
- /* empty loop founded, skip next instruction */
- switch (*p++) {
- case OP_JUMP:
- case OP_PUSH:
- p += SIZE_RELADDR;
- break;
- case OP_REPEAT_INC:
- case OP_REPEAT_INC_NG:
- case OP_REPEAT_INC_SG:
- case OP_REPEAT_INC_NG_SG:
- p += SIZE_MEMNUM;
- break;
- default:
- goto unexpected_bytecode_error;
- break;
- }
- }
- }
- STAT_OP_OUT;
- continue;
- break;
-
-#ifdef USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
- case OP_NULL_CHECK_END_MEMST: STAT_OP_IN(OP_NULL_CHECK_END_MEMST);
- {
- int isnull;
-
- GET_MEMNUM_INC(mem, p); /* mem: null check id */
- STACK_NULL_CHECK_MEMST(isnull, mem, s, reg);
- if (isnull) {
-#ifdef ONIG_DEBUG_MATCH
- fprintf(stderr, "NULL_CHECK_END_MEMST: skip id:%d, s:%d\n",
- (int )mem, (int )s);
-#endif
- if (isnull == -1) goto fail;
- goto null_check_found;
- }
- }
- STAT_OP_OUT;
- continue;
- break;
-#endif
-
-#ifdef USE_SUBEXP_CALL
- case OP_NULL_CHECK_END_MEMST_PUSH:
- STAT_OP_IN(OP_NULL_CHECK_END_MEMST_PUSH);
- {
- int isnull;
-
- GET_MEMNUM_INC(mem, p); /* mem: null check id */
-#ifdef USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
- STACK_NULL_CHECK_MEMST_REC(isnull, mem, s, reg);
-#else
- STACK_NULL_CHECK_REC(isnull, mem, s);
-#endif
- if (isnull) {
-#ifdef ONIG_DEBUG_MATCH
- fprintf(stderr, "NULL_CHECK_END_MEMST_PUSH: skip id:%d, s:%d\n",
- (int )mem, (int )s);
-#endif
- if (isnull == -1) goto fail;
- goto null_check_found;
- }
- else {
- STACK_PUSH_NULL_CHECK_END(mem);
- }
- }
- STAT_OP_OUT;
- continue;
- break;
-#endif
-
- case OP_JUMP: STAT_OP_IN(OP_JUMP);
- GET_RELADDR_INC(addr, p);
- p += addr;
- STAT_OP_OUT;
- CHECK_INTERRUPT_IN_MATCH_AT;
- continue;
- break;
-
- case OP_PUSH: STAT_OP_IN(OP_PUSH);
- GET_RELADDR_INC(addr, p);
- STACK_PUSH_ALT(p + addr, s, sprev);
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_POP: STAT_OP_IN(OP_POP);
- STACK_POP_ONE;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_PUSH_OR_JUMP_EXACT1: STAT_OP_IN(OP_PUSH_OR_JUMP_EXACT1);
- GET_RELADDR_INC(addr, p);
- if (*p == *s && DATA_ENSURE_CHECK(1)) {
- p++;
- STACK_PUSH_ALT(p + addr, s, sprev);
- STAT_OP_OUT;
- continue;
- }
- p += (addr + 1);
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_PUSH_IF_PEEK_NEXT: STAT_OP_IN(OP_PUSH_IF_PEEK_NEXT);
- GET_RELADDR_INC(addr, p);
- if (*p == *s) {
- p++;
- STACK_PUSH_ALT(p + addr, s, sprev);
- STAT_OP_OUT;
- continue;
- }
- p++;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_REPEAT: STAT_OP_IN(OP_REPEAT);
- {
- GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
- GET_RELADDR_INC(addr, p);
-
- STACK_ENSURE(1);
- repeat_stk[mem] = GET_STACK_INDEX(stk);
- STACK_PUSH_REPEAT(mem, p);
-
- if (reg->repeat_range[mem].lower == 0) {
- STACK_PUSH_ALT(p + addr, s, sprev);
- }
- }
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_REPEAT_NG: STAT_OP_IN(OP_REPEAT_NG);
- {
- GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
- GET_RELADDR_INC(addr, p);
-
- STACK_ENSURE(1);
- repeat_stk[mem] = GET_STACK_INDEX(stk);
- STACK_PUSH_REPEAT(mem, p);
-
- if (reg->repeat_range[mem].lower == 0) {
- STACK_PUSH_ALT(p, s, sprev);
- p += addr;
- }
- }
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_REPEAT_INC: STAT_OP_IN(OP_REPEAT_INC);
- GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
- si = repeat_stk[mem];
- stkp = STACK_AT(si);
-
- repeat_inc:
- stkp->u.repeat.count++;
- if (stkp->u.repeat.count == reg->repeat_range[mem].upper) {
- /* end of repeat. Nothing to do. */
- }
- else if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
- STACK_PUSH_ALT(p, s, sprev);
- p = STACK_AT(si)->u.repeat.pcode; /* Don't use stkp after PUSH. */
- }
- else {
- p = stkp->u.repeat.pcode;
- }
- STACK_PUSH_REPEAT_INC(si);
- STAT_OP_OUT;
- CHECK_INTERRUPT_IN_MATCH_AT;
- continue;
- break;
-
- case OP_REPEAT_INC_SG: STAT_OP_IN(OP_REPEAT_INC_SG);
- GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
- STACK_GET_REPEAT(mem, stkp);
- si = GET_STACK_INDEX(stkp);
- goto repeat_inc;
- break;
-
- case OP_REPEAT_INC_NG: STAT_OP_IN(OP_REPEAT_INC_NG);
- GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
- si = repeat_stk[mem];
- stkp = STACK_AT(si);
-
- repeat_inc_ng:
- stkp->u.repeat.count++;
- if (stkp->u.repeat.count < reg->repeat_range[mem].upper ||
- IS_REPEAT_INFINITE(reg->repeat_range[mem].upper)) {
- if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
- UChar* pcode = stkp->u.repeat.pcode;
-
- STACK_PUSH_REPEAT_INC(si);
- STACK_PUSH_ALT(pcode, s, sprev);
- }
- else {
- p = stkp->u.repeat.pcode;
- STACK_PUSH_REPEAT_INC(si);
- }
- }
- else if (stkp->u.repeat.count == reg->repeat_range[mem].upper) {
- STACK_PUSH_REPEAT_INC(si);
- }
- STAT_OP_OUT;
- CHECK_INTERRUPT_IN_MATCH_AT;
- continue;
- break;
-
- case OP_REPEAT_INC_NG_SG: STAT_OP_IN(OP_REPEAT_INC_NG_SG);
- GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
- STACK_GET_REPEAT(mem, stkp);
- si = GET_STACK_INDEX(stkp);
- goto repeat_inc_ng;
- break;
-
- case OP_PUSH_POS: STAT_OP_IN(OP_PUSH_POS);
- STACK_PUSH_POS(s, sprev);
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_POP_POS: STAT_OP_IN(OP_POP_POS);
- {
- STACK_POS_END(stkp);
- s = stkp->u.state.pstr;
- sprev = stkp->u.state.pstr_prev;
- }
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_PUSH_POS_NOT: STAT_OP_IN(OP_PUSH_POS_NOT);
- GET_RELADDR_INC(addr, p);
- STACK_PUSH_POS_NOT(p + addr, s, sprev);
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_FAIL_POS: STAT_OP_IN(OP_FAIL_POS);
- STACK_POP_TIL_POS_NOT;
- goto fail;
- break;
-
- case OP_PUSH_STOP_BT: STAT_OP_IN(OP_PUSH_STOP_BT);
- STACK_PUSH_STOP_BT;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_POP_STOP_BT: STAT_OP_IN(OP_POP_STOP_BT);
- STACK_STOP_BT_END;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_LOOK_BEHIND: STAT_OP_IN(OP_LOOK_BEHIND);
- GET_LENGTH_INC(tlen, p);
- s = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen);
- if (IS_NULL(s)) goto fail;
- sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_PUSH_LOOK_BEHIND_NOT: STAT_OP_IN(OP_PUSH_LOOK_BEHIND_NOT);
- GET_RELADDR_INC(addr, p);
- GET_LENGTH_INC(tlen, p);
- q = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen);
- if (IS_NULL(q)) {
- /* too short case -> success. ex. /(?<!XXX)a/.match("a")
- If you want to change to fail, replace following line. */
- p += addr;
- /* goto fail; */
- }
- else {
- STACK_PUSH_LOOK_BEHIND_NOT(p + addr, s, sprev);
- s = q;
- sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);
- }
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_FAIL_LOOK_BEHIND_NOT: STAT_OP_IN(OP_FAIL_LOOK_BEHIND_NOT);
- STACK_POP_TIL_LOOK_BEHIND_NOT;
- goto fail;
- break;
-
-#ifdef USE_SUBEXP_CALL
- case OP_CALL: STAT_OP_IN(OP_CALL);
- GET_ABSADDR_INC(addr, p);
- STACK_PUSH_CALL_FRAME(p);
- p = reg->p + addr;
- STAT_OP_OUT;
- continue;
- break;
-
- case OP_RETURN: STAT_OP_IN(OP_RETURN);
- STACK_RETURN(p);
- STACK_PUSH_RETURN;
- STAT_OP_OUT;
- continue;
- break;
-#endif
-
- case OP_FINISH:
- goto finish;
- break;
-
- fail:
- STAT_OP_OUT;
- /* fall */
- case OP_FAIL: STAT_OP_IN(OP_FAIL);
- STACK_POP;
- p = stk->u.state.pcode;
- s = stk->u.state.pstr;
- sprev = stk->u.state.pstr_prev;
- STAT_OP_OUT;
- continue;
- break;
-
- default:
- goto bytecode_error;
-
- } /* end of switch */
- sprev = sbegin;
- } /* end of while(1) */
-
- finish:
- STACK_SAVE;
- return best_len;
-
-#ifdef ONIG_DEBUG
- stack_error:
- STACK_SAVE;
- return ONIGERR_STACK_BUG;
-#endif
-
- bytecode_error:
- STACK_SAVE;
- return ONIGERR_UNDEFINED_BYTECODE;
-
- unexpected_bytecode_error:
- STACK_SAVE;
- return ONIGERR_UNEXPECTED_BYTECODE;
-}
-
-
-static UChar*
-slow_search(OnigEncoding enc, UChar* target, UChar* target_end,
- const UChar* text, const UChar* text_end, UChar* text_range)
-{
- UChar *t, *p, *s, *end;
-
- end = (UChar* )text_end;
- end -= target_end - target - 1;
- if (end > text_range)
- end = text_range;
-
- s = (UChar* )text;
-
- while (s < end) {
- if (*s == *target) {
- p = s + 1;
- t = target + 1;
- while (t < target_end) {
- if (*t != *p++)
- break;
- t++;
- }
- if (t == target_end)
- return s;
- }
- s += enc_len(enc, s);
- }
-
- return (UChar* )NULL;
-}
-
-static int
-str_lower_case_match(OnigEncoding enc, int ambig_flag,
- const UChar* t, const UChar* tend,
- const UChar* p, const UChar* end)
-{
- int lowlen;
- UChar *q, lowbuf[ONIGENC_MBC_NORMALIZE_MAXLEN];
- const UChar* tsave;
- const UChar* psave;
-
- tsave = t;
- psave = p;
-
- retry:
- while (t < tend) {
- lowlen = ONIGENC_MBC_TO_NORMALIZE(enc, ambig_flag, &p, end, lowbuf);
- q = lowbuf;
- while (lowlen > 0) {
- if (*t++ != *q++) {
- if ((ambig_flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) {
- ambig_flag &= ~ONIGENC_AMBIGUOUS_MATCH_COMPOUND;
- t = tsave;
- p = psave;
- goto retry;
- }
- else
- return 0;
- }
- lowlen--;
- }
- }
-
- return 1;
-}
-
-static UChar*
-slow_search_ic(OnigEncoding enc, int ambig_flag,
- UChar* target, UChar* target_end,
- const UChar* text, const UChar* text_end, UChar* text_range)
-{
- UChar *s, *end;
-
- end = (UChar* )text_end;
- end -= target_end - target - 1;
- if (end > text_range)
- end = text_range;
-
- s = (UChar* )text;
-
- while (s < end) {
- if (str_lower_case_match(enc, ambig_flag, target, target_end, s, text_end))
- return s;
-
- s += enc_len(enc, s);
- }
-
- return (UChar* )NULL;
-}
-
-static UChar*
-slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,
- const UChar* text, const UChar* adjust_text,
- const UChar* text_end, const UChar* text_start)
-{
- UChar *t, *p, *s;
-
- s = (UChar* )text_end;
- s -= (target_end - target);
- if (s > text_start)
- s = (UChar* )text_start;
- else
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s);
-
- while (s >= text) {
- if (*s == *target) {
- p = s + 1;
- t = target + 1;
- while (t < target_end) {
- if (*t != *p++)
- break;
- t++;
- }
- if (t == target_end)
- return s;
- }
- s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s);
- }
-
- return (UChar* )NULL;
-}
-
-static UChar*
-slow_search_backward_ic(OnigEncoding enc, int ambig_flag,
- UChar* target, UChar* target_end,
- const UChar* text, const UChar* adjust_text,
- const UChar* text_end, const UChar* text_start)
-{
- UChar *s;
-
- s = (UChar* )text_end;
- s -= (target_end - target);
- if (s > text_start)
- s = (UChar* )text_start;
- else
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s);
-
- while (s >= text) {
- if (str_lower_case_match(enc, ambig_flag,
- target, target_end, s, text_end))
- return s;
-
- s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s);
- }
-
- return (UChar* )NULL;
-}
-
-static UChar*
-bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,
- const UChar* text, const UChar* text_end,
- const UChar* text_range)
-{
- const UChar *s, *t, *p, *end;
- const UChar *tail;
- int skip;
-
-#ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr, "bm_search_notrev: text: %d, text_end: %d, text_range: %d\n",
- (int )text, (int )text_end, (int )text_range);
-#endif
-
- end = text_range + (target_end - target) - 1;
- if (end > text_end)
- end = text_end;
-
- tail = target_end - 1;
- s = text;
- while ((s - text) < target_end - target) {
- s += enc_len(reg->enc, s);
- }
- s--; /* set to text check tail position. */
-
- if (IS_NULL(reg->int_map)) {
- while (s < end) {
- p = s;
- t = tail;
- while (t >= target && *p == *t) {
- p--; t--;
- }
- if (t < target) return (UChar* )(p + 1);
-
- skip = reg->map[*s];
- p = s + 1;
- if (p >= text_end) return (UChar* )NULL;
- t = p;
- do {
- p += enc_len(reg->enc, p);
- } while ((p - t) < skip && p < text_end);
-
- s += (p - t);
- }
- }
- else {
- while (s < end) {
- p = s;
- t = tail;
- while (t >= target && *p == *t) {
- p--; t--;
- }
- if (t < target) return (UChar* )(p + 1);
-
- skip = reg->int_map[*s];
- p = s + 1;
- if (p >= text_end) return (UChar* )NULL;
- t = p;
- do {
- p += enc_len(reg->enc, p);
- } while ((p - t) < skip && p < text_end);
-
- s += (p - t);
- }
- }
- return (UChar* )NULL;
-}
-
-static UChar*
-bm_search(regex_t* reg, const UChar* target, const UChar* target_end,
- const UChar* text, const UChar* text_end, const UChar* text_range)
-{
- const UChar *s, *t, *p, *end;
- const UChar *tail;
-
- end = text_range + (target_end - target) - 1;
- if (end > text_end)
- end = text_end;
-
- tail = target_end - 1;
- s = text + (target_end - target) - 1;
- if (IS_NULL(reg->int_map)) {
- while (s < end) {
- p = s;
- t = tail;
- while (t >= target && *p == *t) {
- p--; t--;
- }
- if (t < target) return (UChar* )(p + 1);
- s += reg->map[*s];
- }
- }
- else { /* see int_map[] */
- while (s < end) {
- p = s;
- t = tail;
- while (t >= target && *p == *t) {
- p--; t--;
- }
- if (t < target) return (UChar* )(p + 1);
- s += reg->int_map[*s];
- }
- }
- return (UChar* )NULL;
-}
-
-static int
-set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc, int** skip)
-
-{
- int i, len;
-
- if (IS_NULL(*skip)) {
- *skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE);
- if (IS_NULL(*skip)) return ONIGERR_MEMORY;
- }
-
- len = end - s;
- for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
- (*skip)[i] = len;
-
- for (i = len - 1; i > 0; i--)
- (*skip)[s[i]] = i;
-
- return 0;
-}
-
-static UChar*
-bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end,
- const UChar* text, const UChar* adjust_text,
- const UChar* text_end, const UChar* text_start)
-{
- const UChar *s, *t, *p;
-
- s = text_end - (target_end - target);
- if (text_start < s)
- s = text_start;
- else
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s);
-
- while (s >= text) {
- p = s;
- t = target;
- while (t < target_end && *p == *t) {
- p++; t++;
- }
- if (t == target_end)
- return (UChar* )s;
-
- s -= reg->int_map_backward[*s];
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s);
- }
-
- return (UChar* )NULL;
-}
-
-static UChar*
-map_search(OnigEncoding enc, UChar map[],
- const UChar* text, const UChar* text_range)
-{
- const UChar *s = text;
-
- while (s < text_range) {
- if (map[*s]) return (UChar* )s;
-
- s += enc_len(enc, s);
- }
- return (UChar* )NULL;
-}
-
-static UChar*
-map_search_backward(OnigEncoding enc, UChar map[],
- const UChar* text, const UChar* adjust_text,
- const UChar* text_start)
-{
- const UChar *s = text_start;
-
- while (s >= text) {
- if (map[*s]) return (UChar* )s;
-
- s = onigenc_get_prev_char_head(enc, adjust_text, s);
- }
- return (UChar* )NULL;
-}
-
-extern int
-onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, OnigRegion* region,
- OnigOptionType option)
-{
- int r;
- UChar *prev;
- MatchArg msa;
-
-#ifdef USE_MULTI_THREAD_SYSTEM
- if (ONIG_STATE(reg) >= ONIG_STATE_NORMAL) {
- ONIG_STATE_INC(reg);
- if (IS_NOT_NULL(reg->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) {
- onig_chain_reduce(reg);
- ONIG_STATE_INC(reg);
- }
- }
- else {
- int n = 0;
- while (ONIG_STATE(reg) < ONIG_STATE_NORMAL) {
- if (++n > THREAD_PASS_LIMIT_COUNT)
- return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT;
- THREAD_PASS;
- }
- ONIG_STATE_INC(reg);
- }
-#endif /* USE_MULTI_THREAD_SYSTEM */
-
- MATCH_ARG_INIT(msa, option, region, at);
-
- if (region
-#ifdef USE_POSIX_REGION_OPTION
- && !IS_POSIX_REGION(option)
-#endif
- ) {
- r = onig_region_resize_clear(region, reg->num_mem + 1);
- }
- else
- r = 0;
-
- if (r == 0) {
- prev = (UChar* )onigenc_get_prev_char_head(reg->enc, str, at);
- r = match_at(reg, str, end, at, prev, &msa);
- }
-
- MATCH_ARG_FREE(msa);
- ONIG_STATE_DEC(reg);
- return r;
-}
-
-static int
-forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
- UChar* range, UChar** low, UChar** high, UChar** low_prev)
-{
- UChar *p, *pprev = (UChar* )NULL;
-
-#ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr, "forward_search_range: str: %d, end: %d, s: %d, range: %d\n",
- (int )str, (int )end, (int )s, (int )range);
-#endif
-
- p = s;
- if (reg->dmin > 0) {
- if (ONIGENC_IS_SINGLEBYTE(reg->enc)) {
- p += reg->dmin;
- }
- else {
- UChar *q = p + reg->dmin;
- while (p < q) p += enc_len(reg->enc, p);
- }
- }
-
- retry:
- switch (reg->optimize) {
- case ONIG_OPTIMIZE_EXACT:
- p = slow_search(reg->enc, reg->exact, reg->exact_end, p, end, range);
- break;
- case ONIG_OPTIMIZE_EXACT_IC:
- p = slow_search_ic(reg->enc, reg->ambig_flag,
- reg->exact, reg->exact_end, p, end, range);
- break;
-
- case ONIG_OPTIMIZE_EXACT_BM:
- p = bm_search(reg, reg->exact, reg->exact_end, p, end, range);
- break;
-
- case ONIG_OPTIMIZE_EXACT_BM_NOT_REV:
- p = bm_search_notrev(reg, reg->exact, reg->exact_end, p, end, range);
- break;
-
- case ONIG_OPTIMIZE_MAP:
- p = map_search(reg->enc, reg->map, p, range);
- break;
- }
-
- if (p && p < range) {
- if (p - reg->dmin < s) {
- retry_gate:
- pprev = p;
- p += enc_len(reg->enc, p);
- goto retry;
- }
-
- if (reg->sub_anchor) {
- UChar* prev;
-
- switch (reg->sub_anchor) {
- case ANCHOR_BEGIN_LINE:
- if (!ON_STR_BEGIN(p)) {
- prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), p);
- if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end))
- goto retry_gate;
- }
- break;
-
- case ANCHOR_END_LINE:
- if (ON_STR_END(p)) {
- prev = (UChar* )onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), p);
- if (prev && ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end))
- goto retry_gate;
- }
- else if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, p, end))
- goto retry_gate;
- break;
- }
- }
-
- if (reg->dmax == 0) {
- *low = p;
- if (low_prev) {
- if (*low > s)
- *low_prev = onigenc_get_prev_char_head(reg->enc, s, p);
- else
- *low_prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), p);
- }
- }
- else {
- if (reg->dmax != ONIG_INFINITE_DISTANCE) {
- *low = p - reg->dmax;
- if (*low > s) {
- *low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s,
- *low, (const UChar** )low_prev);
- if (low_prev && IS_NULL(*low_prev))
- *low_prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : s), *low);
- }
- else {
- if (low_prev)
- *low_prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), *low);
- }
- }
- }
- /* no needs to adjust *high, *high is used as range check only */
- *high = p - reg->dmin;
-
-#ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr,
- "forward_search_range success: low: %d, high: %d, dmin: %d, dmax: %d\n",
- (int )(*low - str), (int )(*high - str), reg->dmin, reg->dmax);
-#endif
- return 1; /* success */
- }
-
- return 0; /* fail */
-}
-
-static int set_bm_backward_skip P_((UChar* s, UChar* end, OnigEncoding enc,
- int** skip));
-
-#define BM_BACKWARD_SEARCH_LENGTH_THRESHOLD 100
-
-static int
-backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
- UChar* s, const UChar* range, UChar* adjrange,
- UChar** low, UChar** high)
-{
- int r;
- UChar *p;
-
- range += reg->dmin;
- p = s;
-
- retry:
- switch (reg->optimize) {
- case ONIG_OPTIMIZE_EXACT:
- exact_method:
- p = slow_search_backward(reg->enc, reg->exact, reg->exact_end,
- range, adjrange, end, p);
- break;
-
- case ONIG_OPTIMIZE_EXACT_IC:
- p = slow_search_backward_ic(reg->enc, reg->ambig_flag,
- reg->exact, reg->exact_end,
- range, adjrange, end, p);
- break;
-
- case ONIG_OPTIMIZE_EXACT_BM:
- case ONIG_OPTIMIZE_EXACT_BM_NOT_REV:
- if (IS_NULL(reg->int_map_backward)) {
- if (s - range < BM_BACKWARD_SEARCH_LENGTH_THRESHOLD)
- goto exact_method;
-
- r = set_bm_backward_skip(reg->exact, reg->exact_end, reg->enc,
- &(reg->int_map_backward));
- if (r) return r;
- }
- p = bm_search_backward(reg, reg->exact, reg->exact_end, range, adjrange,
- end, p);
- break;
-
- case ONIG_OPTIMIZE_MAP:
- p = map_search_backward(reg->enc, reg->map, range, adjrange, p);
- break;
- }
-
- if (p) {
- if (reg->sub_anchor) {
- UChar* prev;
-
- switch (reg->sub_anchor) {
- case ANCHOR_BEGIN_LINE:
- if (!ON_STR_BEGIN(p)) {
- prev = onigenc_get_prev_char_head(reg->enc, adjrange, p);
- if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) {
- p = prev;
- goto retry;
- }
- }
- break;
-
- case ANCHOR_END_LINE:
- if (ON_STR_END(p)) {
- prev = onigenc_get_prev_char_head(reg->enc, adjrange, p);
- if (IS_NULL(prev)) goto fail;
- if (ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) {
- p = prev;
- goto retry;
- }
- }
- else if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, p, end)) {
- p = onigenc_get_prev_char_head(reg->enc, adjrange, p);
- if (IS_NULL(p)) goto fail;
- goto retry;
- }
- break;
- }
- }
-
- /* no needs to adjust *high, *high is used as range check only */
- if (reg->dmax != ONIG_INFINITE_DISTANCE) {
- *low = p - reg->dmax;
- *high = p - reg->dmin;
- *high = onigenc_get_right_adjust_char_head(reg->enc, adjrange, *high);
- }
-
-#ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr, "backward_search_range: low: %d, high: %d\n",
- (int )(*low - str), (int )(*high - str));
-#endif
- return 1; /* success */
- }
-
- fail:
-#ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr, "backward_search_range: fail.\n");
-#endif
- return 0; /* fail */
-}
-
-
-extern int
-onig_search(regex_t* reg, const UChar* str, const UChar* end,
- const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option)
-{
- int r;
- UChar *s, *prev;
- MatchArg msa;
-
-#ifdef USE_MULTI_THREAD_SYSTEM
- if (ONIG_STATE(reg) >= ONIG_STATE_NORMAL) {
- ONIG_STATE_INC(reg);
- if (IS_NOT_NULL(reg->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) {
- onig_chain_reduce(reg);
- ONIG_STATE_INC(reg);
- }
- }
- else {
- int n = 0;
- while (ONIG_STATE(reg) < ONIG_STATE_NORMAL) {
- if (++n > THREAD_PASS_LIMIT_COUNT)
- return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT;
- THREAD_PASS;
- }
- ONIG_STATE_INC(reg);
- }
-#endif /* USE_MULTI_THREAD_SYSTEM */
-
-#ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr,
- "onig_search (entry point): str: %d, end: %d, start: %d, range: %d\n",
- (int )str, (int )(end - str), (int )(start - str), (int )(range - str));
-#endif
-
- if (region
-#ifdef USE_POSIX_REGION_OPTION
- && !IS_POSIX_REGION(option)
-#endif
- ) {
- r = onig_region_resize_clear(region, reg->num_mem + 1);
- if (r) goto finish_no_msa;
- }
-
- if (start > end || start < str) goto mismatch_no_msa;
-
-#define MATCH_AND_RETURN_CHECK \
- r = match_at(reg, str, end, s, prev, &msa);\
- if (r != ONIG_MISMATCH) {\
- if (r >= 0) goto match;\
- goto finish; /* error */ \
- }
-
- /* anchor optimize: resume search range */
- if (reg->anchor != 0 && str < end) {
- UChar* semi_end;
-
- if (reg->anchor & ANCHOR_BEGIN_POSITION) {
- /* search start-position only */
- begin_position:
- if (range > start)
- range = start + 1;
- else
- range = start;
- }
- else if (reg->anchor & ANCHOR_BEGIN_BUF) {
- /* search str-position only */
- if (range > start) {
- if (start != str) goto mismatch_no_msa;
- range = str + 1;
- }
- else {
- if (range <= str) {
- start = str;
- range = str;
- }
- else
- goto mismatch_no_msa;
- }
- }
- else if (reg->anchor & ANCHOR_END_BUF) {
- semi_end = (UChar* )end;
-
- end_buf:
- if ((OnigDistance )(semi_end - str) < reg->anchor_dmin)
- goto mismatch_no_msa;
-
- if (range > start) {
- if ((OnigDistance )(semi_end - start) > reg->anchor_dmax) {
- start = semi_end - reg->anchor_dmax;
- if (start < end)
- start = onigenc_get_right_adjust_char_head(reg->enc, str, start);
- else { /* match with empty at end */
- start = onigenc_get_prev_char_head(reg->enc, str, end);
- }
- }
- if ((OnigDistance )(semi_end - (range - 1)) < reg->anchor_dmin) {
- range = semi_end - reg->anchor_dmin + 1;
- }
-
- if (start >= range) goto mismatch_no_msa;
- }
- else {
- if ((OnigDistance )(semi_end - range) > reg->anchor_dmax) {
- range = semi_end - reg->anchor_dmax;
- }
- if ((OnigDistance )(semi_end - start) < reg->anchor_dmin) {
- start = semi_end - reg->anchor_dmin;
- start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start);
- if (range > start) goto mismatch_no_msa;
- }
- }
- }
- else if (reg->anchor & ANCHOR_SEMI_END_BUF) {
- UChar* pre_end = ONIGENC_STEP_BACK(reg->enc, str, end, 1);
-
- if (ONIGENC_IS_MBC_NEWLINE(reg->enc, pre_end, end)) {
- semi_end = pre_end;
- if (semi_end > str && start <= semi_end) {
- goto end_buf;
- }
- }
- else {
- semi_end = (UChar* )end;
- goto end_buf;
- }
- }
- else if ((reg->anchor & ANCHOR_ANYCHAR_STAR_PL)) {
- goto begin_position;
- }
- }
- else if (str == end) { /* empty string */
- static const UChar* address_for_empty_string = "";
-
-#ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr, "onig_search: empty string.\n");
-#endif
-
- if (reg->threshold_len == 0) {
- start = end = str = address_for_empty_string;
- s = (UChar* )start;
- prev = (UChar* )NULL;
-
- MATCH_ARG_INIT(msa, option, region, start);
- MATCH_AND_RETURN_CHECK;
- goto mismatch;
- }
- goto mismatch_no_msa;
- }
-
-#ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr, "onig_search(apply anchor): end: %d, start: %d, range: %d\n",
- (int )(end - str), (int )(start - str), (int )(range - str));
-#endif
-
- MATCH_ARG_INIT(msa, option, region, start);
-
- s = (UChar* )start;
- if (range > start) { /* forward search */
- if (s > str)
- prev = onigenc_get_prev_char_head(reg->enc, str, s);
- else
- prev = (UChar* )NULL;
-
- if (reg->optimize != ONIG_OPTIMIZE_NONE) {
- UChar *sch_range, *low, *high, *low_prev;
-
- sch_range = (UChar* )range;
- if (reg->dmax != 0) {
- if (reg->dmax == ONIG_INFINITE_DISTANCE)
- sch_range = (UChar* )end;
- else {
- sch_range += reg->dmax;
- if (sch_range > end) sch_range = (UChar* )end;
- }
- }
- if (reg->dmax != ONIG_INFINITE_DISTANCE &&
- (end - start) >= reg->threshold_len) {
- do {
- if (! forward_search_range(reg, str, end, s, sch_range,
- &low, &high, &low_prev)) goto mismatch;
- if (s < low) {
- s = low;
- prev = low_prev;
- }
- while (s <= high) {
- MATCH_AND_RETURN_CHECK;
- prev = s;
- s += enc_len(reg->enc, s);
- }
- if ((reg->anchor & ANCHOR_ANYCHAR_STAR) != 0) {
- if (IS_NOT_NULL(prev)) {
- while (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end) &&
- s < range) {
- prev = s;
- s += enc_len(reg->enc, s);
- }
- }
- }
- } while (s < range);
- goto mismatch;
- }
- else { /* check only. */
- if ((end - start) < reg->threshold_len ||
- ! forward_search_range(reg, str, end, s, sch_range,
- &low, &high, (UChar** )NULL)) goto mismatch;
- }
- }
-
- do {
- MATCH_AND_RETURN_CHECK;
- prev = s;
- s += enc_len(reg->enc, s);
- } while (s <= range); /* exec s == range, because empty match with /$/. */
- }
- else { /* backward search */
- if (reg->optimize != ONIG_OPTIMIZE_NONE) {
- UChar *low, *high, *adjrange, *sch_start;
-
- if (range < end)
- adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range);
- else
- adjrange = (UChar* )end;
-
- if (reg->dmax != ONIG_INFINITE_DISTANCE &&
- (end - range) >= reg->threshold_len) {
- do {
- sch_start = s + reg->dmax;
- if (sch_start > end) sch_start = (UChar* )end;
- if (backward_search_range(reg, str, end, sch_start, range, adjrange,
- &low, &high) <= 0)
- goto mismatch;
-
- if (s > high)
- s = high;
-
- while (s >= low) {
- prev = onigenc_get_prev_char_head(reg->enc, str, s);
- MATCH_AND_RETURN_CHECK;
- s = prev;
- }
- } while (s >= range);
- goto mismatch;
- }
- else { /* check only. */
- if ((end - range) < reg->threshold_len) goto mismatch;
-
- sch_start = s;
- if (reg->dmax != 0) {
- if (reg->dmax == ONIG_INFINITE_DISTANCE)
- sch_start = (UChar* )end;
- else {
- sch_start += reg->dmax;
- if (sch_start > end) sch_start = (UChar* )end;
- else
- sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc,
- start, sch_start);
- }
- }
- if (backward_search_range(reg, str, end, sch_start, range, adjrange,
- &low, &high) <= 0) goto mismatch;
- }
- }
-
- do {
- prev = onigenc_get_prev_char_head(reg->enc, str, s);
- MATCH_AND_RETURN_CHECK;
- s = prev;
- } while (s >= range);
- }
-
- mismatch:
- r = ONIG_MISMATCH;
-
- finish:
- MATCH_ARG_FREE(msa);
- ONIG_STATE_DEC(reg);
-
- /* If result is mismatch and no FIND_NOT_EMPTY option,
- then the region is not setted in match_at(). */
- if (IS_FIND_NOT_EMPTY(reg->options) && region
-#ifdef USE_POSIX_REGION_OPTION
- && !IS_POSIX_REGION(option)
-#endif
- ) {
- onig_region_clear(region);
- }
-
-#ifdef ONIG_DEBUG
- if (r != ONIG_MISMATCH)
- fprintf(stderr, "onig_search: error %d\n", r);
-#endif
- return r;
-
- mismatch_no_msa:
- r = ONIG_MISMATCH;
- finish_no_msa:
- ONIG_STATE_DEC(reg);
-#ifdef ONIG_DEBUG
- if (r != ONIG_MISMATCH)
- fprintf(stderr, "onig_search: error %d\n", r);
-#endif
- return r;
-
- match:
- ONIG_STATE_DEC(reg);
- MATCH_ARG_FREE(msa);
- return s - str;
-}
-
-extern OnigEncoding
-onig_get_encoding(regex_t* reg)
-{
- return reg->enc;
-}
-
-extern OnigOptionType
-onig_get_options(regex_t* reg)
-{
- return reg->options;
-}
-
-extern OnigAmbigType
-onig_get_ambig_flag(regex_t* reg)
-{
- return reg->ambig_flag;
-}
-
-extern OnigSyntaxType*
-onig_get_syntax(regex_t* reg)
-{
- return reg->syntax;
-}
-
-extern int
-onig_number_of_captures(regex_t* reg)
-{
- return reg->num_mem;
-}
-
-extern int
-onig_number_of_capture_histories(regex_t* reg)
-{
-#ifdef USE_CAPTURE_HISTORY
- int i, n;
-
- n = 0;
- for (i = 0; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) {
- if (BIT_STATUS_AT(reg->capture_history, i) != 0)
- n++;
- }
- return n;
-#else
- return 0;
-#endif
-}
-
-extern void
-onig_copy_encoding(OnigEncoding to, OnigEncoding from)
-{
- *to = *from;
-}
-
-/**********************************************************************
- regparse.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 "regparse.h"
-
-#define WARN_BUFSIZE 256
-
-OnigSyntaxType OnigSyntaxRuby = {
- (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY |
- ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 |
- ONIG_SYN_OP_ESC_X_BRACE_HEX8 | ONIG_SYN_OP_ESC_CONTROL_CHARS |
- ONIG_SYN_OP_ESC_C_CONTROL )
- & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END )
- , ( ONIG_SYN_OP2_QMARK_GROUP_EFFECT |
- ONIG_SYN_OP2_OPTION_RUBY |
- ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP | ONIG_SYN_OP2_ESC_K_NAMED_BACKREF |
- ONIG_SYN_OP2_ESC_G_SUBEXP_CALL |
- ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT |
- ONIG_SYN_OP2_CCLASS_SET_OP | ONIG_SYN_OP2_ESC_CAPITAL_C_BAR_CONTROL |
- ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META | ONIG_SYN_OP2_ESC_V_VTAB |
- ONIG_SYN_OP2_ESC_H_XDIGIT )
- , ( SYN_GNU_REGEX_BV |
- ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV |
- ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND |
- ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP |
- ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME |
- ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY |
- ONIG_SYN_WARN_CC_OP_NOT_ESCAPED |
- ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT )
- , ONIG_OPTION_NONE
-};
-
-OnigSyntaxType* OnigDefaultSyntax = ONIG_SYNTAX_RUBY;
-
-extern void onig_null_warn(const char* s, ...) { }
-
-#ifdef DEFAULT_WARN_FUNCTION
-static OnigWarnFunc onig_warn = (OnigWarnFunc )DEFAULT_WARN_FUNCTION;
-#else
-static OnigWarnFunc onig_warn = onig_null_warn;
-#endif
-
-#ifdef DEFAULT_VERB_WARN_FUNCTION
-static OnigWarnFunc onig_verb_warn = (OnigWarnFunc )DEFAULT_VERB_WARN_FUNCTION;
-#else
-static OnigWarnFunc onig_verb_warn = onig_null_warn;
-#endif
-
-extern void onig_set_warn_func(OnigWarnFunc f)
-{
- onig_warn = f;
-}
-
-extern void onig_set_verb_warn_func(OnigWarnFunc f)
-{
- onig_verb_warn = f;
-}
-
-static void
-bbuf_free(BBuf* bbuf)
-{
- if (IS_NOT_NULL(bbuf)) {
- if (IS_NOT_NULL(bbuf->p)) xfree(bbuf->p);
- xfree(bbuf);
- }
-}
-
-static int
-bbuf_clone(BBuf** rto, BBuf* from)
-{
- int r;
- BBuf *to;
-
- *rto = to = (BBuf* )xmalloc(sizeof(BBuf));
- CHECK_NULL_RETURN_VAL(to, ONIGERR_MEMORY);
- r = BBUF_INIT(to, from->alloc);
- if (r != 0) return r;
- to->used = from->used;
- xmemcpy(to->p, from->p, from->used);
- return 0;
-}
-
-#define ONOFF(v,f,negative) (negative) ? ((v) &= ~(f)) : ((v) |= (f))
-
-#define MBCODE_START_POS(enc) \
- (OnigCodePoint )(ONIGENC_MBC_MINLEN(enc) > 1 ? 0 : 0x80)
-
-#define SET_ALL_MULTI_BYTE_RANGE(enc, pbuf) \
- add_code_range_to_buf(pbuf, MBCODE_START_POS(enc), ~((OnigCodePoint )0))
-
-#define ADD_ALL_MULTI_BYTE_RANGE(enc, mbuf) do {\
- if (! ONIGENC_IS_SINGLEBYTE(enc)) {\
- r = SET_ALL_MULTI_BYTE_RANGE(enc, &(mbuf));\
- if (r) return r;\
- }\
-} while (0)
-
-
-#define BITSET_IS_EMPTY(bs,empty) do {\
- int i;\
- empty = 1;\
- for (i = 0; i < BITSET_SIZE; i++) {\
- if ((bs)[i] != 0) {\
- empty = 0; break;\
- }\
- }\
-} while (0)
-
-static void
-bitset_set_range(BitSetRef bs, int from, int to)
-{
- int i;
- for (i = from; i <= to && i < SINGLE_BYTE_SIZE; i++) {
- BITSET_SET_BIT(bs, i);
- }
-}
-
-#if 0
-static void
-bitset_set_all(BitSetRef bs)
-{
- int i;
- for (i = 0; i < BITSET_SIZE; i++) {
- bs[i] = ~((Bits )0);
- }
-}
-#endif
-
-static void
-bitset_invert(BitSetRef bs)
-{
- int i;
- for (i = 0; i < BITSET_SIZE; i++) {
- bs[i] = ~(bs[i]);
- }
-}
-
-static void
-bitset_invert_to(BitSetRef from, BitSetRef to)
-{
- int i;
- for (i = 0; i < BITSET_SIZE; i++) {
- to[i] = ~(from[i]);
- }
-}
-
-static void
-bitset_and(BitSetRef dest, BitSetRef bs)
-{
- int i;
- for (i = 0; i < BITSET_SIZE; i++) {
- dest[i] &= bs[i];
- }
-}
-
-static void
-bitset_or(BitSetRef dest, BitSetRef bs)
-{
- int i;
- for (i = 0; i < BITSET_SIZE; i++) {
- dest[i] |= bs[i];
- }
-}
-
-static void
-bitset_copy(BitSetRef dest, BitSetRef bs)
-{
- int i;
- for (i = 0; i < BITSET_SIZE; i++) {
- dest[i] = bs[i];
- }
-}
-
-extern int
-onig_strncmp(const UChar* s1, const UChar* s2, int n)
-{
- int x;
-
- while (n-- > 0) {
- x = *s2++ - *s1++;
- if (x) return x;
- }
- return 0;
-}
-
-static void
-k_strcpy(UChar* dest, const UChar* src, const UChar* end)
-{
- int len = end - src;
- if (len > 0) {
- xmemcpy(dest, src, len);
- dest[len] = (UChar )0;
- }
-}
-
-static UChar*
-strdup_with_null(OnigEncoding enc, UChar* s, UChar* end)
-{
- int slen, term_len, i;
- UChar *r;
-
- slen = end - s;
- term_len = ONIGENC_MBC_MINLEN(enc);
-
- r = (UChar* )xmalloc(slen + term_len);
- CHECK_NULL_RETURN(r);
- xmemcpy(r, s, slen);
-
- for (i = 0; i < term_len; i++)
- r[slen + i] = (UChar )0;
-
- return r;
-}
-
-
-/* scan pattern methods */
-#define PEND_VALUE 0
-
-#define PFETCH_READY UChar* pfetch_prev
-#define PEND (p < end ? 0 : 1)
-#define PUNFETCH p = pfetch_prev
-#define PINC do { \
- pfetch_prev = p; \
- p += ONIGENC_MBC_ENC_LEN(enc, p); \
-} while (0)
-#define PFETCH(c) do { \
- c = ONIGENC_MBC_TO_CODE(enc, p, end); \
- pfetch_prev = p; \
- p += ONIGENC_MBC_ENC_LEN(enc, p); \
-} while (0)
-
-#define PPEEK (p < end ? ONIGENC_MBC_TO_CODE(enc, p, end) : PEND_VALUE)
-#define PPEEK_IS(c) (PPEEK == (OnigCodePoint )c)
-
-static UChar*
-k_strcat_capa(UChar* dest, UChar* dest_end, const UChar* src, const UChar* src_end,
- int capa)
-{
- UChar* r;
-
- if (dest)
- r = (UChar* )xrealloc(dest, capa + 1);
- else
- r = (UChar* )xmalloc(capa + 1);
-
- CHECK_NULL_RETURN(r);
- k_strcpy(r + (dest_end - dest), src, src_end);
- return r;
-}
-
-/* dest on static area */
-static UChar*
-strcat_capa_from_static(UChar* dest, UChar* dest_end,
- const UChar* src, const UChar* src_end, int capa)
-{
- UChar* r;
-
- r = (UChar* )xmalloc(capa + 1);
- CHECK_NULL_RETURN(r);
- k_strcpy(r, dest, dest_end);
- k_strcpy(r + (dest_end - dest), src, src_end);
- return r;
-}
-
-#ifdef USE_NAMED_GROUP
-
-#define INIT_NAME_BACKREFS_ALLOC_NUM 8
-
-typedef struct {
- UChar* name;
- int name_len; /* byte length */
- int back_num; /* number of backrefs */
- int back_alloc;
- int back_ref1;
- int* back_refs;
-} NameEntry;
-
-#ifdef USE_ST_HASH_TABLE
-
-#include "st.h"
-
-typedef struct {
- unsigned char* s;
- unsigned char* end;
-} st_strend_key;
-
-static int strend_cmp(st_strend_key*, st_strend_key*);
-static int strend_hash(st_strend_key*);
-
-static struct st_hash_type type_strend_hash = {
- strend_cmp,
- strend_hash,
-};
-
-static st_table*
-onig_st_init_strend_table_with_size(int size)
-{
- return onig_st_init_table_with_size(&type_strend_hash, size);
-}
-
-static int
-onig_st_lookup_strend(st_table *table, const UChar* str_key, const UChar* end_key, st_data_t *value)
-{
- st_strend_key key;
-
- key.s = (unsigned char* )str_key;
- key.end = (unsigned char* )end_key;
-
- return onig_st_lookup(table, (st_data_t )(&key), value);
-}
-
-static int
-onig_st_insert_strend(st_table *table, const UChar* str_key, const UChar* end_key, st_data_t value)
-{
- st_strend_key* key;
- int result;
-
- key = (st_strend_key* )xmalloc(sizeof(st_strend_key));
- key->s = (unsigned char* )str_key;
- key->end = (unsigned char* )end_key;
- result = onig_st_insert(table, (st_data_t )key, value);
- if (result) {
- xfree(key);
- }
- return result;
-}
-
-static int
-strend_cmp(st_strend_key* x, st_strend_key* y)
-{
- unsigned char *p, *q;
- int c;
-
- if ((x->end - x->s) != (y->end - y->s))
- return 1;
-
- p = x->s;
- q = y->s;
- while (p < x->end) {
- c = (int )*p - (int )*q;
- if (c != 0) return c;
-
- p++; q++;
- }
-
- return 0;
-}
-
-static int
-strend_hash(st_strend_key* x)
-{
- int val;
- unsigned char *p;
-
- val = 0;
- p = x->s;
- while (p < x->end) {
- val = val * 997 + (int )*p++;
- }
-
- return val + (val >> 5);
-}
-
-typedef st_table NameTable;
-typedef st_data_t HashDataType; /* 1.6 st.h doesn't define st_data_t type */
-
-#define NAMEBUF_SIZE 24
-#define NAMEBUF_SIZE_1 25
-
-#ifdef ONIG_DEBUG
-static int
-i_print_name_entry(UChar* key, NameEntry* e, void* arg)
-{
- int i;
- FILE* fp = (FILE* )arg;
-
- fprintf(fp, "%s: ", e->name);
- if (e->back_num == 0)
- fputs("-", fp);
- else if (e->back_num == 1)
- fprintf(fp, "%d", e->back_ref1);
- else {
- for (i = 0; i < e->back_num; i++) {
- if (i > 0) fprintf(fp, ", ");
- fprintf(fp, "%d", e->back_refs[i]);
- }
- }
- fputs("\n", fp);
- return ST_CONTINUE;
-}
-
-extern int
-onig_print_names(FILE* fp, regex_t* reg)
-{
- NameTable* t = (NameTable* )reg->name_table;
-
- if (IS_NOT_NULL(t)) {
- fprintf(fp, "name table\n");
- onig_st_foreach(t, i_print_name_entry, (HashDataType )fp);
- fputs("\n", fp);
- }
- return 0;
-}
-#endif
-
-static int
-i_free_name_entry(UChar* key, NameEntry* e, void* arg)
-{
- xfree(e->name);
- if (IS_NOT_NULL(e->back_refs)) xfree(e->back_refs);
- xfree(key);
- xfree(e);
- return ST_DELETE;
-}
-
-static int
-names_clear(regex_t* reg)
-{
- NameTable* t = (NameTable* )reg->name_table;
-
- if (IS_NOT_NULL(t)) {
- onig_st_foreach(t, i_free_name_entry, 0);
- }
- return 0;
-}
-
-extern int
-onig_names_free(regex_t* reg)
-{
- int r;
- NameTable* t;
-
- r = names_clear(reg);
- if (r) return r;
-
- t = (NameTable* )reg->name_table;
- if (IS_NOT_NULL(t)) onig_st_free_table(t);
- reg->name_table = (void* )NULL;
- return 0;
-}
-
-static NameEntry*
-name_find(regex_t* reg, const UChar* name, const UChar* name_end)
-{
- NameEntry* e;
- NameTable* t = (NameTable* )reg->name_table;
-
- e = (NameEntry* )NULL;
- if (IS_NOT_NULL(t)) {
- onig_st_lookup_strend(t, name, name_end, (HashDataType* )((void* )(&e)));
- }
- return e;
-}
-
-typedef struct {
- int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*);
- regex_t* reg;
- void* arg;
- int ret;
- OnigEncoding enc;
-} INamesArg;
-
-static int
-i_names(UChar* key, NameEntry* e, INamesArg* arg)
-{
- int r = (*(arg->func))(e->name,
- /*e->name + onigenc_str_bytelen_null(arg->enc, e->name), */
- e->name + e->name_len,
- e->back_num,
- (e->back_num > 1 ? e->back_refs : &(e->back_ref1)),
- arg->reg, arg->arg);
- if (r != 0) {
- arg->ret = r;
- return ST_STOP;
- }
- return ST_CONTINUE;
-}
-
-extern int
-onig_foreach_name(regex_t* reg,
- int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*),
- void* arg)
-{
- INamesArg narg;
- NameTable* t = (NameTable* )reg->name_table;
-
- narg.ret = 0;
- if (IS_NOT_NULL(t)) {
- narg.func = func;
- narg.reg = reg;
- narg.arg = arg;
- narg.enc = reg->enc; /* should be pattern encoding. */
- onig_st_foreach(t, i_names, (HashDataType )&narg);
- }
- return narg.ret;
-}
-
-static int
-i_renumber_name(UChar* key, NameEntry* e, GroupNumRemap* map)
-{
- int i;
-
- if (e->back_num > 1) {
- for (i = 0; i < e->back_num; i++) {
- e->back_refs[i] = map[e->back_refs[i]].new_val;
- }
- }
- else if (e->back_num == 1) {
- e->back_ref1 = map[e->back_ref1].new_val;
- }
-
- return ST_CONTINUE;
-}
-
-extern int
-onig_renumber_name_table(regex_t* reg, GroupNumRemap* map)
-{
- NameTable* t = (NameTable* )reg->name_table;
-
- if (IS_NOT_NULL(t)) {
- onig_st_foreach(t, i_renumber_name, (HashDataType )map);
- }
- return 0;
-}
-
-
-extern int
-onig_number_of_names(regex_t* reg)
-{
- NameTable* t = (NameTable* )reg->name_table;
-
- if (IS_NOT_NULL(t))
- return t->num_entries;
- else
- return 0;
-}
-
-#else /* USE_ST_HASH_TABLE */
-
-#define INIT_NAMES_ALLOC_NUM 8
-
-typedef struct {
- NameEntry* e;
- int num;
- int alloc;
-} NameTable;
-
-
-#ifdef ONIG_DEBUG
-extern int
-onig_print_names(FILE* fp, regex_t* reg)
-{
- int i, j;
- NameEntry* e;
- NameTable* t = (NameTable* )reg->name_table;
-
- if (IS_NOT_NULL(t) && t->num > 0) {
- fprintf(fp, "name table\n");
- for (i = 0; i < t->num; i++) {
- e = &(t->e[i]);
- fprintf(fp, "%s: ", e->name);
- if (e->back_num == 0) {
- fputs("-", fp);
- }
- else if (e->back_num == 1) {
- fprintf(fp, "%d", e->back_ref1);
- }
- else {
- for (j = 0; j < e->back_num; j++) {
- if (j > 0) fprintf(fp, ", ");
- fprintf(fp, "%d", e->back_refs[j]);
- }
- }
- fputs("\n", fp);
- }
- fputs("\n", fp);
- }
- return 0;
-}
-#endif
-
-static int
-names_clear(regex_t* reg)
-{
- int i;
- NameEntry* e;
- NameTable* t = (NameTable* )reg->name_table;
-
- if (IS_NOT_NULL(t)) {
- for (i = 0; i < t->num; i++) {
- e = &(t->e[i]);
- if (IS_NOT_NULL(e->name)) {
- xfree(e->name);
- e->name = NULL;
- e->name_len = 0;
- e->back_num = 0;
- e->back_alloc = 0;
- if (IS_NOT_NULL(e->back_refs)) xfree(e->back_refs);
- e->back_refs = (int* )NULL;
- }
- }
- if (IS_NOT_NULL(t->e)) {
- xfree(t->e);
- t->e = NULL;
- }
- t->num = 0;
- }
- return 0;
-}
-
-extern int
-onig_names_free(regex_t* reg)
-{
- int r;
- NameTable* t;
-
- r = names_clear(reg);
- if (r) return r;
-
- t = (NameTable* )reg->name_table;
- if (IS_NOT_NULL(t)) xfree(t);
- reg->name_table = NULL;
- return 0;
-}
-
-static NameEntry*
-name_find(regex_t* reg, UChar* name, UChar* name_end)
-{
- int i, len;
- NameEntry* e;
- NameTable* t = (NameTable* )reg->name_table;
-
- if (IS_NOT_NULL(t)) {
- len = name_end - name;
- for (i = 0; i < t->num; i++) {
- e = &(t->e[i]);
- if (len == e->name_len && onig_strncmp(name, e->name, len) == 0)
- return e;
- }
- }
- return (NameEntry* )NULL;
-}
-
-extern int
-onig_foreach_name(regex_t* reg,
- int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*),
- void* arg)
-{
- int i, r;
- NameEntry* e;
- NameTable* t = (NameTable* )reg->name_table;
-
- if (IS_NOT_NULL(t)) {
- for (i = 0; i < t->num; i++) {
- e = &(t->e[i]);
- r = (*func)(e->name, e->name + e->name_len, e->back_num,
- (e->back_num > 1 ? e->back_refs : &(e->back_ref1)),
- reg, arg);
- if (r != 0) return r;
- }
- }
- return 0;
-}
-
-extern int
-onig_number_of_names(regex_t* reg)
-{
- NameTable* t = (NameTable* )reg->name_table;
-
- if (IS_NOT_NULL(t))
- return t->num;
- else
- return 0;
-}
-
-#endif /* else USE_ST_HASH_TABLE */
-
-static int
-name_add(regex_t* reg, UChar* name, UChar* name_end, int backref, ScanEnv* env)
-{
- int alloc;
- NameEntry* e;
- NameTable* t = (NameTable* )reg->name_table;
-
- if (name_end - name <= 0)
- return ONIGERR_EMPTY_GROUP_NAME;
-
- e = name_find(reg, name, name_end);
- if (IS_NULL(e)) {
-#ifdef USE_ST_HASH_TABLE
- if (IS_NULL(t)) {
- t = onig_st_init_strend_table_with_size(5);
- reg->name_table = (void* )t;
- }
- e = (NameEntry* )xmalloc(sizeof(NameEntry));
- CHECK_NULL_RETURN_VAL(e, ONIGERR_MEMORY);
-
- e->name = strdup_with_null(reg->enc, name, name_end);
- if (IS_NULL(e->name)) return ONIGERR_MEMORY;
- onig_st_insert_strend(t, e->name, (e->name + (name_end - name)),
- (HashDataType )e);
-
- e->name_len = name_end - name;
- e->back_num = 0;
- e->back_alloc = 0;
- e->back_refs = (int* )NULL;
-
-#else
-
- if (IS_NULL(t)) {
- alloc = INIT_NAMES_ALLOC_NUM;
- t = (NameTable* )xmalloc(sizeof(NameTable));
- CHECK_NULL_RETURN_VAL(t, ONIGERR_MEMORY);
- t->e = NULL;
- t->alloc = 0;
- t->num = 0;
-
- t->e = (NameEntry* )xmalloc(sizeof(NameEntry) * alloc);
- if (IS_NULL(t->e)) {
- xfree(t);
- return ONIGERR_MEMORY;
- }
- t->alloc = alloc;
- reg->name_table = t;
- goto clear;
- }
- else if (t->num == t->alloc) {
- int i;
-
- alloc = t->alloc * 2;
- t->e = (NameEntry* )xrealloc(t->e, sizeof(NameEntry) * alloc);
- CHECK_NULL_RETURN_VAL(t->e, ONIGERR_MEMORY);
- t->alloc = alloc;
-
- clear:
- for (i = t->num; i < t->alloc; i++) {
- t->e[i].name = NULL;
- t->e[i].name_len = 0;
- t->e[i].back_num = 0;
- t->e[i].back_alloc = 0;
- t->e[i].back_refs = (int* )NULL;
- }
- }
- e = &(t->e[t->num]);
- t->num++;
- e->name = strdup_with_null(reg->enc, name, name_end);
- e->name_len = name_end - name;
-#endif
- }
-
- if (e->back_num >= 1 &&
- ! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME)) {
- onig_scan_env_set_error_string(env, ONIGERR_MULTIPLEX_DEFINED_NAME,
- name, name_end);
- return ONIGERR_MULTIPLEX_DEFINED_NAME;
- }
-
- e->back_num++;
- if (e->back_num == 1) {
- e->back_ref1 = backref;
- }
- else {
- if (e->back_num == 2) {
- alloc = INIT_NAME_BACKREFS_ALLOC_NUM;
- e->back_refs = (int* )xmalloc(sizeof(int) * alloc);
- CHECK_NULL_RETURN_VAL(e->back_refs, ONIGERR_MEMORY);
- e->back_alloc = alloc;
- e->back_refs[0] = e->back_ref1;
- e->back_refs[1] = backref;
- }
- else {
- if (e->back_num > e->back_alloc) {
- alloc = e->back_alloc * 2;
- e->back_refs = (int* )xrealloc(e->back_refs, sizeof(int) * alloc);
- CHECK_NULL_RETURN_VAL(e->back_refs, ONIGERR_MEMORY);
- e->back_alloc = alloc;
- }
- e->back_refs[e->back_num - 1] = backref;
- }
- }
-
- return 0;
-}
-
-extern int
-onig_name_to_group_numbers(regex_t* reg, const UChar* name,
- const UChar* name_end, int** nums)
-{
- NameEntry* e;
-
- e = name_find(reg, name, name_end);
- if (IS_NULL(e)) return ONIGERR_UNDEFINED_NAME_REFERENCE;
-
- switch (e->back_num) {
- case 0:
- break;
- case 1:
- *nums = &(e->back_ref1);
- break;
- default:
- *nums = e->back_refs;
- break;
- }
- return e->back_num;
-}
-
-extern int
-onig_name_to_backref_number(regex_t* reg, const UChar* name,
- const UChar* name_end, OnigRegion *region)
-{
- int i, n, *nums;
-
- n = onig_name_to_group_numbers(reg, name, name_end, &nums);
- if (n < 0)
- return n;
- else if (n == 0)
- return ONIGERR_PARSER_BUG;
- else if (n == 1)
- return nums[0];
- else {
- if (IS_NOT_NULL(region)) {
- for (i = n - 1; i >= 0; i--) {
- if (region->beg[nums[i]] != ONIG_REGION_NOTPOS)
- return nums[i];
- }
- }
- return nums[n - 1];
- }
-}
-
-#else /* USE_NAMED_GROUP */
-
-extern int
-onig_name_to_group_numbers(regex_t* reg, const UChar* name,
- const UChar* name_end, int** nums)
-{
- return ONIG_NO_SUPPORT_CONFIG;
-}
-
-extern int
-onig_name_to_backref_number(regex_t* reg, const UChar* name,
- const UChar* name_end, OnigRegion* region)
-{
- return ONIG_NO_SUPPORT_CONFIG;
-}
-
-extern int
-onig_foreach_name(regex_t* reg,
- int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*),
- void* arg)
-{
- return ONIG_NO_SUPPORT_CONFIG;
-}
-
-extern int
-onig_number_of_names(regex_t* reg)
-{
- return 0;
-}
-#endif /* else USE_NAMED_GROUP */
-
-
-#define INIT_SCANENV_MEMNODES_ALLOC_SIZE 16
-
-static void
-scan_env_clear(ScanEnv* env)
-{
- int i;
-
- BIT_STATUS_CLEAR(env->capture_history);
- BIT_STATUS_CLEAR(env->bt_mem_start);
- BIT_STATUS_CLEAR(env->bt_mem_end);
- BIT_STATUS_CLEAR(env->backrefed_mem);
- env->error = (UChar* )NULL;
- env->error_end = (UChar* )NULL;
- env->num_call = 0;
- env->num_mem = 0;
-#ifdef USE_NAMED_GROUP
- env->num_named = 0;
-#endif
- env->mem_alloc = 0;
- env->mem_nodes_dynamic = (Node** )NULL;
-
- for (i = 0; i < SCANENV_MEMNODES_SIZE; i++)
- env->mem_nodes_static[i] = NULL_NODE;
-}
-
-static int
-scan_env_add_mem_entry(ScanEnv* env)
-{
- int i, need, alloc;
- Node** p;
-
- need = env->num_mem + 1;
- if (need >= SCANENV_MEMNODES_SIZE) {
- if (env->mem_alloc <= need) {
- if (IS_NULL(env->mem_nodes_dynamic)) {
- alloc = INIT_SCANENV_MEMNODES_ALLOC_SIZE;
- p = (Node** )xmalloc(sizeof(Node*) * alloc);
- xmemcpy(p, env->mem_nodes_static,
- sizeof(Node*) * SCANENV_MEMNODES_SIZE);
- }
- else {
- alloc = env->mem_alloc * 2;
- p = (Node** )xrealloc(env->mem_nodes_dynamic, sizeof(Node*) * alloc);
- }
- CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY);
-
- for (i = env->num_mem + 1; i < alloc; i++)
- p[i] = NULL_NODE;
-
- env->mem_nodes_dynamic = p;
- env->mem_alloc = alloc;
- }
- }
-
- env->num_mem++;
- return env->num_mem;
-}
-
-static int
-scan_env_set_mem_node(ScanEnv* env, int num, Node* node)
-{
- if (env->num_mem >= num)
- SCANENV_MEM_NODES(env)[num] = node;
- else
- return ONIGERR_PARSER_BUG;
- return 0;
-}
-
-
-#ifdef USE_RECYCLE_NODE
-typedef struct _FreeNode {
- struct _FreeNode* next;
-} FreeNode;
-
-static FreeNode* FreeNodeList = (FreeNode* )NULL;
-#endif
-
-extern void
-onig_node_free(Node* node)
-{
- start:
- if (IS_NULL(node)) return ;
-
- switch (NTYPE(node)) {
- case N_STRING:
- if (IS_NOT_NULL(NSTRING(node).s) && NSTRING(node).s != NSTRING(node).buf) {
- xfree(NSTRING(node).s);
- }
- break;
-
- case N_LIST:
- case N_ALT:
- onig_node_free(NCONS(node).left);
- /* onig_node_free(NCONS(node).right); */
- {
- Node* next_node = NCONS(node).right;
-
-#ifdef USE_RECYCLE_NODE
- {
- FreeNode* n = (FreeNode* )node;
-
- THREAD_ATOMIC_START;
- n->next = FreeNodeList;
- FreeNodeList = n;
- THREAD_ATOMIC_END;
- }
-#else
- xfree(node);
-#endif
-
- node = next_node;
- goto start;
- }
- break;
-
- case N_CCLASS:
- {
- CClassNode* cc = &(NCCLASS(node));
-
- if (IS_CCLASS_SHARE(cc))
- return ;
-
- if (cc->mbuf)
- bbuf_free(cc->mbuf);
- }
- break;
-
- case N_QUALIFIER:
- if (NQUALIFIER(node).target)
- onig_node_free(NQUALIFIER(node).target);
- break;
-
- case N_EFFECT:
- if (NEFFECT(node).target)
- onig_node_free(NEFFECT(node).target);
- break;
-
- case N_BACKREF:
- if (IS_NOT_NULL(NBACKREF(node).back_dynamic))
- xfree(NBACKREF(node).back_dynamic);
- break;
-
- case N_ANCHOR:
- if (NANCHOR(node).target)
- onig_node_free(NANCHOR(node).target);
- break;
- }
-
-#ifdef USE_RECYCLE_NODE
- {
- FreeNode* n = (FreeNode* )node;
-
- THREAD_ATOMIC_START;
- n->next = FreeNodeList;
- FreeNodeList = n;
- THREAD_ATOMIC_END;
- }
-#else
- xfree(node);
-#endif
-}
-
-#ifdef USE_RECYCLE_NODE
-extern int
-onig_free_node_list()
-{
- FreeNode* n;
-
- THREAD_ATOMIC_START;
- while (FreeNodeList) {
- n = FreeNodeList;
- FreeNodeList = FreeNodeList->next;
- xfree(n);
- }
- THREAD_ATOMIC_END;
- return 0;
-}
-#endif
-
-static Node*
-node_new()
-{
- Node* node;
-
-#ifdef USE_RECYCLE_NODE
- if (IS_NOT_NULL(FreeNodeList)) {
- THREAD_ATOMIC_START;
- node = (Node* )FreeNodeList;
- FreeNodeList = FreeNodeList->next;
- THREAD_ATOMIC_END;
- return node;
- }
-#endif
-
- node = (Node* )xmalloc(sizeof(Node));
- return node;
-}
-
-
-static void
-initialize_cclass(CClassNode* cc)
-{
- BITSET_CLEAR(cc->bs);
- cc->flags = 0;
- cc->mbuf = NULL;
-}
-
-static Node*
-node_new_cclass()
-{
- Node* node = node_new();
- CHECK_NULL_RETURN(node);
- node->type = N_CCLASS;
-
- initialize_cclass(&(NCCLASS(node)));
- return node;
-}
-
-extern Node*
-node_new_cclass_by_codepoint_range(int not,
- OnigCodePoint sbr[], OnigCodePoint mbr[])
-{
- CClassNode* cc;
- int n, i, j;
-
- Node* node = node_new();
- CHECK_NULL_RETURN(node);
- node->type = N_CCLASS;
-
- cc = &(NCCLASS(node));
- cc->flags = 0;
- if (not != 0) CCLASS_SET_NOT(cc);
-
- BITSET_CLEAR(cc->bs);
- if (IS_NOT_NULL(sbr)) {
- n = ONIGENC_CODE_RANGE_NUM(sbr);
- for (i = 0; i < n; i++) {
- for (j = ONIGENC_CODE_RANGE_FROM(sbr, i);
- j <= (int )ONIGENC_CODE_RANGE_TO(sbr, i); j++) {
- BITSET_SET_BIT(cc->bs, j);
- }
- }
- }
-
- if (IS_NULL(mbr)) {
- is_null:
- cc->mbuf = NULL;
- }
- else {
- BBuf* bbuf;
-
- n = ONIGENC_CODE_RANGE_NUM(mbr);
- if (n == 0) goto is_null;
-
- bbuf = (BBuf* )xmalloc(sizeof(BBuf));
- CHECK_NULL_RETURN_VAL(bbuf, NULL);
- bbuf->alloc = n + 1;
- bbuf->used = n + 1;
- bbuf->p = (UChar* )((void* )mbr);
-
- cc->mbuf = bbuf;
- }
-
- return node;
-}
-
-static Node*
-node_new_ctype(int type)
-{
- Node* node = node_new();
- CHECK_NULL_RETURN(node);
- node->type = N_CTYPE;
- NCTYPE(node).type = type;
- return node;
-}
-
-static Node*
-node_new_anychar()
-{
- Node* node = node_new();
- CHECK_NULL_RETURN(node);
- node->type = N_ANYCHAR;
- return node;
-}
-
-static Node*
-node_new_list(Node* left, Node* right)
-{
- Node* node = node_new();
- CHECK_NULL_RETURN(node);
- node->type = N_LIST;
- NCONS(node).left = left;
- NCONS(node).right = right;
- return node;
-}
-
-extern Node*
-onig_node_new_list(Node* left, Node* right)
-{
- return node_new_list(left, right);
-}
-
-static Node*
-node_new_alt(Node* left, Node* right)
-{
- Node* node = node_new();
- CHECK_NULL_RETURN(node);
- node->type = N_ALT;
- NCONS(node).left = left;
- NCONS(node).right = right;
- return node;
-}
-
-extern Node*
-onig_node_new_anchor(int type)
-{
- Node* node = node_new();
- CHECK_NULL_RETURN(node);
- node->type = N_ANCHOR;
- NANCHOR(node).type = type;
- NANCHOR(node).target = NULL;
- NANCHOR(node).char_len = -1;
- return node;
-}
-
-static Node*
-node_new_backref(int back_num, int* backrefs, int by_name, ScanEnv* env)
-{
- int i;
- Node* node = node_new();
-
- CHECK_NULL_RETURN(node);
- node->type = N_BACKREF;
- NBACKREF(node).state = 0;
- NBACKREF(node).back_num = back_num;
- NBACKREF(node).back_dynamic = (int* )NULL;
- if (by_name != 0)
- NBACKREF(node).state |= NST_NAME_REF;
-
- for (i = 0; i < back_num; i++) {
- if (backrefs[i] <= env->num_mem &&
- IS_NULL(SCANENV_MEM_NODES(env)[backrefs[i]])) {
- NBACKREF(node).state |= NST_RECURSION; /* /...(\1).../ */
- break;
- }
- }
-
- if (back_num <= NODE_BACKREFS_SIZE) {
- for (i = 0; i < back_num; i++)
- NBACKREF(node).back_static[i] = backrefs[i];
- }
- else {
- int* p = (int* )xmalloc(sizeof(int) * back_num);
- if (IS_NULL(p)) {
- onig_node_free(node);
- return NULL;
- }
- NBACKREF(node).back_dynamic = p;
- for (i = 0; i < back_num; i++)
- p[i] = backrefs[i];
- }
- return node;
-}
-
-#ifdef USE_SUBEXP_CALL
-static Node*
-node_new_call(UChar* name, UChar* name_end)
-{
- Node* node = node_new();
- CHECK_NULL_RETURN(node);
-
- node->type = N_CALL;
- NCALL(node).state = 0;
- NCALL(node).ref_num = CALLNODE_REFNUM_UNDEF;
- NCALL(node).target = NULL_NODE;
- NCALL(node).name = name;
- NCALL(node).name_end = name_end;
- return node;
-}
-#endif
-
-static Node*
-node_new_qualifier(int lower, int upper, int by_number)
-{
- Node* node = node_new();
- CHECK_NULL_RETURN(node);
- node->type = N_QUALIFIER;
- NQUALIFIER(node).state = 0;
- NQUALIFIER(node).target = NULL;
- NQUALIFIER(node).lower = lower;
- NQUALIFIER(node).upper = upper;
- NQUALIFIER(node).greedy = 1;
- NQUALIFIER(node).by_number = by_number;
- NQUALIFIER(node).target_empty_info = NQ_TARGET_ISNOT_EMPTY;
- NQUALIFIER(node).head_exact = NULL_NODE;
- NQUALIFIER(node).next_head_exact = NULL_NODE;
- NQUALIFIER(node).is_refered = 0;
- return node;
-}
-
-static Node*
-node_new_effect(int type)
-{
- Node* node = node_new();
- CHECK_NULL_RETURN(node);
- node->type = N_EFFECT;
- NEFFECT(node).type = type;
- NEFFECT(node).state = 0;
- NEFFECT(node).regnum = 0;
- NEFFECT(node).option = 0;
- NEFFECT(node).target = NULL;
- NEFFECT(node).call_addr = -1;
- NEFFECT(node).opt_count = 0;
- return node;
-}
-
-extern Node*
-onig_node_new_effect(int type)
-{
- return node_new_effect(type);
-}
-
-static Node*
-node_new_effect_memory(OnigOptionType option, int is_named)
-{
- Node* node = node_new_effect(EFFECT_MEMORY);
- CHECK_NULL_RETURN(node);
- if (is_named != 0)
- SET_EFFECT_STATUS(node, NST_NAMED_GROUP);
-
-#ifdef USE_SUBEXP_CALL
- NEFFECT(node).option = option;
-#endif
- return node;
-}
-
-static Node*
-node_new_option(OnigOptionType option)
-{
- Node* node = node_new_effect(EFFECT_OPTION);
- CHECK_NULL_RETURN(node);
- NEFFECT(node).option = option;
- return node;
-}
-
-extern int
-onig_node_str_cat(Node* node, const UChar* s, const UChar* end)
-{
- int addlen = end - s;
-
- if (addlen > 0) {
- int len = NSTRING(node).end - NSTRING(node).s;
-
- if (NSTRING(node).capa > 0 || (len + addlen > NODE_STR_BUF_SIZE - 1)) {
- UChar* p;
- int capa = len + addlen + NODE_STR_MARGIN;
-
- if (capa <= NSTRING(node).capa) {
- k_strcpy(NSTRING(node).s + len, s, end);
- }
- else {
- if (NSTRING(node).s == NSTRING(node).buf)
- p = strcat_capa_from_static(NSTRING(node).s, NSTRING(node).end,
- s, end, capa);
- else
- p = k_strcat_capa(NSTRING(node).s, NSTRING(node).end, s, end, capa);
-
- CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY);
- NSTRING(node).s = p;
- NSTRING(node).capa = capa;
- }
- }
- else {
- k_strcpy(NSTRING(node).s + len, s, end);
- }
- NSTRING(node).end = NSTRING(node).s + len + addlen;
- }
-
- return 0;
-}
-
-static int
-node_str_cat_char(Node* node, UChar c)
-{
- UChar s[1];
-
- s[0] = c;
- return onig_node_str_cat(node, s, s + 1);
-}
-
-extern void
-onig_node_conv_to_str_node(Node* node, int flag)
-{
- node->type = N_STRING;
-
- NSTRING(node).flag = flag;
- NSTRING(node).capa = 0;
- NSTRING(node).s = NSTRING(node).buf;
- NSTRING(node).end = NSTRING(node).buf;
-}
-
-extern void
-onig_node_str_clear(Node* node)
-{
- if (NSTRING(node).capa != 0 &&
- IS_NOT_NULL(NSTRING(node).s) && NSTRING(node).s != NSTRING(node).buf) {
- xfree(NSTRING(node).s);
- }
-
- NSTRING(node).capa = 0;
- NSTRING(node).flag = 0;
- NSTRING(node).s = NSTRING(node).buf;
- NSTRING(node).end = NSTRING(node).buf;
-}
-
-static Node*
-node_new_str(const UChar* s, const UChar* end)
-{
- Node* node = node_new();
- CHECK_NULL_RETURN(node);
-
- node->type = N_STRING;
- NSTRING(node).capa = 0;
- NSTRING(node).flag = 0;
- NSTRING(node).s = NSTRING(node).buf;
- NSTRING(node).end = NSTRING(node).buf;
- if (onig_node_str_cat(node, s, end)) {
- onig_node_free(node);
- return NULL;
- }
- return node;
-}
-
-extern Node*
-onig_node_new_str(const UChar* s, const UChar* end)
-{
- return node_new_str(s, end);
-}
-
-static Node*
-node_new_str_raw(UChar* s, UChar* end)
-{
- Node* node = node_new_str(s, end);
- NSTRING_SET_RAW(node);
- return node;
-}
-
-static Node*
-node_new_empty()
-{
- return node_new_str(NULL, NULL);
-}
-
-static Node*
-node_new_str_raw_char(UChar c)
-{
- UChar p[1];
-
- p[0] = c;
- return node_new_str_raw(p, p + 1);
-}
-
-static Node*
-str_node_split_last_char(StrNode* sn, OnigEncoding enc)
-{
- const UChar *p;
- Node* n = NULL_NODE;
-
- if (sn->end > sn->s) {
- p = onigenc_get_prev_char_head(enc, sn->s, sn->end);
- if (p && p > sn->s) { /* can be splitted. */
- n = node_new_str(p, sn->end);
- if ((sn->flag & NSTR_RAW) != 0)
- NSTRING_SET_RAW(n);
- sn->end = (UChar* )p;
- }
- }
- return n;
-}
-
-static int
-str_node_can_be_split(StrNode* sn, OnigEncoding enc)
-{
- if (sn->end > sn->s) {
- return ((enc_len(enc, sn->s) < sn->end - sn->s) ? 1 : 0);
- }
- return 0;
-}
-
-extern int
-onig_scan_unsigned_number(UChar** src, const UChar* end, OnigEncoding enc)
-{
- unsigned int num, val;
- OnigCodePoint c;
- UChar* p = *src;
- PFETCH_READY;
-
- num = 0;
- while (!PEND) {
- PFETCH(c);
- if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
- val = (unsigned int )DIGITVAL(c);
- if ((INT_MAX_LIMIT - val) / 10UL < num)
- return -1; /* overflow */
-
- num = num * 10 + val;
- }
- else {
- PUNFETCH;
- break;
- }
- }
- *src = p;
- return num;
-}
-
-static int
-scan_unsigned_hexadecimal_number(UChar** src, UChar* end, int maxlen,
- OnigEncoding enc)
-{
- OnigCodePoint c;
- unsigned int num, val;
- UChar* p = *src;
- PFETCH_READY;
-
- num = 0;
- while (!PEND && maxlen-- != 0) {
- PFETCH(c);
- if (ONIGENC_IS_CODE_XDIGIT(enc, c)) {
- val = (unsigned int )XDIGITVAL(enc,c);
- if ((INT_MAX_LIMIT - val) / 16UL < num)
- return -1; /* overflow */
-
- num = (num << 4) + XDIGITVAL(enc,c);
- }
- else {
- PUNFETCH;
- break;
- }
- }
- *src = p;
- return num;
-}
-
-static int
-scan_unsigned_octal_number(UChar** src, UChar* end, int maxlen,
- OnigEncoding enc)
-{
- OnigCodePoint c;
- unsigned int num, val;
- UChar* p = *src;
- PFETCH_READY;
-
- num = 0;
- while (!PEND && maxlen-- != 0) {
- PFETCH(c);
- if (ONIGENC_IS_CODE_DIGIT(enc, c) && c < '8') {
- val = ODIGITVAL(c);
- if ((INT_MAX_LIMIT - val) / 8UL < num)
- return -1; /* overflow */
-
- num = (num << 3) + val;
- }
- else {
- PUNFETCH;
- break;
- }
- }
- *src = p;
- return num;
-}
-
-
-#define BBUF_WRITE_CODE_POINT(bbuf,pos,code) \
- BBUF_WRITE(bbuf, pos, &(code), SIZE_CODE_POINT)
-
-/* data format:
- [n][from-1][to-1][from-2][to-2] ... [from-n][to-n]
- (all data size is OnigCodePoint)
- */
-static int
-new_code_range(BBuf** pbuf)
-{
-#define INIT_MULTI_BYTE_RANGE_SIZE (SIZE_CODE_POINT * 5)
- int r;
- OnigCodePoint n;
- BBuf* bbuf;
-
- bbuf = *pbuf = (BBuf* )xmalloc(sizeof(BBuf));
- CHECK_NULL_RETURN_VAL(*pbuf, ONIGERR_MEMORY);
- r = BBUF_INIT(*pbuf, INIT_MULTI_BYTE_RANGE_SIZE);
- if (r) return r;
-
- n = 0;
- BBUF_WRITE_CODE_POINT(bbuf, 0, n);
- return 0;
-}
-
-static int
-add_code_range_to_buf(BBuf** pbuf, OnigCodePoint from, OnigCodePoint to)
-{
- int r, inc_n, pos;
- int low, high, bound, x;
- OnigCodePoint n, *data;
- BBuf* bbuf;
-
- if (from > to) {
- n = from; from = to; to = n;
- }
-
- if (IS_NULL(*pbuf)) {
- r = new_code_range(pbuf);
- if (r) return r;
- bbuf = *pbuf;
- n = 0;
- }
- else {
- bbuf = *pbuf;
- GET_CODE_POINT(n, bbuf->p);
- }
- data = (OnigCodePoint* )(bbuf->p);
- data++;
-
- for (low = 0, bound = n; low < bound; ) {
- x = (low + bound) >> 1;
- if (from > data[x*2 + 1])
- low = x + 1;
- else
- bound = x;
- }
-
- for (high = low, bound = n; high < bound; ) {
- x = (high + bound) >> 1;
- if (to >= data[x*2] - 1)
- high = x + 1;
- else
- bound = x;
- }
-
- inc_n = low + 1 - high;
- if (n + inc_n > ONIG_MAX_MULTI_BYTE_RANGES_NUM)
- return ONIGERR_TOO_MANY_MULTI_BYTE_RANGES;
-
- if (inc_n != 1) {
- if (from > data[low*2])
- from = data[low*2];
- if (to < data[(high - 1)*2 + 1])
- to = data[(high - 1)*2 + 1];
- }
-
- if (inc_n != 0 && (OnigCodePoint )high < n) {
- int from_pos = SIZE_CODE_POINT * (1 + high * 2);
- int to_pos = SIZE_CODE_POINT * (1 + (low + 1) * 2);
- int size = (n - high) * 2 * SIZE_CODE_POINT;
-
- if (inc_n > 0) {
- BBUF_MOVE_RIGHT(bbuf, from_pos, to_pos, size);
- }
- else {
- BBUF_MOVE_LEFT_REDUCE(bbuf, from_pos, to_pos);
- }
- }
-
- pos = SIZE_CODE_POINT * (1 + low * 2);
- BBUF_ENSURE_SIZE(bbuf, pos + SIZE_CODE_POINT * 2);
- BBUF_WRITE_CODE_POINT(bbuf, pos, from);
- BBUF_WRITE_CODE_POINT(bbuf, pos + SIZE_CODE_POINT, to);
- n += inc_n;
- BBUF_WRITE_CODE_POINT(bbuf, 0, n);
-
- return 0;
-}
-
-static int
-add_code_range(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePoint to)
-{
- if (from > to) {
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
- return 0;
- else
- return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
- }
-
- return add_code_range_to_buf(pbuf, from, to);
-}
-
-static int
-not_code_range_buf(OnigEncoding enc, BBuf* bbuf, BBuf** pbuf)
-{
- int r, i, n;
- OnigCodePoint pre, from, *data, to = 0;
-
- *pbuf = (BBuf* )NULL;
- if (IS_NULL(bbuf)) {
- set_all:
- return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf);
- }
-
- data = (OnigCodePoint* )(bbuf->p);
- GET_CODE_POINT(n, data);
- data++;
- if (n <= 0) goto set_all;
-
- r = 0;
- pre = MBCODE_START_POS(enc);
- for (i = 0; i < n; i++) {
- from = data[i*2];
- to = data[i*2+1];
- if (pre <= from - 1) {
- r = add_code_range_to_buf(pbuf, pre, from - 1);
- if (r != 0) return r;
- }
- if (to == ~((OnigCodePoint )0)) break;
- pre = to + 1;
- }
- if (to < ~((OnigCodePoint )0)) {
- r = add_code_range_to_buf(pbuf, to + 1, ~((OnigCodePoint )0));
- }
- return r;
-}
-
-#define SWAP_BBUF_NOT(bbuf1, not1, bbuf2, not2) do {\
- BBuf *tbuf; \
- int tnot; \
- tnot = not1; not1 = not2; not2 = tnot; \
- tbuf = bbuf1; bbuf1 = bbuf2; bbuf2 = tbuf; \
-} while (0)
-
-static int
-or_code_range_buf(OnigEncoding enc, BBuf* bbuf1, int not1,
- BBuf* bbuf2, int not2, BBuf** pbuf)
-{
- int r;
- OnigCodePoint i, n1, *data1;
- OnigCodePoint from, to;
-
- *pbuf = (BBuf* )NULL;
- if (IS_NULL(bbuf1) && IS_NULL(bbuf2)) {
- if (not1 != 0 || not2 != 0)
- return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf);
- return 0;
- }
-
- r = 0;
- if (IS_NULL(bbuf2))
- SWAP_BBUF_NOT(bbuf1, not1, bbuf2, not2);
-
- if (IS_NULL(bbuf1)) {
- if (not1 != 0) {
- return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf);
- }
- else {
- if (not2 == 0) {
- return bbuf_clone(pbuf, bbuf2);
- }
- else {
- return not_code_range_buf(enc, bbuf2, pbuf);
- }
- }
- }
-
- if (not1 != 0)
- SWAP_BBUF_NOT(bbuf1, not1, bbuf2, not2);
-
- data1 = (OnigCodePoint* )(bbuf1->p);
- GET_CODE_POINT(n1, data1);
- data1++;
-
- if (not2 == 0 && not1 == 0) { /* 1 OR 2 */
- r = bbuf_clone(pbuf, bbuf2);
- }
- else if (not1 == 0) { /* 1 OR (not 2) */
- r = not_code_range_buf(enc, bbuf2, pbuf);
- }
- if (r != 0) return r;
-
- for (i = 0; i < n1; i++) {
- from = data1[i*2];
- to = data1[i*2+1];
- r = add_code_range_to_buf(pbuf, from, to);
- if (r != 0) return r;
- }
- return 0;
-}
-
-static int
-and_code_range1(BBuf** pbuf, OnigCodePoint from1, OnigCodePoint to1,
- OnigCodePoint* data, int n)
-{
- int i, r;
- OnigCodePoint from2, to2;
-
- for (i = 0; i < n; i++) {
- from2 = data[i*2];
- to2 = data[i*2+1];
- if (from2 < from1) {
- if (to2 < from1) continue;
- else {
- from1 = to2 + 1;
- }
- }
- else if (from2 <= to1) {
- if (to2 < to1) {
- if (from1 <= from2 - 1) {
- r = add_code_range_to_buf(pbuf, from1, from2-1);
- if (r != 0) return r;
- }
- from1 = to2 + 1;
- }
- else {
- to1 = from2 - 1;
- }
- }
- else {
- from1 = from2;
- }
- if (from1 > to1) break;
- }
- if (from1 <= to1) {
- r = add_code_range_to_buf(pbuf, from1, to1);
- if (r != 0) return r;
- }
- return 0;
-}
-
-static int
-and_code_range_buf(BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf)
-{
- int r;
- OnigCodePoint i, j, n1, n2, *data1, *data2;
- OnigCodePoint from, to, from1, to1, from2, to2;
-
- *pbuf = (BBuf* )NULL;
- if (IS_NULL(bbuf1)) {
- if (not1 != 0 && IS_NOT_NULL(bbuf2)) /* not1 != 0 -> not2 == 0 */
- return bbuf_clone(pbuf, bbuf2);
- return 0;
- }
- else if (IS_NULL(bbuf2)) {
- if (not2 != 0)
- return bbuf_clone(pbuf, bbuf1);
- return 0;
- }
-
- if (not1 != 0)
- SWAP_BBUF_NOT(bbuf1, not1, bbuf2, not2);
-
- data1 = (OnigCodePoint* )(bbuf1->p);
- data2 = (OnigCodePoint* )(bbuf2->p);
- GET_CODE_POINT(n1, data1);
- GET_CODE_POINT(n2, data2);
- data1++;
- data2++;
-
- if (not2 == 0 && not1 == 0) { /* 1 AND 2 */
- for (i = 0; i < n1; i++) {
- from1 = data1[i*2];
- to1 = data1[i*2+1];
- for (j = 0; j < n2; j++) {
- from2 = data2[j*2];
- to2 = data2[j*2+1];
- if (from2 > to1) break;
- if (to2 < from1) continue;
- from = MAX(from1, from2);
- to = MIN(to1, to2);
- r = add_code_range_to_buf(pbuf, from, to);
- if (r != 0) return r;
- }
- }
- }
- else if (not1 == 0) { /* 1 AND (not 2) */
- for (i = 0; i < n1; i++) {
- from1 = data1[i*2];
- to1 = data1[i*2+1];
- r = and_code_range1(pbuf, from1, to1, data2, n2);
- if (r != 0) return r;
- }
- }
-
- return 0;
-}
-
-static int
-clear_not_flag_cclass(CClassNode* cc, OnigEncoding enc)
-{
- BBuf *tbuf;
- int r;
-
- if (IS_CCLASS_NOT(cc)) {
- bitset_invert(cc->bs);
-
- if (! ONIGENC_IS_SINGLEBYTE(enc)) {
- r = not_code_range_buf(enc, cc->mbuf, &tbuf);
- if (r != 0) return r;
-
- bbuf_free(cc->mbuf);
- cc->mbuf = tbuf;
- }
-
- CCLASS_CLEAR_NOT(cc);
- }
-
- return 0;
-}
-
-static int
-and_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc)
-{
- int r, not1, not2;
- BBuf *buf1, *buf2, *pbuf;
- BitSetRef bsr1, bsr2;
- BitSet bs1, bs2;
-
- not1 = IS_CCLASS_NOT(dest);
- bsr1 = dest->bs;
- buf1 = dest->mbuf;
- not2 = IS_CCLASS_NOT(cc);
- bsr2 = cc->bs;
- buf2 = cc->mbuf;
-
- if (not1 != 0) {
- bitset_invert_to(bsr1, bs1);
- bsr1 = bs1;
- }
- if (not2 != 0) {
- bitset_invert_to(bsr2, bs2);
- bsr2 = bs2;
- }
- bitset_and(bsr1, bsr2);
- if (bsr1 != dest->bs) {
- bitset_copy(dest->bs, bsr1);
- bsr1 = dest->bs;
- }
- if (not1 != 0) {
- bitset_invert(dest->bs);
- }
-
- if (! ONIGENC_IS_SINGLEBYTE(enc)) {
- if (not1 != 0 && not2 != 0) {
- r = or_code_range_buf(enc, buf1, 0, buf2, 0, &pbuf);
- }
- else {
- r = and_code_range_buf(buf1, not1, buf2, not2, &pbuf);
- if (r == 0 && not1 != 0) {
- BBuf *tbuf;
- r = not_code_range_buf(enc, pbuf, &tbuf);
- if (r != 0) {
- bbuf_free(pbuf);
- return r;
- }
- bbuf_free(pbuf);
- pbuf = tbuf;
- }
- }
- if (r != 0) return r;
-
- dest->mbuf = pbuf;
- bbuf_free(buf1);
- return r;
- }
- return 0;
-}
-
-static int
-or_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc)
-{
- int r, not1, not2;
- BBuf *buf1, *buf2, *pbuf;
- BitSetRef bsr1, bsr2;
- BitSet bs1, bs2;
-
- not1 = IS_CCLASS_NOT(dest);
- bsr1 = dest->bs;
- buf1 = dest->mbuf;
- not2 = IS_CCLASS_NOT(cc);
- bsr2 = cc->bs;
- buf2 = cc->mbuf;
-
- if (not1 != 0) {
- bitset_invert_to(bsr1, bs1);
- bsr1 = bs1;
- }
- if (not2 != 0) {
- bitset_invert_to(bsr2, bs2);
- bsr2 = bs2;
- }
- bitset_or(bsr1, bsr2);
- if (bsr1 != dest->bs) {
- bitset_copy(dest->bs, bsr1);
- bsr1 = dest->bs;
- }
- if (not1 != 0) {
- bitset_invert(dest->bs);
- }
-
- if (! ONIGENC_IS_SINGLEBYTE(enc)) {
- if (not1 != 0 && not2 != 0) {
- r = and_code_range_buf(buf1, 0, buf2, 0, &pbuf);
- }
- else {
- r = or_code_range_buf(enc, buf1, not1, buf2, not2, &pbuf);
- if (r == 0 && not1 != 0) {
- BBuf *tbuf;
- r = not_code_range_buf(enc, pbuf, &tbuf);
- if (r != 0) {
- bbuf_free(pbuf);
- return r;
- }
- bbuf_free(pbuf);
- pbuf = tbuf;
- }
- }
- if (r != 0) return r;
-
- dest->mbuf = pbuf;
- bbuf_free(buf1);
- return r;
- }
- else
- return 0;
-}
-
-static int
-conv_backslash_value(int c, ScanEnv* env)
-{
- if (IS_SYNTAX_OP(env->syntax, ONIG_SYN_OP_ESC_CONTROL_CHARS)) {
- switch (c) {
- case 'n': return '\n';
- case 't': return '\t';
- case 'r': return '\r';
- case 'f': return '\f';
- case 'a': return '\007';
- case 'b': return '\010';
- case 'e': return '\033';
- case 'v':
- if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ESC_V_VTAB))
- return '\v';
- break;
-
- default:
- break;
- }
- }
- return c;
-}
-
-static int
-is_invalid_qualifier_target(Node* node)
-{
- switch (NTYPE(node)) {
- case N_ANCHOR:
- return 1;
- break;
-
- case N_EFFECT:
- if (NEFFECT(node).type == EFFECT_OPTION)
- return is_invalid_qualifier_target(NEFFECT(node).target);
- break;
-
- case N_LIST: /* ex. (?:\G\A)* */
- do {
- if (! is_invalid_qualifier_target(NCONS(node).left)) return 0;
- } while (IS_NOT_NULL(node = NCONS(node).right));
- return 0;
- break;
-
- case N_ALT: /* ex. (?:abc|\A)* */
- do {
- if (is_invalid_qualifier_target(NCONS(node).left)) return 1;
- } while (IS_NOT_NULL(node = NCONS(node).right));
- break;
-
- default:
- break;
- }
- return 0;
-}
-
-/* ?:0, *:1, +:2, ??:3, *?:4, +?:5 */
-static int
-popular_qualifier_num(QualifierNode* qf)
-{
- if (qf->greedy) {
- if (qf->lower == 0) {
- if (qf->upper == 1) return 0;
- else if (IS_REPEAT_INFINITE(qf->upper)) return 1;
- }
- else if (qf->lower == 1) {
- if (IS_REPEAT_INFINITE(qf->upper)) return 2;
- }
- }
- else {
- if (qf->lower == 0) {
- if (qf->upper == 1) return 3;
- else if (IS_REPEAT_INFINITE(qf->upper)) return 4;
- }
- else if (qf->lower == 1) {
- if (IS_REPEAT_INFINITE(qf->upper)) return 5;
- }
- }
- return -1;
-}
-
-
-enum ReduceType {
- RQ_ASIS = 0, /* as is */
- RQ_DEL = 1, /* delete parent */
- RQ_A, /* to '*' */
- RQ_AQ, /* to '*?' */
- RQ_QQ, /* to '??' */
- RQ_P_QQ, /* to '+)??' */
- RQ_PQ_Q, /* to '+?)?' */
-};
-
-static enum ReduceType ReduceTypeTable[6][6] = {
- {RQ_DEL, RQ_A, RQ_A, RQ_QQ, RQ_AQ, RQ_ASIS}, /* '?' */
- {RQ_DEL, RQ_DEL, RQ_DEL, RQ_P_QQ, RQ_P_QQ, RQ_DEL}, /* '*' */
- {RQ_A, RQ_A, RQ_DEL, RQ_ASIS, RQ_P_QQ, RQ_DEL}, /* '+' */
- {RQ_DEL, RQ_AQ, RQ_AQ, RQ_DEL, RQ_AQ, RQ_AQ}, /* '??' */
- {RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL}, /* '*?' */
- {RQ_ASIS, RQ_PQ_Q, RQ_DEL, RQ_AQ, RQ_AQ, RQ_DEL} /* '+?' */
-};
-
-extern void
-onig_reduce_nested_qualifier(Node* pnode, Node* cnode)
-{
- int pnum, cnum;
- QualifierNode *p, *c;
-
- p = &(NQUALIFIER(pnode));
- c = &(NQUALIFIER(cnode));
- pnum = popular_qualifier_num(p);
- cnum = popular_qualifier_num(c);
-
- switch(ReduceTypeTable[cnum][pnum]) {
- case RQ_DEL:
- *p = *c;
- break;
- case RQ_A:
- p->target = c->target;
- p->lower = 0; p->upper = REPEAT_INFINITE; p->greedy = 1;
- break;
- case RQ_AQ:
- p->target = c->target;
- p->lower = 0; p->upper = REPEAT_INFINITE; p->greedy = 0;
- break;
- case RQ_QQ:
- p->target = c->target;
- p->lower = 0; p->upper = 1; p->greedy = 0;
- break;
- case RQ_P_QQ:
- p->target = cnode;
- p->lower = 0; p->upper = 1; p->greedy = 0;
- c->lower = 1; c->upper = REPEAT_INFINITE; c->greedy = 1;
- return ;
- break;
- case RQ_PQ_Q:
- p->target = cnode;
- p->lower = 0; p->upper = 1; p->greedy = 1;
- c->lower = 1; c->upper = REPEAT_INFINITE; c->greedy = 0;
- return ;
- break;
- case RQ_ASIS:
- p->target = cnode;
- return ;
- break;
- }
-
- c->target = NULL_NODE;
- onig_node_free(cnode);
-}
-
-
-enum TokenSyms {
- TK_EOT = 0, /* end of token */
- TK_RAW_BYTE = 1,
- TK_CHAR,
- TK_STRING,
- TK_CODE_POINT,
- TK_ANYCHAR,
- TK_CHAR_TYPE,
- TK_BACKREF,
- TK_CALL,
- TK_ANCHOR,
- TK_OP_REPEAT,
- TK_INTERVAL,
- TK_ANYCHAR_ANYTIME, /* SQL '%' == .* */
- TK_ALT,
- TK_SUBEXP_OPEN,
- TK_SUBEXP_CLOSE,
- TK_CC_OPEN,
- TK_QUOTE_OPEN,
- TK_CHAR_PROPERTY, /* \p{...}, \P{...} */
- /* in cc */
- TK_CC_CLOSE,
- TK_CC_RANGE,
- TK_POSIX_BRACKET_OPEN,
- TK_CC_AND, /* && */
- TK_CC_CC_OPEN /* [ */
-};
-
-typedef struct {
- enum TokenSyms type;
- int escaped;
- int base; /* is number: 8, 16 (used in [....]) */
- UChar* backp;
- union {
- UChar* s;
- int c;
- OnigCodePoint code;
- int anchor;
- int subtype;
- struct {
- int lower;
- int upper;
- int greedy;
- int possessive;
- } repeat;
- struct {
- int num;
- int ref1;
- int* refs;
- int by_name;
- } backref;
- struct {
- UChar* name;
- UChar* name_end;
- } call;
- struct {
- int not;
- } prop;
- } u;
-} OnigToken;
-
-
-static int
-fetch_range_qualifier(UChar** src, UChar* end, OnigToken* tok, ScanEnv* env)
-{
- int low, up, syn_allow, non_low = 0;
- int r = 0;
- OnigCodePoint c;
- OnigEncoding enc = env->enc;
- UChar* p = *src;
- PFETCH_READY;
-
- syn_allow = IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_INVALID_INTERVAL);
-
- if (PEND) {
- if (syn_allow)
- return 1; /* "....{" : OK! */
- else
- return ONIGERR_END_PATTERN_AT_LEFT_BRACE; /* "....{" syntax error */
- }
-
- if (! syn_allow) {
- c = PPEEK;
- if (c == ')' || c == '(' || c == '|') {
- return ONIGERR_END_PATTERN_AT_LEFT_BRACE;
- }
- }
-
- low = onig_scan_unsigned_number(&p, end, env->enc);
- if (low < 0) return ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE;
- if (low > ONIG_MAX_REPEAT_NUM)
- return ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE;
-
- if (p == *src) { /* can't read low */
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV)) {
- /* allow {,n} as {0,n} */
- low = 0;
- non_low = 1;
- }
- else
- goto invalid;
- }
-
- if (PEND) goto invalid;
- PFETCH(c);
- if (c == ',') {
- UChar* prev = p;
- up = onig_scan_unsigned_number(&p, end, env->enc);
- if (up < 0) return ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE;
- if (up > ONIG_MAX_REPEAT_NUM)
- return ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE;
-
- if (p == prev) {
- if (non_low != 0)
- goto invalid;
- up = REPEAT_INFINITE; /* {n,} : {n,infinite} */
- }
- }
- else {
- if (non_low != 0)
- goto invalid;
-
- PUNFETCH;
- up = low; /* {n} : exact n times */
- r = 2; /* fixed */
- }
-
- if (PEND) goto invalid;
- PFETCH(c);
- if (IS_SYNTAX_OP(env->syntax, ONIG_SYN_OP_ESC_BRACE_INTERVAL)) {
- if (c != MC_ESC(enc)) goto invalid;
- PFETCH(c);
- }
- if (c != '}') goto invalid;
-
- if (!IS_REPEAT_INFINITE(up) && low > up) {
- return ONIGERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE;
- }
-
- tok->type = TK_INTERVAL;
- tok->u.repeat.lower = low;
- tok->u.repeat.upper = up;
- *src = p;
- return r; /* 0: normal {n,m}, 2: fixed {n} */
-
- invalid:
- if (syn_allow)
- return 1; /* OK */
- else
- return ONIGERR_INVALID_REPEAT_RANGE_PATTERN;
-}
-
-/* \M-, \C-, \c, or \... */
-static int
-fetch_escaped_value(UChar** src, UChar* end, ScanEnv* env)
-{
- int v;
- OnigCodePoint c;
- OnigEncoding enc = env->enc;
- UChar* p = *src;
- PFETCH_READY;
-
- if (PEND) return ONIGERR_END_PATTERN_AT_ESCAPE;
-
- PFETCH(c);
- switch (c) {
- case 'M':
- if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META)) {
- if (PEND) return ONIGERR_END_PATTERN_AT_META;
- PFETCH(c);
- if (c != '-') return ONIGERR_META_CODE_SYNTAX;
- if (PEND) return ONIGERR_END_PATTERN_AT_META;
- PFETCH(c);
- if (c == MC_ESC(enc)) {
- v = fetch_escaped_value(&p, end, env);
- if (v < 0) return v;
- c = (OnigCodePoint )v;
- }
- c = ((c & 0xff) | 0x80);
- }
- else
- goto backslash;
- break;
-
- case 'C':
- if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ESC_CAPITAL_C_BAR_CONTROL)) {
- if (PEND) return ONIGERR_END_PATTERN_AT_CONTROL;
- PFETCH(c);
- if (c != '-') return ONIGERR_CONTROL_CODE_SYNTAX;
- goto control;
- }
- else
- goto backslash;
-
- case 'c':
- if (IS_SYNTAX_OP(env->syntax, ONIG_SYN_OP_ESC_C_CONTROL)) {
- control:
- if (PEND) return ONIGERR_END_PATTERN_AT_CONTROL;
- PFETCH(c);
- if (c == MC_ESC(enc)) {
- v = fetch_escaped_value(&p, end, env);
- if (v < 0) return v;
- c = (OnigCodePoint )v;
- }
- else if (c == '?')
- c = 0177;
- else
- c &= 0x9f;
- break;
- }
- /* fall through */
-
- default:
- {
- backslash:
- c = conv_backslash_value(c, env);
- }
- break;
- }
-
- *src = p;
- return c;
-}
-
-static int fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env);
-
-#ifdef USE_NAMED_GROUP
-/*
- def: 0 -> define name (don't allow number name)
- 1 -> reference name (allow number name)
-*/
-static int
-fetch_name(UChar** src, UChar* end, UChar** rname_end, ScanEnv* env, int ref)
-{
- int r, is_num;
- OnigCodePoint c = 0;
- OnigCodePoint first_code;
- OnigEncoding enc = env->enc;
- UChar *name_end;
- UChar *p = *src;
- PFETCH_READY;
-
- name_end = end;
- r = 0;
- is_num = 0;
- if (PEND) {
- return ONIGERR_EMPTY_GROUP_NAME;
- }
- else {
- PFETCH(c);
- first_code = c;
- if (c == '>')
- return ONIGERR_EMPTY_GROUP_NAME;
-
- if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
- if (ref == 1)
- is_num = 1;
- else {
- r = ONIGERR_INVALID_GROUP_NAME;
- }
- }
- else if (!ONIGENC_IS_CODE_WORD(enc, c)) {
- r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
- }
- }
-
- while (!PEND) {
- name_end = p;
- PFETCH(c);
- if (c == '>' || c == ')') break;
-
- if (is_num == 1) {
- if (! ONIGENC_IS_CODE_DIGIT(enc, c)) {
- if (!ONIGENC_IS_CODE_WORD(enc, c))
- r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
- else
- r = ONIGERR_INVALID_GROUP_NAME;
- }
- }
- else {
- if (!ONIGENC_IS_CODE_WORD(enc, c)) {
- r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
- }
- }
- }
-
- if (c != '>') {
- r = ONIGERR_INVALID_GROUP_NAME;
- name_end = end;
- }
- else {
- if (ONIGENC_IS_CODE_ASCII(first_code) &&
- ONIGENC_IS_CODE_UPPER(enc, first_code))
- r = ONIGERR_INVALID_GROUP_NAME;
- }
-
- if (r == 0) {
- *rname_end = name_end;
- *src = p;
- return 0;
- }
- else {
- onig_scan_env_set_error_string(env, r, *src, name_end);
- return r;
- }
-}
-#else
-static int
-fetch_name(UChar** src, UChar* end, UChar** rname_end, ScanEnv* env, int ref)
-{
- int r, len;
- OnigCodePoint c = 0;
- UChar *name_end;
- OnigEncoding enc = env->enc;
- UChar *p = *src;
- PFETCH_READY;
-
- r = 0;
- while (!PEND) {
- name_end = p;
- if (enc_len(enc, p) > 1)
- r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
-
- PFETCH(c);
- if (c == '>' || c == ')') break;
- if (! ONIGENC_IS_CODE_DIGIT(enc, c))
- r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
- }
- if (c != '>') {
- r = ONIGERR_INVALID_GROUP_NAME;
- name_end = end;
- }
-
- if (r == 0) {
- *rname_end = name_end;
- *src = p;
- return 0;
- }
- else {
- err:
- onig_scan_env_set_error_string(env, r, *src, name_end);
- return r;
- }
-}
-#endif
-
-static void
-CC_ESC_WARN(ScanEnv* env, UChar *c)
-{
- if (onig_warn == onig_null_warn) return ;
-
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_CC_OP_NOT_ESCAPED) &&
- IS_SYNTAX_BV(env->syntax, ONIG_SYN_BACKSLASH_ESCAPE_IN_CC)) {
- char buf[WARN_BUFSIZE];
- onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
- env->pattern, env->pattern_end,
- "character class has '%s' without escape", c);
- (*onig_warn)(buf);
- }
-}
-
-static void
-CCEND_ESC_WARN(ScanEnv* env, UChar* c)
-{
- if (onig_warn == onig_null_warn) return ;
-
- if (IS_SYNTAX_BV((env)->syntax, ONIG_SYN_WARN_CC_OP_NOT_ESCAPED)) {
- char buf[WARN_BUFSIZE];
- onig_snprintf_with_pattern(buf, WARN_BUFSIZE, (env)->enc,
- (env)->pattern, (env)->pattern_end,
- "regular expression has '%s' without escape", c);
- (*onig_warn)(buf);
- }
-}
-
-static UChar*
-find_str_position(OnigCodePoint s[], int n, UChar* from, UChar* to,
- UChar **next, OnigEncoding enc)
-{
- int i;
- OnigCodePoint x;
- UChar *q;
- UChar *p = from;
-
- while (p < to) {
- x = ONIGENC_MBC_TO_CODE(enc, p, to);
- q = p + enc_len(enc, p);
- if (x == s[0]) {
- for (i = 1; i < n && q < to; i++) {
- x = ONIGENC_MBC_TO_CODE(enc, q, to);
- if (x != s[i]) break;
- q += enc_len(enc, q);
- }
- if (i >= n) {
- if (IS_NOT_NULL(next))
- *next = q;
- return p;
- }
- }
- p = q;
- }
- return NULL_UCHARP;
-}
-
-static int
-str_exist_check_with_esc(OnigCodePoint s[], int n, UChar* from, UChar* to,
- OnigCodePoint bad, OnigEncoding enc)
-{
- int i, in_esc;
- OnigCodePoint x;
- UChar *q;
- UChar *p = from;
-
- in_esc = 0;
- while (p < to) {
- if (in_esc) {
- in_esc = 0;
- p += enc_len(enc, p);
- }
- else {
- x = ONIGENC_MBC_TO_CODE(enc, p, to);
- q = p + enc_len(enc, p);
- if (x == s[0]) {
- for (i = 1; i < n && q < to; i++) {
- x = ONIGENC_MBC_TO_CODE(enc, q, to);
- if (x != s[i]) break;
- q += enc_len(enc, q);
- }
- if (i >= n) return 1;
- p += enc_len(enc, p);
- }
- else {
- x = ONIGENC_MBC_TO_CODE(enc, p, to);
- if (x == bad) return 0;
- else if (x == MC_ESC(enc)) in_esc = 1;
- p = q;
- }
- }
- }
- return 0;
-}
-
-static int
-fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
-{
- int num;
- OnigCodePoint c, c2;
- OnigSyntaxType* syn = env->syntax;
- OnigEncoding enc = env->enc;
- UChar* prev;
- UChar* p = *src;
- PFETCH_READY;
-
- if (PEND) {
- tok->type = TK_EOT;
- return tok->type;
- }
-
- PFETCH(c);
- tok->type = TK_CHAR;
- tok->base = 0;
- tok->u.c = c;
- if (c == ']') {
- tok->type = TK_CC_CLOSE;
- }
- else if (c == '-') {
- tok->type = TK_CC_RANGE;
- }
- else if (c == MC_ESC(enc)) {
- if (! IS_SYNTAX_BV(syn, ONIG_SYN_BACKSLASH_ESCAPE_IN_CC))
- goto end;
-
- if (PEND) return ONIGERR_END_PATTERN_AT_ESCAPE;
-
- PFETCH(c);
- tok->escaped = 1;
- tok->u.c = c;
- switch (c) {
- case 'w':
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_WORD;
- break;
- case 'W':
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_NOT_WORD;
- break;
- case 'd':
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_DIGIT;
- break;
- case 'D':
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_NOT_DIGIT;
- break;
- case 's':
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_WHITE_SPACE;
- break;
- case 'S':
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_NOT_WHITE_SPACE;
- break;
- case 'h':
- if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break;
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_XDIGIT;
- break;
- case 'H':
- if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break;
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_NOT_XDIGIT;
- break;
-
- case 'p':
- case 'P':
- c2 = PPEEK;
- if (c2 == '{' &&
- IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY)) {
- PINC;
- tok->type = TK_CHAR_PROPERTY;
- tok->u.prop.not = (c == 'P' ? 1 : 0);
-
- if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) {
- PFETCH(c2);
- if (c2 == '^') {
- tok->u.prop.not = (tok->u.prop.not == 0 ? 1 : 0);
- }
- else
- PUNFETCH;
- }
- }
- break;
-
- case 'x':
- if (PEND) break;
-
- prev = p;
- if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_BRACE_HEX8)) {
- PINC;
- num = scan_unsigned_hexadecimal_number(&p, end, 8, enc);
- if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
- if (!PEND) {
- c2 = PPEEK;
- if (ONIGENC_IS_CODE_XDIGIT(enc, c2))
- return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
- }
-
- if (p > prev + enc_len(enc, prev) && !PEND && (PPEEK_IS('}'))) {
- PINC;
- tok->type = TK_CODE_POINT;
- tok->base = 16;
- tok->u.code = (OnigCodePoint )num;
- }
- else {
- /* can't read nothing or invalid format */
- p = prev;
- }
- }
- else if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_HEX2)) {
- num = scan_unsigned_hexadecimal_number(&p, end, 2, enc);
- if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
- if (p == prev) { /* can't read nothing. */
- num = 0; /* but, it's not error */
- }
- tok->type = TK_RAW_BYTE;
- tok->base = 16;
- tok->u.c = num;
- }
- break;
-
- case 'u':
- if (PEND) break;
-
- prev = p;
- if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_U_HEX4)) {
- num = scan_unsigned_hexadecimal_number(&p, end, 4, enc);
- if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
- if (p == prev) { /* can't read nothing. */
- num = 0; /* but, it's not error */
- }
- tok->type = TK_CODE_POINT;
- tok->base = 16;
- tok->u.code = (OnigCodePoint )num;
- }
- break;
-
- case '0':
- case '1': case '2': case '3': case '4': case '5': case '6': case '7':
- if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_OCTAL3)) {
- PUNFETCH;
- prev = p;
- num = scan_unsigned_octal_number(&p, end, 3, enc);
- if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
- if (p == prev) { /* can't read nothing. */
- num = 0; /* but, it's not error */
- }
- tok->type = TK_RAW_BYTE;
- tok->base = 8;
- tok->u.c = num;
- }
- break;
-
- default:
- PUNFETCH;
- num = fetch_escaped_value(&p, end, env);
- if (num < 0) return num;
- if (tok->u.c != num) {
- tok->u.code = (OnigCodePoint )num;
- tok->type = TK_CODE_POINT;
- }
- break;
- }
- }
- else if (c == '[') {
- if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_POSIX_BRACKET) && (PPEEK_IS(':'))) {
- OnigCodePoint send[] = { (OnigCodePoint )':', (OnigCodePoint )']' };
- tok->backp = p; /* point at '[' is readed */
- PINC;
- if (str_exist_check_with_esc(send, 2, p, end,
- (OnigCodePoint )']', enc)) {
- tok->type = TK_POSIX_BRACKET_OPEN;
- }
- else {
- PUNFETCH;
- goto cc_in_cc;
- }
- }
- else {
- cc_in_cc:
- if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_CCLASS_SET_OP)) {
- tok->type = TK_CC_CC_OPEN;
- }
- else {
- CC_ESC_WARN(env, "[");
- }
- }
- }
- else if (c == '&') {
- if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_CCLASS_SET_OP) &&
- !PEND && (PPEEK_IS('&'))) {
- PINC;
- tok->type = TK_CC_AND;
- }
- }
-
- end:
- *src = p;
- return tok->type;
-}
-
-static int
-fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
-{
- int r, num;
- OnigCodePoint c;
- OnigEncoding enc = env->enc;
- OnigSyntaxType* syn = env->syntax;
- UChar* prev;
- UChar* p = *src;
- PFETCH_READY;
-
- start:
- if (PEND) {
- tok->type = TK_EOT;
- return tok->type;
- }
-
- tok->type = TK_STRING;
- tok->base = 0;
- tok->backp = p;
-
- PFETCH(c);
- if (c == MC_ESC(enc)) {
- if (PEND) return ONIGERR_END_PATTERN_AT_ESCAPE;
-
- tok->backp = p;
- PFETCH(c);
-
- tok->u.c = c;
- tok->escaped = 1;
- switch (c) {
- case '*':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_ASTERISK_ZERO_INF)) break;
- tok->type = TK_OP_REPEAT;
- tok->u.repeat.lower = 0;
- tok->u.repeat.upper = REPEAT_INFINITE;
- goto greedy_check;
- break;
-
- case '+':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_PLUS_ONE_INF)) break;
- tok->type = TK_OP_REPEAT;
- tok->u.repeat.lower = 1;
- tok->u.repeat.upper = REPEAT_INFINITE;
- goto greedy_check;
- break;
-
- case '?':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_QMARK_ZERO_ONE)) break;
- tok->type = TK_OP_REPEAT;
- tok->u.repeat.lower = 0;
- tok->u.repeat.upper = 1;
- greedy_check:
- if (!PEND && PPEEK_IS('?') &&
- IS_SYNTAX_OP(syn, ONIG_SYN_OP_QMARK_NON_GREEDY)) {
- PFETCH(c);
- tok->u.repeat.greedy = 0;
- tok->u.repeat.possessive = 0;
- }
- else {
- possessive_check:
- if (!PEND && PPEEK_IS('+') &&
- ((IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT) &&
- tok->type != TK_INTERVAL) ||
- (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL) &&
- tok->type == TK_INTERVAL))) {
- PFETCH(c);
- tok->u.repeat.greedy = 1;
- tok->u.repeat.possessive = 1;
- }
- else {
- tok->u.repeat.greedy = 1;
- tok->u.repeat.possessive = 0;
- }
- }
- break;
-
- case '{':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_BRACE_INTERVAL)) break;
- r = fetch_range_qualifier(&p, end, tok, env);
- if (r < 0) return r; /* error */
- if (r == 0) goto greedy_check;
- else if (r == 2) { /* {n} */
- if (IS_SYNTAX_BV(syn, ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY))
- goto possessive_check;
-
- goto greedy_check;
- }
- /* r == 1 : normal char */
- break;
-
- case '|':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_VBAR_ALT)) break;
- tok->type = TK_ALT;
- break;
-
- case '(':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_LPAREN_SUBEXP)) break;
- tok->type = TK_SUBEXP_OPEN;
- break;
-
- case ')':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_LPAREN_SUBEXP)) break;
- tok->type = TK_SUBEXP_CLOSE;
- break;
-
- case 'w':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_W_WORD)) break;
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_WORD;
- break;
-
- case 'W':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_W_WORD)) break;
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_NOT_WORD;
- break;
-
- case 'b':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_B_WORD_BOUND)) break;
- tok->type = TK_ANCHOR;
- tok->u.anchor = ANCHOR_WORD_BOUND;
- break;
-
- case 'B':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_B_WORD_BOUND)) break;
- tok->type = TK_ANCHOR;
- tok->u.anchor = ANCHOR_NOT_WORD_BOUND;
- break;
-
-#ifdef USE_WORD_BEGIN_END
- case '<':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END)) break;
- tok->type = TK_ANCHOR;
- tok->u.anchor = ANCHOR_WORD_BEGIN;
- break;
-
- case '>':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END)) break;
- tok->type = TK_ANCHOR;
- tok->u.anchor = ANCHOR_WORD_END;
- break;
-#endif
-
- case 's':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_S_WHITE_SPACE)) break;
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_WHITE_SPACE;
- break;
-
- case 'S':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_S_WHITE_SPACE)) break;
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_NOT_WHITE_SPACE;
- break;
-
- case 'd':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_D_DIGIT)) break;
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_DIGIT;
- break;
-
- case 'D':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_D_DIGIT)) break;
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_NOT_DIGIT;
- break;
-
- case 'h':
- if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break;
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_XDIGIT;
- break;
-
- case 'H':
- if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break;
- tok->type = TK_CHAR_TYPE;
- tok->u.subtype = CTYPE_NOT_XDIGIT;
- break;
-
- case 'A':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR)) break;
- begin_buf:
- tok->type = TK_ANCHOR;
- tok->u.subtype = ANCHOR_BEGIN_BUF;
- break;
-
- case 'Z':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR)) break;
- tok->type = TK_ANCHOR;
- tok->u.subtype = ANCHOR_SEMI_END_BUF;
- break;
-
- case 'z':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR)) break;
- end_buf:
- tok->type = TK_ANCHOR;
- tok->u.subtype = ANCHOR_END_BUF;
- break;
-
- case 'G':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_CAPITAL_G_BEGIN_ANCHOR)) break;
- tok->type = TK_ANCHOR;
- tok->u.subtype = ANCHOR_BEGIN_POSITION;
- break;
-
- case '`':
- if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR)) break;
- goto begin_buf;
- break;
-
- case '\'':
- if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR)) break;
- goto end_buf;
- break;
-
- case 'x':
- if (PEND) break;
-
- prev = p;
- if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_BRACE_HEX8)) {
- PINC;
- num = scan_unsigned_hexadecimal_number(&p, end, 8, enc);
- if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
- if (!PEND) {
- if (ONIGENC_IS_CODE_XDIGIT(enc, PPEEK))
- return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
- }
-
- if ((p > prev + enc_len(enc, prev)) && !PEND && PPEEK_IS('}')) {
- PINC;
- tok->type = TK_CODE_POINT;
- tok->u.code = (OnigCodePoint )num;
- }
- else {
- /* can't read nothing or invalid format */
- p = prev;
- }
- }
- else if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_HEX2)) {
- num = scan_unsigned_hexadecimal_number(&p, end, 2, enc);
- if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
- if (p == prev) { /* can't read nothing. */
- num = 0; /* but, it's not error */
- }
- tok->type = TK_RAW_BYTE;
- tok->base = 16;
- tok->u.c = num;
- }
- break;
-
- case 'u':
- if (PEND) break;
-
- prev = p;
- if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_U_HEX4)) {
- num = scan_unsigned_hexadecimal_number(&p, end, 4, enc);
- if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
- if (p == prev) { /* can't read nothing. */
- num = 0; /* but, it's not error */
- }
- tok->type = TK_CODE_POINT;
- tok->base = 16;
- tok->u.code = (OnigCodePoint )num;
- }
- break;
-
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- PUNFETCH;
- prev = p;
- num = onig_scan_unsigned_number(&p, end, enc);
- if (num < 0 || num > ONIG_MAX_BACKREF_NUM) {
- goto skip_backref;
- }
-
- if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_DECIMAL_BACKREF) &&
- (num <= env->num_mem || num <= 9)) { /* This spec. from GNU regex */
- if (IS_SYNTAX_BV(syn, ONIG_SYN_STRICT_CHECK_BACKREF)) {
- if (num > env->num_mem || IS_NULL(SCANENV_MEM_NODES(env)[num]))
- return ONIGERR_INVALID_BACKREF;
- }
-
- tok->type = TK_BACKREF;
- tok->u.backref.num = 1;
- tok->u.backref.ref1 = num;
- tok->u.backref.by_name = 0;
- break;
- }
-
- skip_backref:
- if (c == '8' || c == '9') {
- /* normal char */
- p = prev; PINC;
- break;
- }
-
- p = prev;
- /* fall through */
- case '0':
- if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_OCTAL3)) {
- prev = p;
- num = scan_unsigned_octal_number(&p, end, (c == '0' ? 2:3), enc);
- if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
- if (p == prev) { /* can't read nothing. */
- num = 0; /* but, it's not error */
- }
- tok->type = TK_RAW_BYTE;
- tok->base = 8;
- tok->u.c = num;
- }
- else if (c != '0') {
- PINC;
- }
- break;
-
-#ifdef USE_NAMED_GROUP
- case 'k':
- if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_K_NAMED_BACKREF)) {
- PFETCH(c);
- if (c == '<') {
- UChar* name_end;
- int* backs;
-
- prev = p;
- r = fetch_name(&p, end, &name_end, env, 1);
- if (r < 0) return r;
- num = onig_name_to_group_numbers(env->reg, prev, name_end, &backs);
- if (num <= 0) {
- onig_scan_env_set_error_string(env,
- ONIGERR_UNDEFINED_NAME_REFERENCE, prev, name_end);
- return ONIGERR_UNDEFINED_NAME_REFERENCE;
- }
- if (IS_SYNTAX_BV(syn, ONIG_SYN_STRICT_CHECK_BACKREF)) {
- int i;
- for (i = 0; i < num; i++) {
- if (backs[i] > env->num_mem ||
- IS_NULL(SCANENV_MEM_NODES(env)[backs[i]]))
- return ONIGERR_INVALID_BACKREF;
- }
- }
-
- tok->type = TK_BACKREF;
- tok->u.backref.by_name = 1;
- if (num == 1) {
- tok->u.backref.num = 1;
- tok->u.backref.ref1 = backs[0];
- }
- else {
- tok->u.backref.num = num;
- tok->u.backref.refs = backs;
- }
- }
- else
- PUNFETCH;
- }
- break;
-#endif
-
-#ifdef USE_SUBEXP_CALL
- case 'g':
- if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_G_SUBEXP_CALL)) {
- PFETCH(c);
- if (c == '<') {
- UChar* name_end;
-
- prev = p;
- r = fetch_name(&p, end, &name_end, env, 1);
- if (r < 0) return r;
-
- tok->type = TK_CALL;
- tok->u.call.name = prev;
- tok->u.call.name_end = name_end;
- }
- else
- PUNFETCH;
- }
- break;
-#endif
-
- case 'Q':
- if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE)) {
- tok->type = TK_QUOTE_OPEN;
- }
- break;
-
- case 'p':
- case 'P':
- if (PPEEK_IS('{') &&
- IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY)) {
- PINC;
- tok->type = TK_CHAR_PROPERTY;
- tok->u.prop.not = (c == 'P' ? 1 : 0);
-
- if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) {
- PFETCH(c);
- if (c == '^') {
- tok->u.prop.not = (tok->u.prop.not == 0 ? 1 : 0);
- }
- else
- PUNFETCH;
- }
- }
- break;
-
- default:
- PUNFETCH;
- num = fetch_escaped_value(&p, end, env);
- if (num < 0) return num;
- /* set_raw: */
- if (tok->u.c != num) {
- tok->type = TK_CODE_POINT;
- tok->u.code = (OnigCodePoint )num;
- }
- else { /* string */
- p = tok->backp + enc_len(enc, tok->backp);
- }
- break;
- }
- }
- else {
- tok->u.c = c;
- tok->escaped = 0;
-
-#ifdef USE_VARIABLE_META_CHARS
- if ((c != ONIG_INEFFECTIVE_META_CHAR) &&
- IS_SYNTAX_OP(syn, ONIG_SYN_OP_VARIABLE_META_CHARACTERS)) {
- if (c == MC_ANYCHAR(enc))
- goto any_char;
- else if (c == MC_ANYTIME(enc))
- goto anytime;
- else if (c == MC_ZERO_OR_ONE_TIME(enc))
- goto zero_or_one_time;
- else if (c == MC_ONE_OR_MORE_TIME(enc))
- goto one_or_more_time;
- else if (c == MC_ANYCHAR_ANYTIME(enc)) {
- tok->type = TK_ANYCHAR_ANYTIME;
- goto out;
- }
- }
-#endif
-
- switch (c) {
- case '.':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_DOT_ANYCHAR)) break;
- any_char:
- tok->type = TK_ANYCHAR;
- break;
-
- case '*':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ASTERISK_ZERO_INF)) break;
- anytime:
- tok->type = TK_OP_REPEAT;
- tok->u.repeat.lower = 0;
- tok->u.repeat.upper = REPEAT_INFINITE;
- goto greedy_check;
- break;
-
- case '+':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_PLUS_ONE_INF)) break;
- one_or_more_time:
- tok->type = TK_OP_REPEAT;
- tok->u.repeat.lower = 1;
- tok->u.repeat.upper = REPEAT_INFINITE;
- goto greedy_check;
- break;
-
- case '?':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_QMARK_ZERO_ONE)) break;
- zero_or_one_time:
- tok->type = TK_OP_REPEAT;
- tok->u.repeat.lower = 0;
- tok->u.repeat.upper = 1;
- goto greedy_check;
- break;
-
- case '{':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_BRACE_INTERVAL)) break;
- r = fetch_range_qualifier(&p, end, tok, env);
- if (r < 0) return r; /* error */
- if (r == 0) goto greedy_check;
- else if (r == 2) { /* {n} */
- if (IS_SYNTAX_BV(syn, ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY))
- goto possessive_check;
-
- goto greedy_check;
- }
- /* r == 1 : normal char */
- break;
-
- case '|':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_VBAR_ALT)) break;
- tok->type = TK_ALT;
- break;
-
- case '(':
- if (PPEEK_IS('?') &&
- IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) {
- PINC;
- if (PPEEK_IS('#')) {
- PFETCH(c);
- while (1) {
- if (PEND) return ONIGERR_END_PATTERN_IN_GROUP;
- PFETCH(c);
- if (c == MC_ESC(enc)) {
- if (!PEND) PFETCH(c);
- }
- else {
- if (c == ')') break;
- }
- }
- goto start;
- }
- PUNFETCH;
- }
-
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LPAREN_SUBEXP)) break;
- tok->type = TK_SUBEXP_OPEN;
- break;
-
- case ')':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LPAREN_SUBEXP)) break;
- tok->type = TK_SUBEXP_CLOSE;
- break;
-
- case '^':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LINE_ANCHOR)) break;
- tok->type = TK_ANCHOR;
- tok->u.subtype = (IS_SINGLELINE(env->option)
- ? ANCHOR_BEGIN_BUF : ANCHOR_BEGIN_LINE);
- break;
-
- case '$':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LINE_ANCHOR)) break;
- tok->type = TK_ANCHOR;
- tok->u.subtype = (IS_SINGLELINE(env->option)
- ? ANCHOR_END_BUF : ANCHOR_END_LINE);
- break;
-
- case '[':
- if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_BRACKET_CC)) break;
- tok->type = TK_CC_OPEN;
- break;
-
- case ']':
- if (*src > env->pattern) /* /].../ is allowed. */
- CCEND_ESC_WARN(env, "]");
- break;
-
- case '#':
- if (IS_EXTEND(env->option)) {
- while (!PEND) {
- PFETCH(c);
- if (ONIGENC_IS_CODE_NEWLINE(enc, c))
- break;
- }
- goto start;
- break;
- }
- break;
-
- case ' ': case '\t': case '\n': case '\r': case '\f':
- if (IS_EXTEND(env->option))
- goto start;
- break;
-
- default:
- /* string */
- break;
- }
- }
-
- out:
- *src = p;
- return tok->type;
-}
-
-static int
-add_ctype_to_cc_by_range(CClassNode* cc, int ctype, int not, OnigEncoding enc,
- OnigCodePoint sbr[], OnigCodePoint mbr[])
-{
- int i, r;
- OnigCodePoint j;
-
- int nsb = ONIGENC_CODE_RANGE_NUM(sbr);
- int nmb = ONIGENC_CODE_RANGE_NUM(mbr);
-
- if (not == 0) {
- for (i = 0; i < nsb; i++) {
- for (j = ONIGENC_CODE_RANGE_FROM(sbr, i);
- j <= ONIGENC_CODE_RANGE_TO(sbr, i); j++) {
- BITSET_SET_BIT(cc->bs, j);
- }
- }
-
- for (i = 0; i < nmb; i++) {
- r = add_code_range_to_buf(&(cc->mbuf),
- ONIGENC_CODE_RANGE_FROM(mbr, i),
- ONIGENC_CODE_RANGE_TO(mbr, i));
- if (r != 0) return r;
- }
- }
- else {
- OnigCodePoint prev = 0;
-
- if (ONIGENC_MBC_MINLEN(enc) == 1) {
- for (i = 0; i < nsb; i++) {
- for (j = prev;
- j < ONIGENC_CODE_RANGE_FROM(sbr, i); j++) {
- BITSET_SET_BIT(cc->bs, j);
- }
- prev = ONIGENC_CODE_RANGE_TO(sbr, i) + 1;
- }
- if (prev < 0x7f) {
- for (j = prev; j < 0x7f; j++) {
- BITSET_SET_BIT(cc->bs, j);
- }
- }
-
- prev = 0x80;
- }
-
- for (i = 0; i < nmb; i++) {
- if (prev < ONIGENC_CODE_RANGE_FROM(mbr, i)) {
- r = add_code_range_to_buf(&(cc->mbuf), prev,
- ONIGENC_CODE_RANGE_FROM(mbr, i) - 1);
- if (r != 0) return r;
- }
- prev = ONIGENC_CODE_RANGE_TO(mbr, i) + 1;
- }
- if (prev < 0x7fffffff) {
- r = add_code_range_to_buf(&(cc->mbuf), prev, 0x7fffffff);
- if (r != 0) return r;
- }
- }
-
- return 0;
-}
-
-static int
-add_ctype_to_cc(CClassNode* cc, int ctype, int not, ScanEnv* env)
-{
- int c, r;
- OnigCodePoint *sbr, *mbr;
- OnigEncoding enc = env->enc;
-
- r = ONIGENC_GET_CTYPE_CODE_RANGE(enc, ctype, &sbr, &mbr);
- if (r == 0) {
- return add_ctype_to_cc_by_range(cc, ctype, not, env->enc, sbr, mbr);
- }
- else if (r != ONIG_NO_SUPPORT_CONFIG) {
- return r;
- }
-
- r = 0;
- switch (ctype) {
- case ONIGENC_CTYPE_ALPHA:
- case ONIGENC_CTYPE_BLANK:
- case ONIGENC_CTYPE_CNTRL:
- case ONIGENC_CTYPE_DIGIT:
- case ONIGENC_CTYPE_LOWER:
- case ONIGENC_CTYPE_PUNCT:
- case ONIGENC_CTYPE_SPACE:
- case ONIGENC_CTYPE_UPPER:
- case ONIGENC_CTYPE_XDIGIT:
- case ONIGENC_CTYPE_ASCII:
- case ONIGENC_CTYPE_ALNUM:
- if (not != 0) {
- for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
- if (! ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
- BITSET_SET_BIT(cc->bs, c);
- }
- ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
- }
- else {
- for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
- if (ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
- BITSET_SET_BIT(cc->bs, c);
- }
- }
- break;
-
- case ONIGENC_CTYPE_GRAPH:
- case ONIGENC_CTYPE_PRINT:
- if (not != 0) {
- for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
- if (! ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
- BITSET_SET_BIT(cc->bs, c);
- }
- }
- else {
- for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
- if (ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
- BITSET_SET_BIT(cc->bs, c);
- }
- ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
- }
- break;
-
- case ONIGENC_CTYPE_WORD:
- if (not == 0) {
- for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
- if (ONIGENC_IS_CODE_SB_WORD(enc, c)) BITSET_SET_BIT(cc->bs, c);
- }
- ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
- }
- else {
- for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
- if ((ONIGENC_CODE_TO_MBCLEN(enc, c) > 0) /* 0: invalid code point */
- && ! ONIGENC_IS_CODE_WORD(enc, c))
- BITSET_SET_BIT(cc->bs, c);
- }
- }
- break;
-
- default:
- return ONIGERR_PARSER_BUG;
- break;
- }
-
- return r;
-}
-
-static int
-parse_ctype_to_enc_ctype(int pctype, int* not)
-{
- int ctype;
-
- switch (pctype) {
- case CTYPE_WORD:
- ctype = ONIGENC_CTYPE_WORD;
- *not = 0;
- break;
- case CTYPE_NOT_WORD:
- ctype = ONIGENC_CTYPE_WORD;
- *not = 1;
- break;
- case CTYPE_WHITE_SPACE:
- ctype = ONIGENC_CTYPE_SPACE;
- *not = 0;
- break;
- case CTYPE_NOT_WHITE_SPACE:
- ctype = ONIGENC_CTYPE_SPACE;
- *not = 1;
- break;
- case CTYPE_DIGIT:
- ctype = ONIGENC_CTYPE_DIGIT;
- *not = 0;
- break;
- case CTYPE_NOT_DIGIT:
- ctype = ONIGENC_CTYPE_DIGIT;
- *not = 1;
- break;
- case CTYPE_XDIGIT:
- ctype = ONIGENC_CTYPE_XDIGIT;
- *not = 0;
- break;
- case CTYPE_NOT_XDIGIT:
- ctype = ONIGENC_CTYPE_XDIGIT;
- *not = 1;
- break;
- default:
- return ONIGERR_PARSER_BUG;
- break;
- }
- return ctype;
-}
-
-typedef struct {
- UChar *name;
- int ctype;
- short int len;
-} PosixBracketEntryType;
-
-static int
-parse_posix_bracket(CClassNode* cc, UChar** src, UChar* end, ScanEnv* env)
-{
-#define POSIX_BRACKET_CHECK_LIMIT_LENGTH 20
-#define POSIX_BRACKET_NAME_MAX_LEN 6
-
- static PosixBracketEntryType PBS[] = {
- { "alnum", ONIGENC_CTYPE_ALNUM, 5 },
- { "alpha", ONIGENC_CTYPE_ALPHA, 5 },
- { "blank", ONIGENC_CTYPE_BLANK, 5 },
- { "cntrl", ONIGENC_CTYPE_CNTRL, 5 },
- { "digit", ONIGENC_CTYPE_DIGIT, 5 },
- { "graph", ONIGENC_CTYPE_GRAPH, 5 },
- { "lower", ONIGENC_CTYPE_LOWER, 5 },
- { "print", ONIGENC_CTYPE_PRINT, 5 },
- { "punct", ONIGENC_CTYPE_PUNCT, 5 },
- { "space", ONIGENC_CTYPE_SPACE, 5 },
- { "upper", ONIGENC_CTYPE_UPPER, 5 },
- { "xdigit", ONIGENC_CTYPE_XDIGIT, 6 },
- { "ascii", ONIGENC_CTYPE_ASCII, 5 }, /* I don't know origin. Perl? */
- { (UChar* )NULL, -1, 0 }
- };
-
- PosixBracketEntryType *pb;
- int not, i, r;
- OnigCodePoint c;
- OnigEncoding enc = env->enc;
- UChar *p = *src;
- PFETCH_READY;
-
- if (PPEEK_IS('^')) {
- PINC;
- not = 1;
- }
- else
- not = 0;
-
- if (onigenc_strlen(enc, p, end) < POSIX_BRACKET_NAME_MAX_LEN + 2)
- goto not_posix_bracket;
-
- for (pb = PBS; IS_NOT_NULL(pb->name); pb++) {
- if (onigenc_with_ascii_strncmp(enc, p, end, pb->name, pb->len) == 0) {
- p = (UChar* )onigenc_step(enc, p, end, pb->len);
- if (onigenc_with_ascii_strncmp(enc, p, end, ":]", 2) != 0)
- return ONIGERR_INVALID_POSIX_BRACKET_TYPE;
-
- r = add_ctype_to_cc(cc, pb->ctype, not, env);
- if (r != 0) return r;
-
- PINC; PINC;
- *src = p;
- return 0;
- }
- }
-
- not_posix_bracket:
- c = 0;
- i = 0;
- while (!PEND && ((c = PPEEK) != ':') && c != ']') {
- PINC;
- if (++i > POSIX_BRACKET_CHECK_LIMIT_LENGTH) break;
- }
- if (c == ':' && ! PEND) {
- PINC;
- if (! PEND) {
- PFETCH(c);
- if (c == ']')
- return ONIGERR_INVALID_POSIX_BRACKET_TYPE;
- }
- }
-
- return 1; /* 1: is not POSIX bracket, but no error. */
-}
-
-static int
-property_name_to_ctype(UChar* p, UChar* end, OnigEncoding enc)
-{
- static PosixBracketEntryType PBS[] = {
- { "Alnum", ONIGENC_CTYPE_ALNUM, 5 },
- { "Alpha", ONIGENC_CTYPE_ALPHA, 5 },
- { "Blank", ONIGENC_CTYPE_BLANK, 5 },
- { "Cntrl", ONIGENC_CTYPE_CNTRL, 5 },
- { "Digit", ONIGENC_CTYPE_DIGIT, 5 },
- { "Graph", ONIGENC_CTYPE_GRAPH, 5 },
- { "Lower", ONIGENC_CTYPE_LOWER, 5 },
- { "Print", ONIGENC_CTYPE_PRINT, 5 },
- { "Punct", ONIGENC_CTYPE_PUNCT, 5 },
- { "Space", ONIGENC_CTYPE_SPACE, 5 },
- { "Upper", ONIGENC_CTYPE_UPPER, 5 },
- { "XDigit", ONIGENC_CTYPE_XDIGIT, 6 },
- { "ASCII", ONIGENC_CTYPE_ASCII, 5 },
- { (UChar* )NULL, -1, 0 }
- };
-
- PosixBracketEntryType *pb;
- int len;
-
- len = onigenc_strlen(enc, p, end);
- for (pb = PBS; IS_NOT_NULL(pb->name); pb++) {
- if (len == pb->len &&
- onigenc_with_ascii_strncmp(enc, p, end, pb->name, pb->len) == 0)
- return pb->ctype;
- }
-
- return -1;
-}
-
-static int
-fetch_char_property_to_ctype(UChar** src, UChar* end, ScanEnv* env)
-{
- int ctype;
- OnigCodePoint c;
- OnigEncoding enc = env->enc;
- UChar *prev, *start, *p = *src;
- PFETCH_READY;
-
- /* 'IsXXXX' => 'XXXX' */
- if (!PEND &&
- IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_CHAR_PROPERTY_PREFIX_IS)) {
- c = PPEEK;
- if (c == 'I') {
- PINC;
- if (! PEND) {
- c = PPEEK;
- if (c == 's')
- PINC;
- else
- PUNFETCH;
- }
- }
- }
-
- start = prev = p;
-
- while (!PEND) {
- prev = p;
- PFETCH(c);
- if (c == '}') {
- ctype = property_name_to_ctype(start, prev, enc);
- if (ctype < 0) break;
-
- *src = p;
- return ctype;
- }
- else if (c == '(' || c == ')' || c == '{' || c == '|')
- break;
- }
-
- onig_scan_env_set_error_string(env, ONIGERR_INVALID_CHAR_PROPERTY_NAME,
- *src, prev);
- return ONIGERR_INVALID_CHAR_PROPERTY_NAME;
-}
-
-static int
-parse_char_property(Node** np, OnigToken* tok, UChar** src, UChar* end,
- ScanEnv* env)
-{
- int r, ctype;
- CClassNode* cc;
-
- ctype = fetch_char_property_to_ctype(src, end, env);
- if (ctype < 0) return ctype;
-
- *np = node_new_cclass();
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- cc = &(NCCLASS(*np));
- r = add_ctype_to_cc(cc, ctype, 0, env);
- if (r != 0) return r;
- if (tok->u.prop.not != 0) CCLASS_SET_NOT(cc);
-
- return 0;
-}
-
-
-enum CCSTATE {
- CCS_VALUE,
- CCS_RANGE,
- CCS_COMPLETE,
- CCS_START
-};
-
-enum CCVALTYPE {
- CCV_SB,
- CCV_CODE_POINT,
- CCV_CLASS
-};
-
-static int
-next_state_class(CClassNode* cc, OnigCodePoint* vs, enum CCVALTYPE* type,
- enum CCSTATE* state, ScanEnv* env)
-{
- int r;
-
- if (*state == CCS_RANGE)
- return ONIGERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE;
-
- if (*state == CCS_VALUE && *type != CCV_CLASS) {
- if (*type == CCV_SB)
- BITSET_SET_BIT(cc->bs, (int )(*vs));
- else if (*type == CCV_CODE_POINT) {
- r = add_code_range(&(cc->mbuf), env, *vs, *vs);
- if (r < 0) return r;
- }
- }
-
- *state = CCS_VALUE;
- *type = CCV_CLASS;
- return 0;
-}
-
-static int
-next_state_val(CClassNode* cc, OnigCodePoint *vs, OnigCodePoint v,
- int* vs_israw, int v_israw,
- enum CCVALTYPE intype, enum CCVALTYPE* type,
- enum CCSTATE* state, ScanEnv* env)
-{
- int r;
-
- switch (*state) {
- case CCS_VALUE:
- if (*type == CCV_SB)
- BITSET_SET_BIT(cc->bs, (int )(*vs));
- else if (*type == CCV_CODE_POINT) {
- r = add_code_range(&(cc->mbuf), env, *vs, *vs);
- if (r < 0) return r;
- }
- break;
-
- case CCS_RANGE:
- if (intype == *type) {
- if (intype == CCV_SB) {
- if (*vs > 0xff || v > 0xff)
- return ONIGERR_INVALID_WIDE_CHAR_VALUE;
-
- if (*vs > v) {
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
- goto ccs_range_end;
- else
- return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
- }
- bitset_set_range(cc->bs, (int )*vs, (int )v);
- }
- else {
- r = add_code_range(&(cc->mbuf), env, *vs, v);
- if (r < 0) return r;
- }
- }
- else {
-#if 0
- if (intype == CCV_CODE_POINT && *type == CCV_SB) {
-#endif
- if (*vs > v) {
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
- goto ccs_range_end;
- else
- return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
- }
- bitset_set_range(cc->bs, (int )*vs, (int )(v < 0xff ? v : 0xff));
- r = add_code_range(&(cc->mbuf), env, (OnigCodePoint )*vs, v);
- if (r < 0) return r;
-#if 0
- }
- else
- return ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE;
-#endif
- }
- ccs_range_end:
- *state = CCS_COMPLETE;
- break;
-
- case CCS_COMPLETE:
- case CCS_START:
- *state = CCS_VALUE;
- break;
-
- default:
- break;
- }
-
- *vs_israw = v_israw;
- *vs = v;
- *type = intype;
- return 0;
-}
-
-static int
-code_exist_check(OnigCodePoint c, UChar* from, UChar* end, int ignore_escaped,
- OnigEncoding enc)
-{
- int in_esc;
- OnigCodePoint code;
- UChar* p = from;
- PFETCH_READY;
-
- in_esc = 0;
- while (! PEND) {
- if (ignore_escaped && in_esc) {
- in_esc = 0;
- }
- else {
- PFETCH(code);
- if (code == c) return 1;
- if (code == MC_ESC(enc)) in_esc = 1;
- }
- }
- return 0;
-}
-
-static int
-parse_char_class(Node** np, OnigToken* tok, UChar** src, UChar* end,
- ScanEnv* env)
-{
- int r, neg, len, fetched, and_start;
- OnigCodePoint v, vs;
- UChar *p;
- Node* node;
- CClassNode *cc, *prev_cc;
- CClassNode work_cc;
-
- enum CCSTATE state;
- enum CCVALTYPE val_type, in_type;
- int val_israw, in_israw;
-
- prev_cc = (CClassNode* )NULL;
- *np = NULL_NODE;
- r = fetch_token_in_cc(tok, src, end, env);
- if (r == TK_CHAR && tok->u.c == '^' && tok->escaped == 0) {
- neg = 1;
- r = fetch_token_in_cc(tok, src, end, env);
- }
- else {
- neg = 0;
- }
-
- if (r < 0) return r;
- if (r == TK_CC_CLOSE) {
- if (! code_exist_check((OnigCodePoint )']',
- *src, env->pattern_end, 1, env->enc))
- return ONIGERR_EMPTY_CHAR_CLASS;
-
- CC_ESC_WARN(env, "]");
- r = tok->type = TK_CHAR; /* allow []...] */
- }
-
- *np = node = node_new_cclass();
- CHECK_NULL_RETURN_VAL(node, ONIGERR_MEMORY);
- cc = &(NCCLASS(node));
-
- and_start = 0;
- state = CCS_START;
- p = *src;
- while (r != TK_CC_CLOSE) {
- fetched = 0;
- switch (r) {
- case TK_CHAR:
- len = ONIGENC_CODE_TO_MBCLEN(env->enc, tok->u.c);
- if (len > 1) {
- in_type = CCV_CODE_POINT;
- }
- else {
- sb_char:
- in_type = CCV_SB;
- }
- v = (OnigCodePoint )tok->u.c;
- in_israw = 0;
- goto val_entry2;
- break;
-
- case TK_RAW_BYTE:
- /* tok->base != 0 : octal or hexadec. */
- if (! ONIGENC_IS_SINGLEBYTE(env->enc) && tok->base != 0) {
- UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];
- UChar* bufe = buf + ONIGENC_CODE_TO_MBC_MAXLEN;
- UChar* psave = p;
- int i, base = tok->base;
-
- buf[0] = tok->u.c;
- for (i = 1; i < ONIGENC_MBC_MAXLEN(env->enc); i++) {
- r = fetch_token_in_cc(tok, &p, end, env);
- if (r < 0) goto err;
- if (r != TK_RAW_BYTE || tok->base != base) {
- fetched = 1;
- break;
- }
- buf[i] = tok->u.c;
- }
-
- if (i < ONIGENC_MBC_MINLEN(env->enc)) {
- r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING;
- goto err;
- }
-
- len = enc_len(env->enc, buf);
- if (i < len) {
- r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING;
- goto err;
- }
- else if (i > len) { /* fetch back */
- p = psave;
- for (i = 1; i < len; i++) {
- r = fetch_token_in_cc(tok, &p, end, env);
- }
- fetched = 0;
- }
-
- if (i == 1) {
- v = (OnigCodePoint )buf[0];
- goto raw_single;
- }
- else {
- v = ONIGENC_MBC_TO_CODE(env->enc, buf, bufe);
- in_type = CCV_CODE_POINT;
- }
- }
- else {
- v = (OnigCodePoint )tok->u.c;
- raw_single:
- in_type = CCV_SB;
- }
- in_israw = 1;
- goto val_entry2;
- break;
-
- case TK_CODE_POINT:
- v = tok->u.code;
- in_israw = 1;
- val_entry:
- len = ONIGENC_CODE_TO_MBCLEN(env->enc, v);
- if (len < 0) {
- r = len;
- goto err;
- }
- in_type = (len == 1 ? CCV_SB : CCV_CODE_POINT);
- val_entry2:
- r = next_state_val(cc, &vs, v, &val_israw, in_israw, in_type, &val_type,
- &state, env);
- if (r != 0) goto err;
- break;
-
- case TK_POSIX_BRACKET_OPEN:
- r = parse_posix_bracket(cc, &p, end, env);
- if (r < 0) goto err;
- if (r == 1) { /* is not POSIX bracket */
- CC_ESC_WARN(env, "[");
- p = tok->backp;
- v = (OnigCodePoint )tok->u.c;
- in_israw = 0;
- goto val_entry;
- }
- goto next_class;
- break;
-
- case TK_CHAR_TYPE:
- {
- int ctype, not;
- ctype = parse_ctype_to_enc_ctype(tok->u.subtype, &not);
- r = add_ctype_to_cc(cc, ctype, not, env);
- if (r != 0) return r;
- }
-
- next_class:
- r = next_state_class(cc, &vs, &val_type, &state, env);
- if (r != 0) goto err;
- break;
-
- case TK_CHAR_PROPERTY:
- {
- int ctype;
-
- ctype = fetch_char_property_to_ctype(&p, end, env);
- if (ctype < 0) return ctype;
- r = add_ctype_to_cc(cc, ctype, tok->u.prop.not, env);
- if (r != 0) return r;
- goto next_class;
- }
- break;
-
- case TK_CC_RANGE:
- if (state == CCS_VALUE) {
- r = fetch_token_in_cc(tok, &p, end, env);
- if (r < 0) goto err;
- fetched = 1;
- if (r == TK_CC_CLOSE) { /* allow [x-] */
- range_end_val:
- v = (OnigCodePoint )'-';
- in_israw = 0;
- goto val_entry;
- }
- else if (r == TK_CC_AND) {
- CC_ESC_WARN(env, "-");
- goto range_end_val;
- }
- state = CCS_RANGE;
- }
- else if (state == CCS_START) {
- /* [-xa] is allowed */
- v = (OnigCodePoint )tok->u.c;
- in_israw = 0;
-
- r = fetch_token_in_cc(tok, &p, end, env);
- if (r < 0) goto err;
- fetched = 1;
- /* [--x] or [a&&-x] is warned. */
- if (r == TK_CC_RANGE || and_start != 0)
- CC_ESC_WARN(env, "-");
-
- goto val_entry;
- }
- else if (state == CCS_RANGE) {
- CC_ESC_WARN(env, "-");
- goto sb_char; /* [!--x] is allowed */
- }
- else { /* CCS_COMPLETE */
- r = fetch_token_in_cc(tok, &p, end, env);
- if (r < 0) goto err;
- fetched = 1;
- if (r == TK_CC_CLOSE) goto range_end_val; /* allow [a-b-] */
- else if (r == TK_CC_AND) {
- CC_ESC_WARN(env, "-");
- goto range_end_val;
- }
-
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC)) {
- CC_ESC_WARN(env, "-");
- goto sb_char; /* [0-9-a] is allowed as [0-9\-a] */
- }
- r = ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS;
- goto err;
- }
- break;
-
- case TK_CC_CC_OPEN: /* [ */
- {
- Node *anode;
- CClassNode* acc;
-
- r = parse_char_class(&anode, tok, &p, end, env);
- if (r != 0) goto cc_open_err;
- acc = &(NCCLASS(anode));
- r = or_cclass(cc, acc, env->enc);
-
- onig_node_free(anode);
- cc_open_err:
- if (r != 0) goto err;
- }
- break;
-
- case TK_CC_AND: /* && */
- {
- if (state == CCS_VALUE) {
- r = next_state_val(cc, &vs, 0, &val_israw, 0, val_type,
- &val_type, &state, env);
- if (r != 0) goto err;
- }
- /* initialize local variables */
- and_start = 1;
- state = CCS_START;
-
- if (IS_NOT_NULL(prev_cc)) {
- r = and_cclass(prev_cc, cc, env->enc);
- if (r != 0) goto err;
- bbuf_free(cc->mbuf);
- }
- else {
- prev_cc = cc;
- cc = &work_cc;
- }
- initialize_cclass(cc);
- }
- break;
-
- case TK_EOT:
- r = ONIGERR_PREMATURE_END_OF_CHAR_CLASS;
- goto err;
- break;
- default:
- r = ONIGERR_PARSER_BUG;
- goto err;
- break;
- }
-
- if (fetched)
- r = tok->type;
- else {
- r = fetch_token_in_cc(tok, &p, end, env);
- if (r < 0) goto err;
- }
- }
-
- if (state == CCS_VALUE) {
- r = next_state_val(cc, &vs, 0, &val_israw, 0, val_type,
- &val_type, &state, env);
- if (r != 0) goto err;
- }
-
- if (IS_NOT_NULL(prev_cc)) {
- r = and_cclass(prev_cc, cc, env->enc);
- if (r != 0) goto err;
- bbuf_free(cc->mbuf);
- cc = prev_cc;
- }
-
- if (neg != 0)
- CCLASS_SET_NOT(cc);
- else
- CCLASS_CLEAR_NOT(cc);
- if (IS_CCLASS_NOT(cc) &&
- IS_SYNTAX_BV(env->syntax, ONIG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC)) {
- int is_empty;
-
- is_empty = (IS_NULL(cc->mbuf) ? 1 : 0);
- if (is_empty != 0)
- BITSET_IS_EMPTY(cc->bs, is_empty);
-
- if (is_empty == 0) {
-#define NEWLINE_CODE 0x0a
-
- if (ONIGENC_IS_CODE_NEWLINE(env->enc, NEWLINE_CODE)) {
- if (ONIGENC_CODE_TO_MBCLEN(env->enc, NEWLINE_CODE) == 1)
- BITSET_SET_BIT(cc->bs, NEWLINE_CODE);
- else
- add_code_range(&(cc->mbuf), env, NEWLINE_CODE, NEWLINE_CODE);
- }
- }
- }
- *src = p;
- return 0;
-
- err:
- if (cc != &(NCCLASS(*np)))
- bbuf_free(cc->mbuf);
- onig_node_free(*np);
- return r;
-}
-
-static int parse_subexp(Node** top, OnigToken* tok, int term,
- UChar** src, UChar* end, ScanEnv* env);
-
-static int
-parse_effect(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,
- ScanEnv* env)
-{
- int r, num;
- int list_capture;
- Node *target;
- OnigOptionType option;
- OnigEncoding enc = env->enc;
- OnigCodePoint c;
- UChar* p = *src;
- PFETCH_READY;
-
- *np = NULL;
- if (PEND) return ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS;
-
- option = env->option;
- if (PPEEK_IS('?') &&
- IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) {
- PINC;
- if (PEND) return ONIGERR_END_PATTERN_IN_GROUP;
-
- PFETCH(c);
- switch (c) {
- case ':': /* (?:...) grouping only */
- group:
- r = fetch_token(tok, &p, end, env);
- if (r < 0) return r;
- r = parse_subexp(np, tok, term, &p, end, env);
- if (r < 0) return r;
- *src = p;
- return 1; /* group */
- break;
-
- case '=':
- *np = onig_node_new_anchor(ANCHOR_PREC_READ);
- break;
- case '!': /* preceding read */
- *np = onig_node_new_anchor(ANCHOR_PREC_READ_NOT);
- break;
- case '>': /* (?>...) stop backtrack */
- *np = node_new_effect(EFFECT_STOP_BACKTRACK);
- break;
-
- case '<': /* look behind (?<=...), (?<!...) */
- PFETCH(c);
- if (c == '=')
- *np = onig_node_new_anchor(ANCHOR_LOOK_BEHIND);
- else if (c == '!')
- *np = onig_node_new_anchor(ANCHOR_LOOK_BEHIND_NOT);
-#ifdef USE_NAMED_GROUP
- else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) {
- UChar *name;
- UChar *name_end;
-
- PUNFETCH;
- list_capture = 0;
-
- named_group:
- name = p;
- r = fetch_name(&p, end, &name_end, env, 0);
- if (r < 0) return r;
-
- num = scan_env_add_mem_entry(env);
- if (num < 0) return num;
- if (list_capture != 0 && num >= BIT_STATUS_BITS_NUM)
- return ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY;
-
- r = name_add(env->reg, name, name_end, num, env);
- if (r != 0) return r;
- *np = node_new_effect_memory(env->option, 1);
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- NEFFECT(*np).regnum = num;
- if (list_capture != 0)
- BIT_STATUS_ON_AT_SIMPLE(env->capture_history, num);
- env->num_named++;
- }
-#endif
- else
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- break;
-
- case '@':
- if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY)) {
-#ifdef USE_NAMED_GROUP
- if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) {
- PFETCH(c);
- if (c == '<') {
- list_capture = 1;
- goto named_group; /* (?@<name>...) */
- }
- PUNFETCH;
- }
-#endif
- *np = node_new_effect_memory(env->option, 0);
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- num = scan_env_add_mem_entry(env);
- if (num < 0) {
- onig_node_free(*np);
- return num;
- }
- else if (num >= BIT_STATUS_BITS_NUM) {
- onig_node_free(*np);
- return ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY;
- }
- NEFFECT(*np).regnum = num;
- BIT_STATUS_ON_AT_SIMPLE(env->capture_history, num);
- }
- else {
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- }
- break;
-
-#ifdef USE_POSIXLINE_OPTION
- case 'p':
-#endif
- case '-': case 'i': case 'm': case 's': case 'x':
- {
- int neg = 0;
-
- while (1) {
- switch (c) {
- case ':':
- case ')':
- break;
-
- case '-': neg = 1; break;
- case 'x': ONOFF(option, ONIG_OPTION_EXTEND, neg); break;
- case 'i': ONOFF(option, ONIG_OPTION_IGNORECASE, neg); break;
- case 's':
- if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) {
- ONOFF(option, ONIG_OPTION_MULTILINE, neg);
- }
- else
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- break;
-
- case 'm':
- if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) {
- ONOFF(option, ONIG_OPTION_SINGLELINE, (neg == 0 ? 1 : 0));
- }
- else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) {
- ONOFF(option, ONIG_OPTION_MULTILINE, neg);
- }
- else
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- break;
-#ifdef USE_POSIXLINE_OPTION
- case 'p':
- ONOFF(option, ONIG_OPTION_MULTILINE|ONIG_OPTION_SINGLELINE, neg);
- break;
-#endif
- default:
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- }
-
- if (c == ')') {
- *np = node_new_option(option);
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- *src = p;
- return 2; /* option only */
- }
- else if (c == ':') {
- OnigOptionType prev = env->option;
-
- env->option = option;
- r = fetch_token(tok, &p, end, env);
- if (r < 0) return r;
- r = parse_subexp(&target, tok, term, &p, end, env);
- env->option = prev;
- if (r < 0) return r;
- *np = node_new_option(option);
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- NEFFECT(*np).target = target;
- *src = p;
- return 0;
- }
-
- if (PEND) return ONIGERR_END_PATTERN_IN_GROUP;
- PFETCH(c);
- }
- }
- break;
-
- default:
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- }
- }
- else {
-#ifdef USE_NAMED_GROUP
- if (ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_DONT_CAPTURE_GROUP))
- goto group;
-#endif
- *np = node_new_effect_memory(env->option, 0);
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- num = scan_env_add_mem_entry(env);
- if (num < 0) return num;
- NEFFECT(*np).regnum = num;
- }
-
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- r = fetch_token(tok, &p, end, env);
- if (r < 0) return r;
- r = parse_subexp(&target, tok, term, &p, end, env);
- if (r < 0) return r;
-
- if (NTYPE(*np) == N_ANCHOR)
- NANCHOR(*np).target = target;
- else {
- NEFFECT(*np).target = target;
- if (NEFFECT(*np).type == EFFECT_MEMORY) {
- /* Don't move this to previous of parse_subexp() */
- r = scan_env_set_mem_node(env, NEFFECT(*np).regnum, *np);
- if (r != 0) return r;
- }
- }
-
- *src = p;
- return 0;
-}
-
-static char* PopularQStr[] = {
- "?", "*", "+", "??", "*?", "+?"
-};
-
-static char* ReduceQStr[] = {
- "", "", "*", "*?", "??", "+ and ??", "+? and ?"
-};
-
-static int
-set_qualifier(Node* qnode, Node* target, int group, ScanEnv* env)
-{
- QualifierNode* qn;
-
- qn = &(NQUALIFIER(qnode));
- if (qn->lower == 1 && qn->upper == 1) {
- return 1;
- }
-
- switch (NTYPE(target)) {
- case N_STRING:
- if (! group) {
- StrNode* sn = &(NSTRING(target));
- if (str_node_can_be_split(sn, env->enc)) {
- Node* n = str_node_split_last_char(sn, env->enc);
- if (IS_NOT_NULL(n)) {
- qn->target = n;
- return 2;
- }
- }
- }
- break;
-
- case N_QUALIFIER:
- { /* check redundant double repeat. */
- /* verbose warn (?:.?)? etc... but not warn (.?)? etc... */
- QualifierNode* qnt = &(NQUALIFIER(target));
-
-#ifdef USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR
- if (qn->by_number == 0 && qnt->by_number == 0 &&
- IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT)) {
- int nestq_num, targetq_num;
- char buf[WARN_BUFSIZE];
-
- nestq_num = popular_qualifier_num(qn);
- targetq_num = popular_qualifier_num(qnt);
-
- switch(ReduceTypeTable[targetq_num][nestq_num]) {
- case RQ_ASIS:
- break;
-
- case RQ_DEL:
- if (onig_verb_warn != onig_null_warn) {
- onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
- env->pattern, env->pattern_end,
- "redundant nested repeat operator");
- (*onig_verb_warn)(buf);
- }
- goto warn_exit;
- break;
-
- default:
- if (onig_verb_warn != onig_null_warn) {
- onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
- env->pattern, env->pattern_end,
- "nested repeat operator %s and %s was replaced with '%s'",
- PopularQStr[targetq_num], PopularQStr[nestq_num],
- ReduceQStr[ReduceTypeTable[targetq_num][nestq_num]]);
- (*onig_verb_warn)(buf);
- }
- goto warn_exit;
- break;
- }
- }
-
- warn_exit:
-#endif
- if (popular_qualifier_num(qnt) >= 0 && popular_qualifier_num(qn) >= 0) {
- onig_reduce_nested_qualifier(qnode, target);
- goto q_exit;
- }
- }
- break;
-
- default:
- break;
- }
-
- qn->target = target;
- q_exit:
- return 0;
-}
-
-static int
-make_compound_alt_node_from_cc(OnigAmbigType ambig_flag, OnigEncoding enc,
- CClassNode* cc, Node** root)
-{
- int r, i, j, k, clen, len, ncode, n;
- UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];
- Node **ptail, *snode = NULL_NODE;
- OnigCompAmbigCodes* ccs;
- OnigCompAmbigCodeItem* ci;
- OnigAmbigType amb;
-
- n = 0;
- *root = NULL_NODE;
- ptail = root;
-
-
- for (amb = 0x01; amb <= ONIGENC_AMBIGUOUS_MATCH_LIMIT; amb <<= 1) {
- if ((amb & ambig_flag) == 0) continue;
-
- ncode = ONIGENC_GET_ALL_COMP_AMBIG_CODES(enc, amb, &ccs);
- for (i = 0; i < ncode; i++) {
- if (onig_is_code_in_cc(enc, ccs[i].code, cc)) {
- for (j = 0; j < ccs[i].n; j++) {
- ci = &(ccs[i].items[j]);
- if (ci->len > 1) { /* compound only */
- if (IS_CCLASS_NOT(cc)) clear_not_flag_cclass(cc, enc);
-
- clen = ci->len;
- for (k = 0; k < clen; k++) {
- len = ONIGENC_CODE_TO_MBC(enc, ci->code[k], buf);
-
- if (k == 0) {
- snode = node_new_str_raw(buf, buf + len);
- CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY);
- }
- else {
- r = onig_node_str_cat(snode, buf, buf + len);
- if (r < 0) return r;
- }
- }
-
- *ptail = node_new_alt(snode, NULL_NODE);
- CHECK_NULL_RETURN_VAL(*ptail, ONIGERR_MEMORY);
- ptail = &(NCONS(*ptail).right);
- n++;
- }
- }
- }
- }
- }
-
- return n;
-}
-
-
-#ifdef USE_SHARED_CCLASS_TABLE
-
-#define THRESHOLD_RANGE_NUM_FOR_SHARE_CCLASS 8
-
-/* for ctype node hash table */
-
-typedef struct {
- OnigEncoding enc;
- int not;
- int type;
-} type_cclass_key;
-
-static int type_cclass_cmp(type_cclass_key* x, type_cclass_key* y)
-{
- if (x->type != y->type) return 1;
- if (x->enc != y->enc) return 1;
- if (x->not != y->not) return 1;
- return 0;
-}
-
-static int type_cclass_hash(type_cclass_key* key)
-{
- int i, val;
- unsigned char *p;
-
- val = 0;
-
- p = (unsigned char* )&(key->enc);
- for (i = 0; i < sizeof(key->enc); i++) {
- val = val * 997 + (int )*p++;
- }
-
- p = (unsigned char* )(&key->type);
- for (i = 0; i < sizeof(key->type); i++) {
- val = val * 997 + (int )*p++;
- }
-
- val += key->not;
- return val + (val >> 5);
-}
-
-static struct st_hash_type type_type_cclass_hash = {
- type_cclass_cmp,
- type_cclass_hash,
-};
-
-static st_table* OnigTypeCClassTable;
-
-
-static int
-i_free_shared_class(type_cclass_key* key, Node* node, void* arg)
-{
- if (IS_NOT_NULL(node)) {
- CClassNode* cc = &(NCCLASS(node));
- if (IS_NOT_NULL(cc->mbuf)) xfree(cc->mbuf);
- xfree(node);
- }
- return ST_DELETE;
-}
-
-extern int
-onig_free_shared_cclass_table()
-{
- if (IS_NOT_NULL(OnigTypeCClassTable)) {
- onig_st_foreach(OnigTypeCClassTable, i_free_shared_class, 0);
- }
-
- return 0;
-}
-
-#endif /* USE_SHARED_CCLASS_TABLE */
-
-
-static int
-parse_exp(Node** np, OnigToken* tok, int term,
- UChar** src, UChar* end, ScanEnv* env)
-{
- int r, len, group = 0;
- Node* qn;
- Node** targetp;
-
- *np = NULL;
- if (tok->type == term)
- goto end_of_token;
-
- switch (tok->type) {
- case TK_ALT:
- case TK_EOT:
- end_of_token:
- *np = node_new_empty();
- return tok->type;
- break;
-
- case TK_SUBEXP_OPEN:
- r = parse_effect(np, tok, TK_SUBEXP_CLOSE, src, end, env);
- if (r < 0) return r;
- if (r == 1) group = 1;
- else if (r == 2) { /* option only */
- Node* target;
- OnigOptionType prev = env->option;
-
- env->option = NEFFECT(*np).option;
- r = fetch_token(tok, src, end, env);
- if (r < 0) return r;
- r = parse_subexp(&target, tok, term, src, end, env);
- env->option = prev;
- if (r < 0) return r;
- NEFFECT(*np).target = target;
- return tok->type;
- }
- break;
-
- case TK_SUBEXP_CLOSE:
- if (! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_UNMATCHED_CLOSE_SUBEXP))
- return ONIGERR_UNMATCHED_CLOSE_PARENTHESIS;
-
- if (tok->escaped) goto tk_raw_byte;
- else goto tk_byte;
- break;
-
- case TK_STRING:
- tk_byte:
- {
- *np = node_new_str(tok->backp, *src);
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
-
- while (1) {
- r = fetch_token(tok, src, end, env);
- if (r < 0) return r;
- if (r != TK_STRING) break;
-
- r = onig_node_str_cat(*np, tok->backp, *src);
- if (r < 0) return r;
- }
-
- string_end:
- targetp = np;
- goto repeat;
- }
- break;
-
- case TK_RAW_BYTE:
- tk_raw_byte:
- {
- *np = node_new_str_raw_char((UChar )tok->u.c);
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- len = 1;
- while (1) {
- r = fetch_token(tok, src, end, env);
- if (r < 0) return r;
- if (r != TK_RAW_BYTE) {
-#ifndef NUMBERED_CHAR_IS_NOT_CASE_AMBIG
- if (len >= enc_len(env->enc, NSTRING(*np).s)) {
- NSTRING_CLEAR_RAW(*np);
- }
-#endif
- goto string_end;
- }
-
- r = node_str_cat_char(*np, (UChar )tok->u.c);
- if (r < 0) return r;
- len++;
- }
- }
- break;
-
- case TK_CODE_POINT:
- {
- UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];
- int num = ONIGENC_CODE_TO_MBC(env->enc, tok->u.code, buf);
- if (num < 0) return num;
-#ifdef NUMBERED_CHAR_IS_NOT_CASE_AMBIG
- *np = node_new_str_raw(buf, buf + num);
-#else
- *np = node_new_str(buf, buf + num);
-#endif
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- }
- break;
-
- case TK_QUOTE_OPEN:
- {
- OnigCodePoint end_op[2];
- UChar *qstart, *qend, *nextp;
-
- end_op[0] = (OnigCodePoint )MC_ESC(env->enc);
- end_op[1] = (OnigCodePoint )'E';
- qstart = *src;
- qend = find_str_position(end_op, 2, qstart, end, &nextp, env->enc);
- if (IS_NULL(qend)) {
- nextp = qend = end;
- }
- *np = node_new_str(qstart, qend);
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- *src = nextp;
- }
- break;
-
- case TK_CHAR_TYPE:
- {
- switch (tok->u.subtype) {
- case CTYPE_WORD:
- case CTYPE_NOT_WORD:
- *np = node_new_ctype(tok->u.subtype);
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- break;
-
- case CTYPE_WHITE_SPACE:
- case CTYPE_NOT_WHITE_SPACE:
- case CTYPE_DIGIT:
- case CTYPE_NOT_DIGIT:
- case CTYPE_XDIGIT:
- case CTYPE_NOT_XDIGIT:
- {
- CClassNode* cc;
- int ctype, not;
-
-#ifdef USE_SHARED_CCLASS_TABLE
- OnigCodePoint *sbr, *mbr;
-
- ctype = parse_ctype_to_enc_ctype(tok->u.subtype, &not);
- r = ONIGENC_GET_CTYPE_CODE_RANGE(env->enc, ctype, &sbr, &mbr);
- if (r == 0 &&
- ONIGENC_CODE_RANGE_NUM(mbr)
- >= THRESHOLD_RANGE_NUM_FOR_SHARE_CCLASS) {
- type_cclass_key key;
- type_cclass_key* new_key;
-
- key.enc = env->enc;
- key.not = not;
- key.type = ctype;
-
- THREAD_ATOMIC_START;
-
- if (IS_NULL(OnigTypeCClassTable)) {
- OnigTypeCClassTable
- = onig_st_init_table_with_size(&type_type_cclass_hash, 10);
- if (IS_NULL(OnigTypeCClassTable)) {
- THREAD_ATOMIC_END;
- return ONIGERR_MEMORY;
- }
- }
- else {
- if (onig_st_lookup(OnigTypeCClassTable, (st_data_t )&key,
- (st_data_t* )np)) {
- THREAD_ATOMIC_END;
- break;
- }
- }
-
- *np = node_new_cclass_by_codepoint_range(not, sbr, mbr);
- if (IS_NULL(*np)) {
- THREAD_ATOMIC_END;
- return ONIGERR_MEMORY;
- }
-
- CCLASS_SET_SHARE(&(NCCLASS(*np)));
- new_key = (type_cclass_key* )xmalloc(sizeof(type_cclass_key));
- onig_st_add_direct(OnigTypeCClassTable, (st_data_t )new_key,
- (st_data_t )*np);
-
- THREAD_ATOMIC_END;
- }
- else {
-#endif
- ctype = parse_ctype_to_enc_ctype(tok->u.subtype, &not);
- *np = node_new_cclass();
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- cc = &(NCCLASS(*np));
- add_ctype_to_cc(cc, ctype, 0, env);
- if (not != 0) CCLASS_SET_NOT(cc);
-#ifdef USE_SHARED_CCLASS_TABLE
- }
-#endif
- }
- break;
-
- default:
- return ONIGERR_PARSER_BUG;
- break;
- }
- }
- break;
-
- case TK_CHAR_PROPERTY:
- r = parse_char_property(np, tok, src, end, env);
- if (r != 0) return r;
- break;
-
- case TK_CC_OPEN:
- {
- CClassNode* cc;
-
- r = parse_char_class(np, tok, src, end, env);
- if (r != 0) return r;
-
- cc = &(NCCLASS(*np));
-
- if (IS_IGNORECASE(env->option)) {
- int i, n, in_cc;
- OnigPairAmbigCodes* ccs;
- BitSetRef bs = cc->bs;
- OnigAmbigType amb;
-
- for (amb = 0x01; amb <= ONIGENC_AMBIGUOUS_MATCH_LIMIT; amb <<= 1) {
- if ((amb & env->ambig_flag) == 0) continue;
-
- n = ONIGENC_GET_ALL_PAIR_AMBIG_CODES(env->enc, amb, &ccs);
- for (i = 0; i < n; i++) {
- in_cc = onig_is_code_in_cc(env->enc, ccs[i].from, cc);
-
- if ((in_cc != 0 && !IS_CCLASS_NOT(cc)) ||
- (in_cc == 0 && IS_CCLASS_NOT(cc))) {
- if (ONIGENC_MBC_MINLEN(env->enc) > 1 ||
- ccs[i].from >= SINGLE_BYTE_SIZE) {
- /* if (cc->not) clear_not_flag_cclass(cc, env->enc); */
- add_code_range(&(cc->mbuf), env, ccs[i].to, ccs[i].to);
- }
- else {
- if (BITSET_AT(bs, ccs[i].from)) {
- /* /(?i:[^A-C])/.match("a") ==> fail. */
- BITSET_SET_BIT(bs, ccs[i].to);
- }
- if (BITSET_AT(bs, ccs[i].to)) {
- BITSET_SET_BIT(bs, ccs[i].from);
- }
- }
- }
- }
- }
- }
-
- if (IS_IGNORECASE(env->option) &&
- (env->ambig_flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) {
- int res;
- Node *alt_root, *work;
-
- res = make_compound_alt_node_from_cc(env->ambig_flag, env->enc,
- cc, &alt_root);
- if (res < 0) return res;
- if (res > 0) {
- work = node_new_alt(*np, alt_root);
- if (IS_NULL(work)) {
- onig_node_free(alt_root);
- return ONIGERR_MEMORY;
- }
- *np = work;
- }
- }
- }
- break;
-
- case TK_ANYCHAR:
- *np = node_new_anychar();
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- break;
-
- case TK_ANYCHAR_ANYTIME:
- *np = node_new_anychar();
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- qn = node_new_qualifier(0, REPEAT_INFINITE, 0);
- CHECK_NULL_RETURN_VAL(qn, ONIGERR_MEMORY);
- NQUALIFIER(qn).target = *np;
- *np = qn;
- break;
-
- case TK_BACKREF:
- len = tok->u.backref.num;
- *np = node_new_backref(len,
- (len > 1 ? tok->u.backref.refs : &(tok->u.backref.ref1)),
- tok->u.backref.by_name, env);
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- break;
-
-#ifdef USE_SUBEXP_CALL
- case TK_CALL:
- *np = node_new_call(tok->u.call.name, tok->u.call.name_end);
- CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY);
- env->num_call++;
- break;
-#endif
-
- case TK_ANCHOR:
- *np = onig_node_new_anchor(tok->u.anchor);
- break;
-
- case TK_OP_REPEAT:
- case TK_INTERVAL:
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_CONTEXT_INDEP_REPEAT_OPS)) {
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_CONTEXT_INVALID_REPEAT_OPS))
- return ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED;
- else
- *np = node_new_empty();
- }
- else {
- goto tk_byte;
- }
- break;
-
- default:
- return ONIGERR_PARSER_BUG;
- break;
- }
-
- {
- targetp = np;
-
- re_entry:
- r = fetch_token(tok, src, end, env);
- if (r < 0) return r;
-
- repeat:
- if (r == TK_OP_REPEAT || r == TK_INTERVAL) {
- if (is_invalid_qualifier_target(*targetp))
- return ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID;
-
- qn = node_new_qualifier(tok->u.repeat.lower, tok->u.repeat.upper,
- (r == TK_INTERVAL ? 1 : 0));
- CHECK_NULL_RETURN_VAL(qn, ONIGERR_MEMORY);
- NQUALIFIER(qn).greedy = tok->u.repeat.greedy;
- r = set_qualifier(qn, *targetp, group, env);
- if (r < 0) return r;
-
- if (tok->u.repeat.possessive != 0) {
- Node* en;
- en = node_new_effect(EFFECT_STOP_BACKTRACK);
- CHECK_NULL_RETURN_VAL(en, ONIGERR_MEMORY);
- NEFFECT(en).target = qn;
- qn = en;
- }
-
- if (r == 0) {
- *targetp = qn;
- }
- else if (r == 2) { /* split case: /abc+/ */
- Node *tmp;
-
- *targetp = node_new_list(*targetp, NULL);
- CHECK_NULL_RETURN_VAL(*targetp, ONIGERR_MEMORY);
- tmp = NCONS(*targetp).right = node_new_list(qn, NULL);
- CHECK_NULL_RETURN_VAL(tmp, ONIGERR_MEMORY);
- targetp = &(NCONS(tmp).left);
- }
- goto re_entry;
- }
- }
-
- return r;
-}
-
-static int
-parse_branch(Node** top, OnigToken* tok, int term,
- UChar** src, UChar* end, ScanEnv* env)
-{
- int r;
- Node *node, **headp;
-
- *top = NULL;
- r = parse_exp(&node, tok, term, src, end, env);
- if (r < 0) return r;
-
- if (r == TK_EOT || r == term || r == TK_ALT) {
- *top = node;
- }
- else {
- *top = node_new_list(node, NULL);
- headp = &(NCONS(*top).right);
- while (r != TK_EOT && r != term && r != TK_ALT) {
- r = parse_exp(&node, tok, term, src, end, env);
- if (r < 0) return r;
-
- if (NTYPE(node) == N_LIST) {
- *headp = node;
- while (IS_NOT_NULL(NCONS(node).right)) node = NCONS(node).right;
- headp = &(NCONS(node).right);
- }
- else {
- *headp = node_new_list(node, NULL);
- headp = &(NCONS(*headp).right);
- }
- }
- }
-
- return r;
-}
-
-/* term_tok: TK_EOT or TK_SUBEXP_CLOSE */
-static int
-parse_subexp(Node** top, OnigToken* tok, int term,
- UChar** src, UChar* end, ScanEnv* env)
-{
- int r;
- Node *node, **headp;
-
- *top = NULL;
- r = parse_branch(&node, tok, term, src, end, env);
- if (r < 0) {
- onig_node_free(node);
- return r;
- }
-
- if (r == term) {
- *top = node;
- }
- else if (r == TK_ALT) {
- *top = node_new_alt(node, NULL);
- headp = &(NCONS(*top).right);
- while (r == TK_ALT) {
- r = fetch_token(tok, src, end, env);
- if (r < 0) return r;
- r = parse_branch(&node, tok, term, src, end, env);
- if (r < 0) return r;
-
- *headp = node_new_alt(node, NULL);
- headp = &(NCONS(*headp).right);
- }
-
- if (tok->type != term)
- goto err;
- }
- else {
- err:
- if (term == TK_SUBEXP_CLOSE)
- return ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS;
- else
- return ONIGERR_PARSER_BUG;
- }
-
- return r;
-}
-
-static int
-parse_regexp(Node** top, UChar** src, UChar* end, ScanEnv* env)
-{
- int r;
- OnigToken tok;
-
- r = fetch_token(&tok, src, end, env);
- if (r < 0) return r;
- r = parse_subexp(top, &tok, TK_EOT, src, end, env);
- if (r < 0) return r;
- return 0;
-}
-
-extern int
-onig_parse_make_tree(Node** root, const UChar* pattern, const UChar* end, regex_t* reg,
- ScanEnv* env)
-{
- int r;
- UChar* p;
-
-#ifdef USE_NAMED_GROUP
- names_clear(reg);
-#endif
-
- scan_env_clear(env);
- env->option = reg->options;
- env->ambig_flag = reg->ambig_flag;
- env->enc = reg->enc;
- env->syntax = reg->syntax;
- env->pattern = (UChar* )pattern;
- env->pattern_end = (UChar* )end;
- env->reg = reg;
-
- *root = NULL;
- p = (UChar* )pattern;
- r = parse_regexp(root, &p, (UChar* )end, env);
- reg->num_mem = env->num_mem;
- return r;
-}
-
-extern void
-onig_scan_env_set_error_string(ScanEnv* env, int ecode,
- UChar* arg, UChar* arg_end)
-{
- env->error = arg;
- env->error_end = arg_end;
-}
-/**********************************************************************
-
- ruby.c -
-
- $Author: nobu $
- $Date: 2005/05/01 00:13:34 $
- created at: Tue Aug 10 12:47:31 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
-#if defined _WIN32 || defined __CYGWIN__
-#include <windows.h>
-#endif
-#ifdef _WIN32_WCE
-#include <winsock.h>
-#include "wince.h"
-#endif
-#include "ruby.h"
-#include "dln.h"
-#include "node.h"
-#include <stdio.h>
-#include <sys/types.h>
-#include <ctype.h>
-
-#ifdef __hpux
-#include <sys/pstat.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-#ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-#endif
-
-#ifndef HAVE_STRING_H
-char *strchr _((const char*,const char));
-char *strrchr _((const char*,const char));
-char *strstr _((const char*,const char*));
-#endif
-
-#include "util.h"
-
-#ifndef HAVE_STDLIB_H
-char *getenv();
-#endif
-
-VALUE ruby_debug = Qfalse;
-VALUE ruby_verbose = Qfalse;
-static int sflag = 0;
-static int xflag = 0;
-extern int ruby_yydebug;
-
-char *ruby_inplace_mode = Qfalse;
-
-static void load_stdin _((void));
-static void load_file _((const char *, int));
-static void forbid_setid _((const char *));
-
-static VALUE do_loop = Qfalse, do_print = Qfalse;
-static VALUE do_check = Qfalse, do_line = Qfalse;
-static VALUE do_split = Qfalse;
-
-static char *script;
-
-static int origargc;
-static char **origargv;
-
-static void
-usage(name)
- const char *name;
-{
- /* This message really ought to be max 23 lines.
- * Removed -h because the user already knows that option. Others? */
-
- static char *usage_msg[] = {
-"-0[octal] specify record separator (\\0, if no argument)",
-"-a autosplit mode with -n or -p (splits $_ into $F)",
-"-c check syntax only",
-"-Cdirectory cd to directory, before executing your script",
-"-d set debugging flags (set $DEBUG to true)",
-"-e 'command' one line of script. Several -e's allowed. Omit [programfile]",
-"-Fpattern split() pattern for autosplit (-a)",
-"-i[extension] edit ARGV files in place (make backup if extension supplied)",
-"-Idirectory specify $LOAD_PATH directory (may be used more than once)",
-"-Kkcode specifies KANJI (Japanese) code-set",
-"-l enable line ending processing",
-"-n assume 'while gets(); ... end' loop around your script",
-"-p assume loop like -n but print line also like sed",
-"-rlibrary require the library, before executing your script",
-"-s enable some switch parsing for switches after script name",
-"-S look for the script using PATH environment variable",
-"-T[level] turn on tainting checks",
-"-v print version number, then turn on verbose mode",
-"-w turn warnings on for your script",
-"-W[level] set warning level; 0=silence, 1=medium, 2=verbose (default)",
-"-x[directory] strip off text before #!ruby line and perhaps cd to directory",
-"--copyright print the copyright",
-"--version print the version",
-NULL
-};
- char **p = usage_msg;
-
- printf("Usage: %s [switches] [--] [programfile] [arguments]\n", name);
- while (*p)
- printf(" %s\n", *p++);
-}
-
-extern VALUE rb_load_path;
-
-#define STATIC_FILE_LENGTH 255
-
-#if defined _WIN32 || defined __CYGWIN__ || defined __DJGPP__
-static char *
-rubylib_mangle(s, l)
- char *s;
- unsigned int l;
-{
- static char *newp, *oldp;
- static int newl, oldl, notfound;
- static char newsub[STATIC_FILE_LENGTH+1];
-
- if (!newp && !notfound) {
- newp = getenv("RUBYLIB_PREFIX");
- if (newp) {
- char *s;
-
- oldp = newp;
- while (*newp && !ISSPACE(*newp) && *newp != ';') {
- newp++; oldl++; /* Skip digits. */
- }
- while (*newp && (ISSPACE(*newp) || *newp == ';')) {
- newp++; /* Skip whitespace. */
- }
- newl = strlen(newp);
- if (newl == 0 || oldl == 0 || newl > STATIC_FILE_LENGTH) {
- rb_fatal("malformed RUBYLIB_PREFIX");
- }
- strcpy(newsub, newp);
- s = newsub;
- while (*s) {
- if (*s == '\\') *s = '/';
- s++;
- }
- }
- else {
- notfound = 1;
- }
- }
- if (l == 0) {
- l = strlen(s);
- }
- if (!newp || l < oldl || strncasecmp(oldp, s, oldl) != 0) {
- static char ret[STATIC_FILE_LENGTH+1];
- strncpy(ret, s, l);
- ret[l] = 0;
- return ret;
- }
- if (l + newl - oldl > STATIC_FILE_LENGTH || newl > STATIC_FILE_LENGTH) {
- rb_fatal("malformed RUBYLIB_PREFIX");
- }
- strcpy(newsub + newl, s + oldl);
- newsub[l + newl - oldl] = 0;
- return newsub;
-}
-#define rubylib_mangled_path(s, l) rb_str_new2(rubylib_mangle((s), (l)))
-#define rubylib_mangled_path2(s) rb_str_new2(rubylib_mangle((s), 0))
-#else
-#define rubylib_mangled_path(s, l) rb_str_new((s), (l))
-#define rubylib_mangled_path2(s) rb_str_new2(s)
-#endif
-
-void
-ruby_push_include(path, filter)
- const char *path;
- VALUE (*filter)_((VALUE));
-{
- const char sep = PATH_SEP_CHAR;
-
- if (path == 0) return;
-#if defined(__CYGWIN__)
- {
- char rubylib[FILENAME_MAX];
- conv_to_posix_path(path, rubylib, FILENAME_MAX);
- path = rubylib;
- }
-#endif
- if (strchr(path, sep)) {
- const char *p, *s;
- VALUE ary = rb_ary_new();
-
- p = path;
- while (*p) {
- while (*p == sep) p++;
- if ((s = strchr(p, sep)) != 0) {
- rb_ary_push(ary, (*filter)(rubylib_mangled_path(p, (int)(s-p))));
- p = s + 1;
- }
- else {
- rb_ary_push(ary, (*filter)(rubylib_mangled_path2(p)));
- break;
- }
- }
- rb_ary_concat(rb_load_path, ary);
- }
- else {
- rb_ary_push(rb_load_path, (*filter)(rubylib_mangled_path2(path)));
- }
-}
-
-static VALUE
-identical_path(path)
- VALUE path;
-{
- return path;
-}
-
-void
-ruby_incpush(const char *path)
-{
- ruby_push_include(path, identical_path);
-}
-
-static VALUE
-expand_include_path(path)
- VALUE path;
-{
- char *p = RSTRING(path)->ptr;
- if (!p) return path;
- if (*p == '.' && p[1] == '/') return path;
- return rb_file_expand_path(path, Qnil);
-}
-
-
-void
-ruby_incpush_expand(const char *path)
-{
- ruby_push_include(path, expand_include_path);
-}
-
-#if defined DOSISH || defined __CYGWIN__
-#define LOAD_RELATIVE 1
-#endif
-
-#if defined DOSISH || defined __CYGWIN__
-static inline void translate_char _((char *, int, int));
-
-static inline void
-translate_char(p, from, to)
- char *p;
- int from, to;
-{
- while (*p) {
- if ((unsigned char)*p == from)
- *p = to;
-#ifdef CharNext /* defined as CharNext[AW] on Windows. */
- p = CharNext(p);
-#else
- p += mblen(p, RUBY_MBCHAR_MAXSIZE);
-#endif
- }
-}
-#endif
-
-void
-ruby_init_loadpath()
-{
-#if defined LOAD_RELATIVE
- char libpath[MAXPATHLEN+1];
- char *p;
- int rest;
-#if defined _WIN32 || defined __CYGWIN__
- HMODULE libruby = NULL;
- MEMORY_BASIC_INFORMATION m;
-
-#ifndef _WIN32_WCE
- memset(&m, 0, sizeof(m));
- if (VirtualQuery(ruby_init_loadpath, &m, sizeof(m)) && m.State == MEM_COMMIT)
- libruby = (HMODULE)m.AllocationBase;
-#endif
- GetModuleFileName(libruby, libpath, sizeof libpath);
-#elif defined(DJGPP)
- extern char *__dos_argv0;
- strncpy(libpath, __dos_argv0, sizeof(libpath) - 1);
-#elif defined(__human68k__)
- extern char **_argv;
- strncpy(libpath, _argv[0], sizeof(libpath) - 1);
-#elif defined(__EMX__)
- _execname(libpath, sizeof(libpath) - 1);
-#endif
-
- libpath[sizeof(libpath) - 1] = '\0';
-#if defined DOSISH || defined __CYGWIN__
- translate_char(libpath, '\\', '/');
-#endif
- p = strrchr(libpath, '/');
- if (p) {
- *p = 0;
- if (p-libpath > 3 && !strcasecmp(p-4, "/bin")) {
- p -= 4;
- *p = 0;
- }
- }
- else {
- strcpy(libpath, ".");
- p = libpath + 1;
- }
-
- rest = sizeof(libpath) - 1 - (p - libpath);
-
-#define RUBY_RELATIVE(path) (strncpy(p, (path), rest), libpath)
-#else
-#define RUBY_RELATIVE(path) (path)
-#endif
-
- if (rb_safe_level() == 0) {
- ruby_incpush(getenv("RUBYLIB"));
- }
-
-#ifdef RUBY_SEARCH_PATH
- ruby_incpush(RUBY_RELATIVE(RUBY_SEARCH_PATH));
-#endif
-
- ruby_incpush(RUBY_RELATIVE(RUBY_SITE_LIB2));
-#ifdef RUBY_SITE_THIN_ARCHLIB
- ruby_incpush(RUBY_RELATIVE(RUBY_SITE_THIN_ARCHLIB));
-#endif
- ruby_incpush(RUBY_RELATIVE(RUBY_SITE_ARCHLIB));
- ruby_incpush(RUBY_RELATIVE(RUBY_SITE_LIB));
-
- ruby_incpush(RUBY_RELATIVE(RUBY_LIB));
-#ifdef RUBY_THIN_ARCHLIB
- ruby_incpush(RUBY_RELATIVE(RUBY_THIN_ARCHLIB));
-#endif
- ruby_incpush(RUBY_RELATIVE(RUBY_ARCHLIB));
-
- if (rb_safe_level() == 0) {
- ruby_incpush(".");
- }
-}
-
-struct req_list {
- char *name;
- struct req_list *next;
-};
-static struct req_list req_list_head, *req_list_last = &req_list_head;
-
-static void
-add_modules(mod)
- const char *mod;
-{
- struct req_list *list;
-
- list = ALLOC(struct req_list);
- list->name = ALLOC_N(char, strlen(mod)+1);
- strcpy(list->name, mod);
- list->next = 0;
- req_list_last->next = list;
- req_list_last = list;
-}
-
-extern void Init_ext _((void));
-
-static void
-require_libraries()
-{
- extern NODE *ruby_eval_tree;
- NODE *save[3];
- struct req_list *list = req_list_head.next;
- struct req_list *tmp;
-
- save[0] = ruby_eval_tree;
- save[1] = NEW_BEGIN(0);
- ruby_eval_tree = 0;
- ruby_current_node = 0;
- Init_ext(); /* should be called here for some reason :-( */
- ruby_current_node = save[1];
- ruby_set_current_source();
- req_list_last = 0;
- while (list) {
- ruby_current_node = 0;
- rb_require(list->name);
- tmp = list->next;
- free(list->name);
- free(list);
- list = tmp;
- ruby_current_node = save[1];
- ruby_set_current_source();
- }
- req_list_head.next = 0;
- ruby_eval_tree = save[0];
- rb_gc_force_recycle((VALUE)save[1]);
- ruby_current_node = 0;
-}
-
-static void
-process_sflag()
-{
- if (sflag) {
- long n;
- VALUE *args;
-
- n = RARRAY(rb_argv)->len;
- args = RARRAY(rb_argv)->ptr;
- while (n > 0) {
- VALUE v = *args++;
- char *s = StringValuePtr(v);
- char *p;
- int hyphen = Qfalse;
-
- if (s[0] != '-') break;
- n--;
- if (s[1] == '-' && s[2] == '\0') break;
-
- v = Qtrue;
- /* check if valid name before replacing - with _ */
- for (p = s + 1; *p; p++) {
- if (*p == '=') {
- *p++ = '\0';
- v = rb_str_new2(p);
- break;
- }
- if (*p == '-') {
- hyphen = Qtrue;
- }
- else if (*p != '_' && !ISALNUM(*p)) {
- VALUE name_error[2];
- name_error[0] = rb_str_new2("invalid name for global variable - ");
- if (!(p = strchr(p, '='))) {
- rb_str_cat2(name_error[0], s);
- }
- else {
- rb_str_cat(name_error[0], s, p - s);
- }
- name_error[1] = args[-1];
- rb_exc_raise(rb_class_new_instance(2, name_error, rb_eNameError));
- }
- }
- s[0] = '$';
- if (hyphen) {
- for (p = s + 1; *p; ++p) {
- if (*p == '-') *p = '_';
- }
- }
- rb_gv_set(s, v);
- }
- n = RARRAY(rb_argv)->len - n;
- while (n--) {
- rb_ary_shift(rb_argv);
- }
- }
- sflag = 0;
-}
-
-static void proc_options _((int argc, char **argv));
-
-static char*
-moreswitches(s)
- char *s;
-{
- int argc; char *argv[3];
- char *p = s;
-
- argc = 2; argv[0] = argv[2] = 0;
- while (*s && !ISSPACE(*s))
- s++;
- argv[1] = ALLOCA_N(char, s-p+2);
- argv[1][0] = '-';
- strncpy(argv[1]+1, p, s-p);
- argv[1][s-p+1] = '\0';
- proc_options(argc, argv);
- while (*s && ISSPACE(*s))
- s++;
- return s;
-}
-
-NODE *ruby_eval_tree;
-
-static void
-proc_options(argc, argv)
- int argc;
- char **argv;
-{
- char *argv0 = argv[0];
- int do_search;
- char *s;
- NODE *volatile script_node = 0;
-
- int version = 0;
- int copyright = 0;
- int verbose = 0;
- VALUE e_script = Qfalse;
-
- if (argc == 0) return;
-
- do_search = Qfalse;
-
- for (argc--,argv++; argc > 0; argc--,argv++) {
- if (argv[0][0] != '-' || !argv[0][1]) break;
-
- s = argv[0]+1;
- reswitch:
- switch (*s) {
- case 'a':
- do_split = Qtrue;
- s++;
- goto reswitch;
-
- case 'p':
- do_print = Qtrue;
- /* through */
- case 'n':
- do_loop = Qtrue;
- s++;
- goto reswitch;
-
- case 'd':
- ruby_debug = Qtrue;
- ruby_verbose = Qtrue;
- s++;
- goto reswitch;
-
- case 'y':
- ruby_yydebug = 1;
- s++;
- goto reswitch;
-
- case 'v':
- if (argv0 == 0 || verbose) {
- s++;
- goto reswitch;
- }
- ruby_show_version();
- verbose = 1;
- case 'w':
- ruby_verbose = Qtrue;
- s++;
- goto reswitch;
-
- case 'W':
- {
- int numlen;
- int v = 2; /* -W as -W2 */
-
- if (*++s) {
- v = scan_oct(s, 1, &numlen);
- if (numlen == 0) v = 1;
- s += numlen;
- }
- switch (v) {
- case 0:
- ruby_verbose = Qnil; break;
- case 1:
- ruby_verbose = Qfalse; break;
- default:
- ruby_verbose = Qtrue; break;
- }
- }
- goto reswitch;
-
- case 'c':
- do_check = Qtrue;
- s++;
- goto reswitch;
-
- case 's':
- forbid_setid("-s");
- sflag = 1;
- s++;
- goto reswitch;
-
- case 'h':
- usage(origargv[0]);
- exit(0);
-
- case 'l':
- do_line = Qtrue;
- rb_output_rs = rb_rs;
- s++;
- goto reswitch;
-
- case 'S':
- forbid_setid("-S");
- do_search = Qtrue;
- s++;
- goto reswitch;
-
- case 'e':
- forbid_setid("-e");
- if (!*++s) {
- s = argv[1];
- argc--,argv++;
- }
- if (!s) {
- fprintf(stderr, "%s: no code specified for -e\n", origargv[0]);
- exit(2);
- }
- if (!e_script) {
- e_script = rb_str_new(0,0);
- if (script == 0) script = "-e";
- }
- rb_str_cat2(e_script, s);
- rb_str_cat2(e_script, "\n");
- break;
-
- case 'r':
- forbid_setid("-r");
- if (*++s) {
- add_modules(s);
- }
- else if (argv[1]) {
- add_modules(argv[1]);
- argc--,argv++;
- }
- break;
-
- case 'i':
- forbid_setid("-i");
- if (ruby_inplace_mode) free(ruby_inplace_mode);
- ruby_inplace_mode = strdup(s+1);
- break;
-
- case 'x':
- xflag = Qtrue;
- s++;
- if (*s && chdir(s) < 0) {
- rb_fatal("Can't chdir to %s", s);
- }
- break;
-
- case 'C':
- case 'X':
- s++;
- if (!*s) {
- s = argv[1];
- argc--,argv++;
- }
- if (!s || !*s) {
- rb_fatal("Can't chdir");
- }
- if (chdir(s) < 0) {
- rb_fatal("Can't chdir to %s", s);
- }
- break;
-
- case 'F':
- if (*++s) {
- rb_fs = rb_reg_new(s, strlen(s), 0);
- }
- break;
-
- case 'K':
- if (*++s) {
- rb_set_kcode(s);
- s++;
- }
- goto reswitch;
-
- case 'T':
- {
- int numlen;
- int v = 1;
-
- if (*++s) {
- v = scan_oct(s, 2, &numlen);
- if (numlen == 0) v = 1;
- s += numlen;
- }
- rb_set_safe_level(v);
- }
- goto reswitch;
-
- case 'I':
- forbid_setid("-I");
- if (*++s)
- ruby_incpush_expand(s);
- else if (argv[1]) {
- ruby_incpush_expand(argv[1]);
- argc--,argv++;
- }
- break;
-
- case '0':
- {
- int numlen;
- int v;
- char c;
-
- v = scan_oct(s, 4, &numlen);
- s += numlen;
- if (v > 0377) rb_rs = Qnil;
- else if (v == 0 && numlen >= 2) {
- rb_rs = rb_str_new2("\n\n");
- }
- else {
- c = v & 0xff;
- rb_rs = rb_str_new(&c, 1);
- }
- }
- goto reswitch;
-
- case '-':
- if (!s[1] || (s[1] == '\r' && !s[2])) {
- argc--,argv++;
- goto switch_end;
- }
- s++;
- if (strcmp("copyright", s) == 0)
- copyright = 1;
- else if (strcmp("debug", s) == 0) {
- ruby_debug = Qtrue;
- ruby_verbose = Qtrue;
- }
- else if (strcmp("version", s) == 0)
- version = 1;
- else if (strcmp("verbose", s) == 0) {
- verbose = 1;
- ruby_verbose = Qtrue;
- }
- else if (strcmp("yydebug", s) == 0)
- ruby_yydebug = 1;
- else if (strcmp("help", s) == 0) {
- usage(origargv[0]);
- exit(0);
- }
- else {
- fprintf(stderr, "%s: invalid option --%s (-h will show valid options)\n",
- origargv[0], s);
- exit(2);
- }
- break;
-
- case '\r':
- if (!s[1]) break;
-
- default:
- {
- const char *format;
- if (ISPRINT(*s)) {
- format = "%s: invalid option -%c (-h will show valid options)\n";
- }
- else {
- format = "%s: invalid option -\\%03o (-h will show valid options)\n";
- }
- fprintf(stderr, format, origargv[0], (int)(unsigned char)*s);
- }
- exit(2);
-
- case 0:
- break;
- }
- }
-
- switch_end:
- if (argv0 == 0) return;
-
- if (rb_safe_level() == 0 && (s = getenv("RUBYOPT"))) {
- while (ISSPACE(*s)) s++;
- if (*s == 'T' || (*s == '-' && *(s+1) == 'T')) {
- int numlen;
- int v = 1;
-
- if (*s != 'T') ++s;
- if (*++s) {
- v = scan_oct(s, 2, &numlen);
- if (numlen == 0) v = 1;
- }
- rb_set_safe_level(v);
- }
- else {
- while (s && *s) {
- if (*s == '-') {
- s++;
- if (ISSPACE(*s)) {
- do {s++;} while (ISSPACE(*s));
- continue;
- }
- }
- if (!*s) break;
- if (!strchr("IdvwrK", *s))
- rb_raise(rb_eRuntimeError, "illegal switch in RUBYOPT: -%c", *s);
- s = moreswitches(s);
- }
- }
- }
-
- if (version) {
- ruby_show_version();
- exit(0);
- }
- if (copyright) {
- ruby_show_copyright();
- }
-
- if (rb_safe_level() >= 4) {
- OBJ_TAINT(rb_argv);
- OBJ_TAINT(rb_load_path);
- }
-
- if (!e_script) {
- if (argc == 0) { /* no more args */
- if (verbose) exit(0);
- script = "-";
- }
- else {
- script = argv[0];
- if (script[0] == '\0') {
- script = "-";
- }
- else if (do_search) {
- char *path = getenv("RUBYPATH");
-
- script = 0;
- if (path) {
- script = dln_find_file(argv[0], path);
- }
- if (!script) {
- script = dln_find_file(argv[0], getenv(PATH_ENV));
- }
- if (!script) script = argv[0];
- script = ruby_sourcefile = rb_source_filename(script);
- script_node = NEW_BEGIN(0);
- }
-#if defined DOSISH || defined __CYGWIN__
- translate_char(script, '\\', '/');
-#endif
- argc--; argv++;
- }
- }
-
- ruby_script(script);
- ruby_set_argv(argc, argv);
- process_sflag();
-
- ruby_init_loadpath();
- ruby_sourcefile = rb_source_filename(argv0);
- if (e_script) {
- require_libraries();
- ruby_eval_tree = rb_compile_string(script, e_script, 1);
- }
- else if (strlen(script) == 1 && script[0] == '-') {
- load_stdin();
- }
- else {
- load_file(script, 1);
- }
-
- process_sflag();
- xflag = 0;
-
- if (rb_safe_level() >= 4) {
- FL_UNSET(rb_argv, FL_TAINT);
- FL_UNSET(rb_load_path, FL_TAINT);
- }
-}
-
-extern int ruby__end__seen;
-
-static void
-load_file(fname, script)
- const char *fname;
- int script;
-{
- extern VALUE rb_stdin;
- VALUE f;
- int line_start = 1;
-
- if (!fname) rb_load_fail(fname);
- if (strcmp(fname, "-") == 0) {
- f = rb_stdin;
- }
- else {
- FILE *fp = fopen(fname, "r");
-
- if (fp == NULL) {
- rb_load_fail(fname);
- }
- fclose(fp);
-
- f = rb_file_open(fname, "r");
-#if defined DOSISH || defined __CYGWIN__
- {
- char *ext = strrchr(fname, '.');
- if (ext && strcasecmp(ext, ".exe") == 0)
- rb_io_binmode(f);
- }
-#endif
- }
-
- if (script) {
- VALUE c = 1; /* something not nil */
- VALUE line;
- char *p;
-
- if (xflag) {
- forbid_setid("-x");
- xflag = Qfalse;
- while (!NIL_P(line = rb_io_gets(f))) {
- line_start++;
- if (RSTRING(line)->len > 2
- && RSTRING(line)->ptr[0] == '#'
- && RSTRING(line)->ptr[1] == '!') {
- if ((p = strstr(RSTRING(line)->ptr, "ruby")) != 0) {
- goto start_read;
- }
- }
- }
- rb_raise(rb_eLoadError, "no Ruby script found in input");
- }
-
- c = rb_io_getc(f);
- if (c == INT2FIX('#')) {
- line = rb_io_gets(f);
- if (NIL_P(line)) return;
- line_start++;
-
- if (RSTRING(line)->len > 2 && RSTRING(line)->ptr[0] == '!') {
- if ((p = strstr(RSTRING(line)->ptr, "ruby")) == 0) {
- /* not ruby script, kick the program */
- char **argv;
- char *path;
- char *pend = RSTRING(line)->ptr + RSTRING(line)->len;
-
- p = RSTRING(line)->ptr + 1; /* skip `#!' */
- if (pend[-1] == '\n') pend--; /* chomp line */
- if (pend[-1] == '\r') pend--;
- *pend = '\0';
- while (p < pend && ISSPACE(*p))
- p++;
- path = p; /* interpreter path */
- while (p < pend && !ISSPACE(*p))
- p++;
- *p++ = '\0';
- if (p < pend) {
- argv = ALLOCA_N(char*, origargc+3);
- argv[1] = p;
- MEMCPY(argv+2, origargv+1, char*, origargc);
- }
- else {
- argv = origargv;
- }
- argv[0] = path;
- execv(path, argv);
-
- ruby_sourcefile = rb_source_filename(fname);
- ruby_sourceline = 1;
- rb_fatal("Can't exec %s", path);
- }
-
- start_read:
- p += 4;
- RSTRING(line)->ptr[RSTRING(line)->len-1] = '\0';
- if (RSTRING(line)->ptr[RSTRING(line)->len-2] == '\r')
- RSTRING(line)->ptr[RSTRING(line)->len-2] = '\0';
- if ((p = strstr(p, " -")) != 0) {
- p++; /* skip space before `-' */
- while (*p == '-') {
- p = moreswitches(p+1);
- }
- }
- }
- }
- else if (!NIL_P(c)) {
- rb_io_ungetc(f, c);
- }
- require_libraries(); /* Why here? unnatural */
- if (NIL_P(c)) return;
- }
- ruby_eval_tree = rb_compile_file(fname, f, line_start);
- if (script && ruby__end__seen) {
- rb_define_global_const("DATA", f);
- }
- else if (f != rb_stdin) {
- rb_io_close(f);
- }
-}
-
-void
-rb_load_file(fname)
- const char *fname;
-{
- load_file(fname, 0);
-}
-
-static void
-load_stdin()
-{
- forbid_setid("program input from stdin");
- load_file("-", 1);
-}
-
-VALUE rb_progname;
-VALUE rb_argv;
-VALUE rb_argv0;
-
-#if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE) && !defined(DOSISH)
-static struct {
- char *begin, *end;
-} envspace;
-extern char **environ;
-
-static void
-set_arg0space()
-{
- char *s;
- int i;
-
- if (!environ || (s = environ[0]) == NULL) return;
- envspace.begin = s;
- s += strlen(s);
- for (i = 1; environ[i]; i++) {
- if (environ[i] == s + 1) {
- s++;
- s += strlen(s); /* this one is ok too */
- }
- }
- envspace.end = s;
-}
-#else
-#define set_arg0space() ((void)0)
-#endif
-
-static void
-set_arg0(val, id)
- VALUE val;
- ID id;
-{
- char *s;
- long i;
- static int len;
-
- if (origargv == 0) rb_raise(rb_eRuntimeError, "$0 not initialized");
- StringValue(val);
- s = RSTRING(val)->ptr;
- i = RSTRING(val)->len;
-#if defined(PSTAT_SETCMD)
- if (i >= PST_CLEN) {
- union pstun j;
- j.pst_command = s;
- i = PST_CLEN;
- RSTRING(val)->len = i;
- *(s + i) = '\0';
- pstat(PSTAT_SETCMD, j, PST_CLEN, 0, 0);
- }
- else {
- union pstun j;
- j.pst_command = s;
- pstat(PSTAT_SETCMD, j, i, 0, 0);
- }
- rb_progname = rb_tainted_str_new(s, i);
-#elif defined(HAVE_SETPROCTITLE)
- setproctitle("%.*s", (int)i, s);
- rb_progname = rb_tainted_str_new(s, i);
-#else
- if (len == 0) {
- char *s = origargv[0];
- int i;
-
- s += strlen(s);
- /* See if all the arguments are contiguous in memory */
- for (i = 1; i < origargc; i++) {
- if (origargv[i] == s + 1) {
- s++;
- s += strlen(s); /* this one is ok too */
- }
- else {
- break;
- }
- }
-#ifndef DOSISH
- if (s + 1 == envspace.begin) {
- s = envspace.end;
- ruby_setenv("", NULL); /* duplicate environ vars */
- }
-#endif
- len = s - origargv[0];
- }
-
- if (i >= len) {
- i = len;
- memcpy(origargv[0], s, i);
- origargv[0][i] = '\0';
- }
- else {
- memcpy(origargv[0], s, i);
- s = origargv[0]+i;
- *s++ = '\0';
- while (++i < len)
- *s++ = ' ';
- for (i = 1; i < origargc; i++)
- origargv[i] = 0;
- }
- rb_progname = rb_tainted_str_new2(origargv[0]);
-#endif
-}
-
-void
-ruby_script(name)
- const char *name;
-{
- if (name) {
- rb_progname = rb_tainted_str_new2(name);
- ruby_sourcefile = rb_source_filename(name);
- }
-}
-
-static int uid, euid, gid, egid;
-
-static void
-init_ids()
-{
- uid = (int)getuid();
- euid = (int)geteuid();
- gid = (int)getgid();
- egid = (int)getegid();
-#ifdef VMS
- uid |= gid << 16;
- euid |= egid << 16;
-#endif
- if (uid && (euid != uid || egid != gid)) {
- rb_set_safe_level(1);
- }
-}
-
-static void
-forbid_setid(s)
- const char *s;
-{
- if (euid != uid)
- rb_raise(rb_eSecurityError, "no %s allowed while running setuid", s);
- if (egid != gid)
- rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s);
- if (rb_safe_level() > 0)
- rb_raise(rb_eSecurityError, "no %s allowed in tainted mode", s);
-}
-
-static void
-verbose_setter(val, id, variable)
- VALUE val;
- ID id;
- VALUE *variable;
-{
- ruby_verbose = RTEST(val) ? Qtrue : val;
-}
-
-static VALUE
-opt_W_getter(val, id)
- VALUE val;
- ID id;
-{
- if (ruby_verbose == Qnil) return INT2FIX(0);
- if (ruby_verbose == Qfalse) return INT2FIX(1);
- if (ruby_verbose == Qtrue) return INT2FIX(2);
- return Qnil; /* not reached */
-}
-
-void
-ruby_prog_init()
-{
- init_ids();
-
- ruby_sourcefile = rb_source_filename("ruby");
- rb_define_hooked_variable("$VERBOSE", &ruby_verbose, 0, verbose_setter);
- rb_define_hooked_variable("$-v", &ruby_verbose, 0, verbose_setter);
- rb_define_hooked_variable("$-w", &ruby_verbose, 0, verbose_setter);
- rb_define_virtual_variable("$-W", opt_W_getter, 0);
- rb_define_variable("$DEBUG", &ruby_debug);
- rb_define_variable("$-d", &ruby_debug);
- rb_define_readonly_variable("$-p", &do_print);
- rb_define_readonly_variable("$-l", &do_line);
-
- rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0);
- rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0);
-
- rb_argv = rb_ary_new();
- rb_define_readonly_variable("$*", &rb_argv);
- rb_define_global_const("ARGV", rb_argv);
- rb_define_readonly_variable("$-a", &do_split);
- rb_global_variable(&rb_argv0);
-
-#ifdef MSDOS
- /*
- * There is no way we can refer to them from ruby, so close them to save
- * space.
- */
- (void)fclose(stdaux);
- (void)fclose(stdprn);
-#endif
-}
-
-void
-ruby_set_argv(argc, argv)
- int argc;
- char **argv;
-{
- int i;
-
-#if defined(USE_DLN_A_OUT)
- if (origargv) dln_argv0 = origargv[0];
- else dln_argv0 = argv[0];
-#endif
- rb_ary_clear(rb_argv);
- for (i=0; i < argc; i++) {
- VALUE arg = rb_tainted_str_new2(argv[i]);
-
- OBJ_FREEZE(arg);
- rb_ary_push(rb_argv, arg);
- }
-}
-
-NODE *rb_parser_append_print _((NODE*));
-NODE *rb_parser_while_loop _((NODE*, int, int));
-
-void
-ruby_process_options(argc, argv)
- int argc;
- char **argv;
-{
- origargc = argc; origargv = argv;
-
- ruby_script(argv[0]); /* for the time being */
- rb_argv0 = rb_progname;
-#if defined(USE_DLN_A_OUT)
- dln_argv0 = argv[0];
-#endif
- set_arg0space();
- proc_options(argc, argv);
-
- if (do_check && ruby_nerrs == 0) {
- printf("Syntax OK\n");
- exit(0);
- }
- if (do_print) {
- ruby_eval_tree = rb_parser_append_print(ruby_eval_tree);
- }
- if (do_loop) {
- ruby_eval_tree = rb_parser_while_loop(ruby_eval_tree, do_line, do_split);
- }
-}
-/**********************************************************************
-
- signal.c -
-
- $Author: matz $
- $Date: 2005/03/04 06:47:41 $
- created at: Tue Dec 20 10:13:44 JST 1994
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
-#include "ruby.h"
-#include "rubysig.h"
-#include <signal.h>
-#include <stdio.h>
-
-#ifdef __BEOS__
-#undef SIGBUS
-#endif
-
-#ifndef NSIG
-# ifdef DJGPP
-# define NSIG SIGMAX
-# else
-# define NSIG (_SIGMAX + 1) /* For QNX */
-# endif
-#endif
-
-static struct signals {
- char *signm;
- int signo;
-} siglist [] = {
-#ifdef SIGHUP
- {"HUP", SIGHUP},
-#endif
- {"INT", SIGINT},
-#ifdef SIGQUIT
- {"QUIT", SIGQUIT},
-#endif
-#ifdef SIGILL
- {"ILL", SIGILL},
-#endif
-#ifdef SIGTRAP
- {"TRAP", SIGTRAP},
-#endif
-#ifdef SIGIOT
- {"IOT", SIGIOT},
-#endif
-#ifdef SIGABRT
- {"ABRT", SIGABRT},
-#endif
-#ifdef SIGEMT
- {"EMT", SIGEMT},
-#endif
-#ifdef SIGFPE
- {"FPE", SIGFPE},
-#endif
-#ifdef SIGKILL
- {"KILL", SIGKILL},
-#endif
-#ifdef SIGBUS
- {"BUS", SIGBUS},
-#endif
-#ifdef SIGSEGV
- {"SEGV", SIGSEGV},
-#endif
-#ifdef SIGSYS
- {"SYS", SIGSYS},
-#endif
-#ifdef SIGPIPE
- {"PIPE", SIGPIPE},
-#endif
-#ifdef SIGALRM
- {"ALRM", SIGALRM},
-#endif
-#ifdef SIGTERM
- {"TERM", SIGTERM},
-#endif
-#ifdef SIGURG
- {"URG", SIGURG},
-#endif
-#ifdef SIGSTOP
- {"STOP", SIGSTOP},
-#endif
-#ifdef SIGTSTP
- {"TSTP", SIGTSTP},
-#endif
-#ifdef SIGCONT
- {"CONT", SIGCONT},
-#endif
-#ifdef SIGCHLD
- {"CHLD", SIGCHLD},
-#endif
-#ifdef SIGCLD
- {"CLD", SIGCLD},
-#else
-# ifdef SIGCHLD
- {"CLD", SIGCHLD},
-# endif
-#endif
-#ifdef SIGTTIN
- {"TTIN", SIGTTIN},
-#endif
-#ifdef SIGTTOU
- {"TTOU", SIGTTOU},
-#endif
-#ifdef SIGIO
- {"IO", SIGIO},
-#endif
-#ifdef SIGXCPU
- {"XCPU", SIGXCPU},
-#endif
-#ifdef SIGXFSZ
- {"XFSZ", SIGXFSZ},
-#endif
-#ifdef SIGVTALRM
- {"VTALRM", SIGVTALRM},
-#endif
-#ifdef SIGPROF
- {"PROF", SIGPROF},
-#endif
-#ifdef SIGWINCH
- {"WINCH", SIGWINCH},
-#endif
-#ifdef SIGUSR1
- {"USR1", SIGUSR1},
-#endif
-#ifdef SIGUSR2
- {"USR2", SIGUSR2},
-#endif
-#ifdef SIGLOST
- {"LOST", SIGLOST},
-#endif
-#ifdef SIGMSG
- {"MSG", SIGMSG},
-#endif
-#ifdef SIGPWR
- {"PWR", SIGPWR},
-#endif
-#ifdef SIGPOLL
- {"POLL", SIGPOLL},
-#endif
-#ifdef SIGDANGER
- {"DANGER", SIGDANGER},
-#endif
-#ifdef SIGMIGRATE
- {"MIGRATE", SIGMIGRATE},
-#endif
-#ifdef SIGPRE
- {"PRE", SIGPRE},
-#endif
-#ifdef SIGGRANT
- {"GRANT", SIGGRANT},
-#endif
-#ifdef SIGRETRACT
- {"RETRACT", SIGRETRACT},
-#endif
-#ifdef SIGSOUND
- {"SOUND", SIGSOUND},
-#endif
-#ifdef SIGINFO
- {"INFO", SIGINFO},
-#endif
- {NULL, 0}
-};
-
-static int
-signm2signo(nm)
- char *nm;
-{
- struct signals *sigs;
-
- for (sigs = siglist; sigs->signm; sigs++)
- if (strcmp(sigs->signm, nm) == 0)
- return sigs->signo;
- return 0;
-}
-
-static char*
-signo2signm(no)
- int no;
-{
- struct signals *sigs;
-
- for (sigs = siglist; sigs->signm; sigs++)
- if (sigs->signo == no)
- return sigs->signm;
- return 0;
-}
-
-const char *
-ruby_signal_name(no)
- int no;
-{
- return signo2signm(no);
-}
-
-/*
- * call-seq:
- * Process.kill(signal, pid, ...) => fixnum
- *
- * Sends the given signal to the specified process id(s), or to the
- * current process if _pid_ is zero. _signal_ may be an
- * integer signal number or a POSIX signal name (either with or without
- * a +SIG+ prefix). If _signal_ is negative (or starts
- * with a minus sign), kills process groups instead of
- * processes. Not all signals are available on all platforms.
- *
- * pid = fork do
- * Signal.trap("HUP") { puts "Ouch!"; exit }
- * # ... do some work ...
- * end
- * # ...
- * Process.kill("HUP", pid)
- * Process.wait
- *
- * <em>produces:</em>
- *
- * Ouch!
- */
-
-VALUE
-rb_f_kill(argc, argv)
- int argc;
- VALUE *argv;
-{
- int negative = 0;
- int sig;
- int i;
- char *s;
-
- rb_secure(2);
- if (argc < 2)
- rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)");
- switch (TYPE(argv[0])) {
- case T_FIXNUM:
- sig = FIX2INT(argv[0]);
- break;
-
- case T_SYMBOL:
- s = rb_id2name(SYM2ID(argv[0]));
- if (!s) rb_raise(rb_eArgError, "bad signal");
- goto str_signal;
-
- case T_STRING:
- s = RSTRING(argv[0])->ptr;
- if (s[0] == '-') {
- negative++;
- s++;
- }
- str_signal:
- if (strncmp("SIG", s, 3) == 0)
- s += 3;
- if((sig = signm2signo(s)) == 0)
- rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);
-
- if (negative)
- sig = -sig;
- break;
-
- default:
- {
- VALUE str;
-
- str = rb_check_string_type(argv[0]);
- if (!NIL_P(str)) {
- s = RSTRING(str)->ptr;
- goto str_signal;
- }
- rb_raise(rb_eArgError, "bad signal type %s",
- rb_obj_classname(argv[0]));
- }
- break;
- }
-
- if (sig < 0) {
- sig = -sig;
- for (i=1; i<argc; i++) {
- int pid = NUM2INT(argv[i]);
-#ifdef HAS_KILLPG
- if (killpg(pid, sig) < 0)
-#else
- if (kill(-pid, sig) < 0)
-#endif
- rb_sys_fail(0);
- }
- }
- else {
- for (i=1; i<argc; i++) {
- Check_Type(argv[i], T_FIXNUM);
- if (kill(FIX2INT(argv[i]), sig) < 0)
- rb_sys_fail(0);
- }
- }
- return INT2FIX(i-1);
-}
-
-static struct {
- VALUE cmd;
- int safe;
-} trap_list[NSIG];
-static rb_atomic_t trap_pending_list[NSIG];
-static char rb_trap_accept_nativethreads[NSIG];
-rb_atomic_t rb_trap_pending;
-rb_atomic_t rb_trap_immediate;
-int rb_prohibit_interrupt = 1;
-
-void
-rb_gc_mark_trap_list()
-{
-#ifndef MACOS_UNUSE_SIGNAL
- int i;
-
- for (i=0; i<NSIG; i++) {
- if (trap_list[i].cmd)
- rb_gc_mark(trap_list[i].cmd);
- }
-#endif /* MACOS_UNUSE_SIGNAL */
-}
-
-#ifdef __dietlibc__
-#define sighandler_t sh_t
-#endif
-
-typedef RETSIGTYPE (*sighandler_t)_((int));
-
-#ifdef POSIX_SIGNAL
-static sighandler_t
-ruby_signal(signum, handler)
- int signum;
- sighandler_t handler;
-{
- struct sigaction sigact, old;
-
- rb_trap_accept_nativethreads[signum] = 0;
-
- sigact.sa_handler = handler;
- sigemptyset(&sigact.sa_mask);
- sigact.sa_flags = 0;
-#if defined(SA_RESTART)
- /* All other signals but VTALRM shall restart restartable syscall
- VTALRM will cause EINTR to syscall if interrupted.
- */
- if (signum != SIGVTALRM) {
- sigact.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */
- }
-#endif
-#ifdef SA_NOCLDWAIT
- if (signum == SIGCHLD && handler == SIG_IGN)
- sigact.sa_flags |= SA_NOCLDWAIT;
-#endif
- sigaction(signum, &sigact, &old);
- return old.sa_handler;
-}
-
-void
-posix_signal(signum, handler)
- int signum;
- sighandler_t handler;
-{
- ruby_signal(signum, handler);
-}
-
-#ifdef HAVE_NATIVETHREAD
-static sighandler_t
-ruby_nativethread_signal(signum, handler)
- int signum;
- sighandler_t handler;
-{
- sighandler_t old;
-
- old = ruby_signal(signum, handler);
- rb_trap_accept_nativethreads[signum] = 1;
- return old;
-}
-
-void
-posix_nativethread_signal(signum, handler)
- int signum;
- sighandler_t handler;
-{
- ruby_nativethread_signal(signum, handler);
-}
-#endif
-#else /* !POSIX_SIGNAL */
-#define ruby_signal(sig,handler) (rb_trap_accept_nativethreads[sig] = 0, signal((sig),(handler)))
-#ifdef HAVE_NATIVETHREAD
-static sighandler_t
-ruby_nativethread_signal(signum, handler)
- int signum;
- sighandler_t handler;
-{
- sighandler_t old;
-
- old = signal(signum, handler);
- rb_trap_accept_nativethreads[signum] = 1;
- return old;
-}
-#endif
-#endif
-
-static void signal_exec _((int sig));
-static void
-signal_exec(sig)
- int sig;
-{
- if (trap_list[sig].cmd == 0) {
- switch (sig) {
- case SIGINT:
- rb_thread_interrupt();
- break;
-#ifdef SIGHUP
- case SIGHUP:
-#endif
-#ifdef SIGQUIT
- case SIGQUIT:
-#endif
-#ifdef SIGALRM
- case SIGALRM:
-#endif
-#ifdef SIGUSR1
- case SIGUSR1:
-#endif
-#ifdef SIGUSR2
- case SIGUSR2:
-#endif
- rb_thread_signal_raise(signo2signm(sig));
- break;
- }
- }
- else {
- rb_thread_trap_eval(trap_list[sig].cmd, sig, trap_list[sig].safe);
- }
-}
-
-static void
-sigsend_to_ruby_thread(sig)
- int sig;
-{
-#ifdef HAVE_NATIVETHREAD_KILL
-# ifdef HAVE_SIGPROCMASK
- sigset_t mask, old_mask;
-# else
- int mask, old_mask;
-# endif
-
-#ifdef HAVE_SIGPROCMASK
- sigfillset(&mask);
- sigprocmask(SIG_BLOCK, &mask, &old_mask);
-#else
- mask = sigblock(~0);
- sigsetmask(mask);
-#endif
-
- ruby_native_thread_kill(sig);
-#endif
-}
-
-static RETSIGTYPE sighandler _((int));
-static RETSIGTYPE
-sighandler(sig)
- int sig;
-{
-#ifdef _WIN32
-#define IN_MAIN_CONTEXT(f, a) (rb_w32_main_context(a, f) ? (void)0 : f(a))
-#else
-#define IN_MAIN_CONTEXT(f, a) f(a)
-#endif
- if (sig >= NSIG) {
- rb_bug("trap_handler: Bad signal %d", sig);
- }
-
-#if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
- if (!is_ruby_native_thread() && !rb_trap_accept_nativethreads[sig]) {
- sigsend_to_ruby_thread(sig);
- return;
- }
-#endif
-
-#if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
- if (rb_trap_accept_nativethreads[sig]) {
- ruby_nativethread_signal(sig, sighandler);
- } else {
- ruby_signal(sig, sighandler);
- }
-#endif
-
- if (trap_list[sig].cmd == 0 && ATOMIC_TEST(rb_trap_immediate)) {
- IN_MAIN_CONTEXT(signal_exec, sig);
- ATOMIC_SET(rb_trap_immediate, 1);
- }
- else {
- ATOMIC_INC(rb_trap_pending);
- ATOMIC_INC(trap_pending_list[sig]);
- }
-}
-
-#ifdef SIGBUS
-static RETSIGTYPE sigbus _((int));
-static RETSIGTYPE
-sigbus(sig)
- int sig;
-{
-#if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
- if (!is_ruby_native_thread() && !rb_trap_accept_nativethreads[sig]) {
- sigsend_to_ruby_thread(sig);
- return;
- }
-#endif
-
- rb_bug("Bus Error");
-}
-#endif
-
-#ifdef SIGSEGV
-static RETSIGTYPE sigsegv _((int));
-static RETSIGTYPE
-sigsegv(sig)
- int sig;
-{
-#if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
- if (!is_ruby_native_thread() && !rb_trap_accept_nativethreads[sig]) {
- sigsend_to_ruby_thread(sig);
- return;
- }
-#endif
-
- rb_bug("Segmentation fault");
-}
-#endif
-
-#ifdef SIGPIPE
-static RETSIGTYPE sigpipe _((int));
-static RETSIGTYPE
-sigpipe(sig)
- int sig;
-{
- /* do nothing */
-}
-#endif
-
-void
-rb_trap_exit()
-{
-#ifndef MACOS_UNUSE_SIGNAL
- if (trap_list[0].cmd) {
- VALUE trap_exit = trap_list[0].cmd;
-
- trap_list[0].cmd = 0;
- rb_eval_cmd(trap_exit, rb_ary_new3(1, INT2FIX(0)), trap_list[0].safe);
- }
-#endif
-}
-
-void
-rb_trap_exec()
-{
-#ifndef MACOS_UNUSE_SIGNAL
- int i;
-
- for (i=0; i<NSIG; i++) {
- if (trap_pending_list[i]) {
- trap_pending_list[i] = 0;
- signal_exec(i);
- }
- }
-#endif /* MACOS_UNUSE_SIGNAL */
- rb_trap_pending = 0;
-}
-
-struct trap_arg {
-#ifndef _WIN32
-# ifdef HAVE_SIGPROCMASK
- sigset_t mask;
-# else
- int mask;
-# endif
-#endif
- VALUE sig, cmd;
-};
-
-# ifdef HAVE_SIGPROCMASK
-static sigset_t trap_last_mask;
-# else
-static int trap_last_mask;
-# endif
-
-static RETSIGTYPE sigexit _((int));
-static RETSIGTYPE
-sigexit(sig)
- int sig;
-{
-#if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
- if (!is_ruby_native_thread() && !rb_trap_accept_nativethreads[sig]) {
- sigsend_to_ruby_thread(sig);
- return;
- }
-#endif
-
- rb_exit(0);
-}
-
-static VALUE
-trap(arg)
- struct trap_arg *arg;
-{
- sighandler_t func, oldfunc;
- VALUE command, oldcmd;
- int sig = -1;
- char *s;
-
- func = sighandler;
- command = arg->cmd;
- if (NIL_P(command)) {
- func = SIG_IGN;
- }
- else if (TYPE(command) == T_STRING) {
- SafeStringValue(command); /* taint check */
- if (RSTRING(command)->len == 0) {
- func = SIG_IGN;
- }
- else if (RSTRING(command)->len == 7) {
- if (strncmp(RSTRING(command)->ptr, "SIG_IGN", 7) == 0) {
- func = SIG_IGN;
- }
- else if (strncmp(RSTRING(command)->ptr, "SIG_DFL", 7) == 0) {
- func = SIG_DFL;
- }
- else if (strncmp(RSTRING(command)->ptr, "DEFAULT", 7) == 0) {
- func = SIG_DFL;
- }
- }
- else if (RSTRING(command)->len == 6) {
- if (strncmp(RSTRING(command)->ptr, "IGNORE", 6) == 0) {
- func = SIG_IGN;
- }
- }
- else if (RSTRING(command)->len == 4) {
- if (strncmp(RSTRING(command)->ptr, "EXIT", 4) == 0) {
- func = sigexit;
- }
- }
- }
- if (func == SIG_IGN || func == SIG_DFL) {
- command = 0;
- }
-
- switch (TYPE(arg->sig)) {
- case T_FIXNUM:
- sig = FIX2INT(arg->sig);
- break;
-
- case T_SYMBOL:
- s = rb_id2name(SYM2ID(arg->sig));
- if (!s) rb_raise(rb_eArgError, "bad signal");
- goto str_signal;
-
- case T_STRING:
- s = RSTRING(arg->sig)->ptr;
-
- str_signal:
- if (strncmp("SIG", s, 3) == 0)
- s += 3;
- sig = signm2signo(s);
- if (sig == 0 && strcmp(s, "EXIT") != 0)
- rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
- }
-
- if (sig < 0 || sig > NSIG) {
- rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
- }
-#if defined(HAVE_SETITIMER)
- if (sig == SIGVTALRM) {
- rb_raise(rb_eArgError, "SIGVTALRM reserved for Thread; can't set handler");
- }
-#endif
- if (func == SIG_DFL) {
- switch (sig) {
- case SIGINT:
-#ifdef SIGHUP
- case SIGHUP:
-#endif
-#ifdef SIGQUIT
- case SIGQUIT:
-#endif
-#ifdef SIGALRM
- case SIGALRM:
-#endif
-#ifdef SIGUSR1
- case SIGUSR1:
-#endif
-#ifdef SIGUSR2
- case SIGUSR2:
-#endif
- func = sighandler;
- break;
-#ifdef SIGBUS
- case SIGBUS:
- func = sigbus;
- break;
-#endif
-#ifdef SIGSEGV
- case SIGSEGV:
- func = sigsegv;
- break;
-#endif
-#ifdef SIGPIPE
- case SIGPIPE:
- func = sigpipe;
- break;
-#endif
- }
- }
- oldfunc = ruby_signal(sig, func);
- oldcmd = trap_list[sig].cmd;
- if (!oldcmd) {
- if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
- else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
- else oldcmd = Qnil;
- }
-
- trap_list[sig].cmd = command;
- trap_list[sig].safe = ruby_safe_level;
- /* enable at least specified signal. */
-#ifndef _WIN32
-#ifdef HAVE_SIGPROCMASK
- sigdelset(&arg->mask, sig);
-#else
- arg->mask &= ~sigmask(sig);
-#endif
-#endif
- return oldcmd;
-}
-
-#ifndef _WIN32
-static VALUE
-trap_ensure(arg)
- struct trap_arg *arg;
-{
- /* enable interrupt */
-#ifdef HAVE_SIGPROCMASK
- sigprocmask(SIG_SETMASK, &arg->mask, NULL);
-#else
- sigsetmask(arg->mask);
-#endif
- trap_last_mask = arg->mask;
- return 0;
-}
-#endif
-
-void
-rb_trap_restore_mask()
-{
-#ifndef _WIN32
-# ifdef HAVE_SIGPROCMASK
- sigprocmask(SIG_SETMASK, &trap_last_mask, NULL);
-# else
- sigsetmask(trap_last_mask);
-# endif
-#endif
-}
-
-/*
- * call-seq:
- * Signal.trap( signal, proc ) => obj
- * Signal.trap( signal ) {| | block } => obj
- *
- * Specifies the handling of signals. The first parameter is a signal
- * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
- * signal number. The characters ``SIG'' may be omitted from the
- * signal name. The command or block specifies code to be run when the
- * signal is raised. If the command is the string ``IGNORE'' or
- * ``SIG_IGN'', the signal will be ignored. If the command is
- * ``DEFAULT'' or ``SIG_DFL'', the operating system's default handler
- * will be invoked. If the command is ``EXIT'', the script will be
- * terminated by the signal. Otherwise, the given command or block
- * will be run.
- * The special signal name ``EXIT'' or signal number zero will be
- * invoked just prior to program termination.
- * trap returns the previous handler for the given signal.
- *
- * Signal.trap(0, proc { puts "Terminating: #{$$}" })
- * Signal.trap("CLD") { puts "Child died" }
- * fork && Process.wait
- *
- * produces:
- * Terminating: 27461
- * Child died
- * Terminating: 27460
- */
-static VALUE
-sig_trap(argc, argv)
- int argc;
- VALUE *argv;
-{
- struct trap_arg arg;
-
- rb_secure(2);
- if (argc == 0 || argc > 2) {
- rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}");
- }
-
- arg.sig = argv[0];
- if (argc == 1) {
- arg.cmd = rb_block_proc();
- }
- else if (argc == 2) {
- arg.cmd = argv[1];
- }
-
- if (OBJ_TAINTED(arg.cmd)) {
- rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
- }
-#ifndef _WIN32
- /* disable interrupt */
-# ifdef HAVE_SIGPROCMASK
- sigfillset(&arg.mask);
- sigprocmask(SIG_BLOCK, &arg.mask, &arg.mask);
-# else
- arg.mask = sigblock(~0);
-# endif
-
- return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg);
-#else
- return trap(&arg);
-#endif
-}
-
-/*
- * call-seq:
- * Signal.list => a_hash
- *
- * Returns a list of signal names mapped to the corresponding
- * underlying signal numbers.
- *
- * Signal.list #=> {"ABRT"=>6, "ALRM"=>14, "BUS"=>7, "CHLD"=>17, "CLD"=>17, "CONT"=>18, "FPE"=>8, "HUP"=>1, "ILL"=>4, "INT"=>2, "IO"=>29, "IOT"=>6, "KILL"=>9, "PIPE"=>13, "POLL"=>29, "PROF"=>27, "PWR"=>30, "QUIT"=>3, "SEGV"=>11, "STOP"=>19, "SYS"=>31, "TERM"=>15, "TRAP"=>5, "TSTP"=>20, "TTIN"=>21, "TTOU"=>22, "URG"=>23, "USR1"=>10, "USR2"=>12, "VTALRM"=>26, "WINCH"=>28, "XCPU"=>24, "XFSZ"=>25}
- */
-static VALUE
-sig_list()
-{
- VALUE h = rb_hash_new();
- struct signals *sigs;
-
- for (sigs = siglist; sigs->signm; sigs++) {
- rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
- }
- return h;
-}
-
-static void
-install_sighandler(signum, handler)
- int signum;
- sighandler_t handler;
-{
- sighandler_t old;
-
- old = ruby_signal(signum, handler);
- if (old != SIG_DFL) {
- ruby_signal(signum, old);
- }
-}
-
-#ifdef HAVE_NATIVETHREAD
-static void
-install_nativethread_sighandler(signum, handler)
- int signum;
- sighandler_t handler;
-{
- sighandler_t old;
- int old_st;
-
- old_st = rb_trap_accept_nativethreads[signum];
- old = ruby_nativethread_signal(signum, handler);
- if (old != SIG_DFL) {
- if (old_st) {
- ruby_nativethread_signal(signum, old);
- } else {
- ruby_signal(signum, old);
- }
- }
-}
-#endif
-
-static void
-init_sigchld(sig)
- int sig;
-{
- sighandler_t oldfunc;
-#ifndef _WIN32
-# ifdef HAVE_SIGPROCMASK
- sigset_t mask;
-# else
- int mask;
-# endif
-#endif
-
-#ifndef _WIN32
- /* disable interrupt */
-# ifdef HAVE_SIGPROCMASK
- sigfillset(&mask);
- sigprocmask(SIG_BLOCK, &mask, &mask);
-# else
- mask = sigblock(~0);
-# endif
-#endif
-
- oldfunc = ruby_signal(sig, SIG_DFL);
- if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
- ruby_signal(sig, oldfunc);
- } else {
- trap_list[sig].cmd = 0;
- }
-
-#ifndef _WIN32
-#ifdef HAVE_SIGPROCMASK
- sigdelset(&mask, sig);
- sigprocmask(SIG_SETMASK, &mask, NULL);
-#else
- mask &= ~sigmask(sig);
- sigsetmask(mask);
-#endif
- trap_last_mask = mask;
-#endif
-}
-
-/*
- * Many operating systems allow signals to be sent to running
- * processes. Some signals have a defined effect on the process, while
- * others may be trapped at the code level and acted upon. For
- * example, your process may trap the USR1 signal and use it to toggle
- * debugging, and may use TERM to initiate a controlled shutdown.
- *
- * pid = fork do
- * Signal.trap("USR1") do
- * $debug = !$debug
- * puts "Debug now: #$debug"
- * end
- * Signal.trap("TERM") do
- * puts "Terminating..."
- * shutdown()
- * end
- * # . . . do some work . . .
- * end
- *
- * Process.detach(pid)
- *
- * # Controlling program:
- * Process.kill("USR1", pid)
- * # ...
- * Process.kill("USR1", pid)
- * # ...
- * Process.kill("TERM", pid)
- *
- * produces:
- * Debug now: true
- * Debug now: false
- * Terminating...
- *
- * The list of available signal names and their interpretation is
- * system dependent. Signal delivery semantics may also vary between
- * systems; in particular signal delivery may not always be reliable.
- */
-void
-Init_signal()
-{
-#ifndef MACOS_UNUSE_SIGNAL
- VALUE mSignal = rb_define_module("Signal");
-
- rb_define_global_function("trap", sig_trap, -1);
- rb_define_module_function(mSignal, "trap", sig_trap, -1);
- rb_define_module_function(mSignal, "list", sig_list, 0);
-
- install_sighandler(SIGINT, sighandler);
-#ifdef SIGHUP
- install_sighandler(SIGHUP, sighandler);
-#endif
-#ifdef SIGQUIT
- install_sighandler(SIGQUIT, sighandler);
-#endif
-#ifdef SIGALRM
- install_sighandler(SIGALRM, sighandler);
-#endif
-#ifdef SIGUSR1
- install_sighandler(SIGUSR1, sighandler);
-#endif
-#ifdef SIGUSR2
- install_sighandler(SIGUSR2, sighandler);
-#endif
-
-#ifdef SIGBUS
- install_sighandler(SIGBUS, sigbus);
-#endif
-#ifdef SIGSEGV
- install_sighandler(SIGSEGV, sigsegv);
-#endif
-#ifdef SIGPIPE
- install_sighandler(SIGPIPE, sigpipe);
-#endif
-
-#ifdef SIGCLD
- init_sigchld(SIGCLD);
-#endif
-#ifdef SIGCHLD
- init_sigchld(SIGCHLD);
-#endif
-
-#endif /* MACOS_UNUSE_SIGNAL */
-}
-/**********************************************************************
- sjis.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"
-
-static int EncLen_SJIS[] = {
- 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, 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, 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, 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, 1, 1
-};
-
-static const char SJIS_CAN_BE_TRAIL_TABLE[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 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, 0,
- 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, 0, 0, 0
-};
-
-#define SJIS_ISMB_FIRST(byte) (EncLen_SJIS[byte] > 1)
-#define SJIS_ISMB_TRAIL(byte) SJIS_CAN_BE_TRAIL_TABLE[(byte)]
-
-static int
-sjis_mbc_enc_len(const UChar* p)
-{
- return EncLen_SJIS[*p];
-}
-
-extern int
-sjis_code_to_mbclen(OnigCodePoint code)
-{
- if (code < 256) {
- if (EncLen_SJIS[(int )code] == 1)
- return 1;
- else
- return 0;
- }
- else if (code <= 0xffff) {
- return 2;
- }
- else
- return 0;
-}
-
-static OnigCodePoint
-sjis_mbc_to_code(const UChar* p, const UChar* end)
-{
- int c, i, len;
- OnigCodePoint n;
-
- len = enc_len(ONIG_ENCODING_SJIS, p);
- c = *p++;
- n = c;
- 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
-sjis_code_to_mbc(OnigCodePoint code, UChar *buf)
-{
- UChar *p = buf;
-
- if ((code & 0xff00) != 0) *p++ = (UChar )(((code >> 8) & 0xff));
- *p++ = (UChar )(code & 0xff);
-
-#if 0
- if (enc_len(ONIG_ENCODING_SJIS, buf) != (p - buf))
- return REGERR_INVALID_WIDE_CHAR_VALUE;
-#endif
- return p - buf;
-}
-
-static int
-sjis_mbc_to_normalize(OnigAmbigType flag,
- const UChar** pp, const UChar* end, UChar* lower)
-{
- 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 {
- int len = enc_len(ONIG_ENCODING_SJIS, 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
-sjis_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end)
-{
- return onigenc_mbn_is_mbc_ambiguous(ONIG_ENCODING_SJIS, flag, pp, end);
-
-}
-
-static int
-sjis_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 (sjis_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*
-sjis_left_adjust_char_head(const UChar* start, const UChar* s)
-{
- const UChar *p;
- int len;
-
- if (s <= start) return (UChar* )s;
- p = s;
-
- if (SJIS_ISMB_TRAIL(*p)) {
- while (p > start) {
- if (! SJIS_ISMB_FIRST(*--p)) {
- p++;
- break;
- }
- }
- }
- len = enc_len(ONIG_ENCODING_SJIS, p);
- if (p + len > s) return (UChar* )p;
- p += len;
- return (UChar* )(p + ((s - p) & ~1));
-}
-
-static int
-sjis_is_allowed_reverse_match(const UChar* s, const UChar* end)
-{
- const UChar c = *s;
- return (SJIS_ISMB_TRAIL(c) ? FALSE : TRUE);
-}
-
-OnigEncodingType OnigEncodingSJIS = {
- sjis_mbc_enc_len,
- "Shift_JIS", /* name */
- 2, /* max byte length */
- 1, /* min byte 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,
- sjis_mbc_to_code,
- sjis_code_to_mbclen,
- sjis_code_to_mbc,
- sjis_mbc_to_normalize,
- sjis_is_mbc_ambiguous,
- onigenc_ascii_get_all_pair_ambig_codes,
- onigenc_nothing_get_all_comp_ambig_codes,
- sjis_is_code_ctype,
- onigenc_not_support_get_ctype_code_range,
- sjis_left_adjust_char_head,
- sjis_is_allowed_reverse_match
-};
-/**********************************************************************
-
- sprintf.c -
-
- $Author: matz $
- $Date: 2005/03/04 06:47:41 $
- created at: Fri Oct 15 10:39:26 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 <ctype.h>
-#include <math.h>
-
-#define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
-
-static void fmt_setup _((char*,int,int,int,int));
-
-static char*
-remove_sign_bits(str, base)
- char *str;
- int base;
-{
- char *s, *t;
-
- s = t = str;
-
- if (base == 16) {
- while (*t == 'f') {
- t++;
- }
- }
- else if (base == 8) {
- if (*t == '3') t++;
- while (*t == '7') {
- t++;
- }
- }
- else if (base == 2) {
- while (*t == '1') {
- t++;
- }
- }
- if (t > s) {
- while (*t) *s++ = *t++;
- *s = '\0';
- }
-
- return str;
-}
-
-static char
-sign_bits(base, p)
- int base;
- const char *p;
-{
- char c = '.';
-
- switch (base) {
- case 16:
- if (*p == 'X') c = 'F';
- else c = 'f';
- break;
- case 8:
- c = '7'; break;
- case 2:
- c = '1'; break;
- }
- return c;
-}
-
-#define FNONE 0
-#define FSHARP 1
-#define FMINUS 2
-#define FPLUS 4
-#define FZERO 8
-#define FSPACE 16
-#define FWIDTH 32
-#define FPREC 64
-
-#define CHECK(l) do {\
- while (blen + (l) >= bsiz) {\
- bsiz*=2;\
- }\
- rb_str_resize(result, bsiz);\
- buf = RSTRING(result)->ptr;\
-} while (0)
-
-#define PUSH(s, l) do { \
- CHECK(l);\
- memcpy(&buf[blen], s, l);\
- blen += (l);\
-} while (0)
-
-#define GETARG() (nextvalue != Qundef ? nextvalue : \
- posarg < 0 ? \
- (rb_raise(rb_eArgError, "unnumbered(%d) mixed with numbered", nextarg), 0) : \
- (posarg = nextarg++, GETNTHARG(posarg)))
-
-#define GETPOSARG(n) (posarg > 0 ? \
- (rb_raise(rb_eArgError, "numbered(%d) after unnumbered(%d)", n, posarg), 0) : \
- ((n < 1) ? (rb_raise(rb_eArgError, "invalid index - %d$", n), 0) : \
- (posarg = -1, GETNTHARG(n))))
-
-#define GETNTHARG(nth) \
- ((nth >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : argv[nth])
-
-#define GETASTER(val) do { \
- t = p++; \
- n = 0; \
- for (; p < end && ISDIGIT(*p); p++) { \
- n = 10 * n + (*p - '0'); \
- } \
- if (p >= end) { \
- rb_raise(rb_eArgError, "malformed format string - %%*[0-9]"); \
- } \
- if (*p == '$') { \
- tmp = GETPOSARG(n); \
- } \
- else { \
- tmp = GETARG(); \
- p = t; \
- } \
- val = NUM2INT(tmp); \
-} while (0)
-
-
-/*
- * call-seq:
- * format(format_string [, arguments...] ) => string
- * sprintf(format_string [, arguments...] ) => string
- *
- * Returns the string resulting from applying <i>format_string</i> to
- * any additional arguments. Within the format string, any characters
- * other than format sequences are copied to the result. A format
- * sequence consists of a percent sign, followed by optional flags,
- * width, and precision indicators, then terminated with a field type
- * character. The field type controls how the corresponding
- * <code>sprintf</code> argument is to be interpreted, while the flags
- * modify that interpretation. The field type characters are listed
- * in the table at the end of this section. The flag characters are:
- *
- * Flag | Applies to | Meaning
- * ---------+--------------+-----------------------------------------
- * space | bdeEfgGioxXu | Leave a space at the start of
- * | | positive numbers.
- * ---------+--------------+-----------------------------------------
- * (digit)$ | all | Specifies the absolute argument number
- * | | for this field. Absolute and relative
- * | | argument numbers cannot be mixed in a
- * | | sprintf string.
- * ---------+--------------+-----------------------------------------
- * # | beEfgGoxX | Use an alternative format. For the
- * | | conversions `o', `x', `X', and `b',
- * | | prefix the result with ``0'', ``0x'', ``0X'',
- * | | and ``0b'', respectively. For `e',
- * | | `E', `f', `g', and 'G', force a decimal
- * | | point to be added, even if no digits follow.
- * | | For `g' and 'G', do not remove trailing zeros.
- * ---------+--------------+-----------------------------------------
- * + | bdeEfgGioxXu | Add a leading plus sign to positive numbers.
- * ---------+--------------+-----------------------------------------
- * - | all | Left-justify the result of this conversion.
- * ---------+--------------+-----------------------------------------
- * 0 (zero) | all | Pad with zeros, not spaces.
- * ---------+--------------+-----------------------------------------
- * * | all | Use the next argument as the field width.
- * | | If negative, left-justify the result. If the
- * | | asterisk is followed by a number and a dollar
- * | | sign, use the indicated argument as the width.
- *
- *
- * The field width is an optional integer, followed optionally by a
- * period and a precision. The width specifies the minimum number of
- * characters that will be written to the result for this field. For
- * numeric fields, the precision controls the number of decimal places
- * displayed. For string fields, the precision determines the maximum
- * number of characters to be copied from the string. (Thus, the format
- * sequence <code>%10.10s</code> will always contribute exactly ten
- * characters to the result.)
- *
- * The field types are:
- *
- * Field | Conversion
- * ------+--------------------------------------------------------------
- * b | Convert argument as a binary number.
- * c | Argument is the numeric code for a single character.
- * d | Convert argument as a decimal number.
- * E | Equivalent to `e', but uses an uppercase E to indicate
- * | the exponent.
- * e | Convert floating point argument into exponential notation
- * | with one digit before the decimal point. The precision
- * | determines the number of fractional digits (defaulting to six).
- * f | Convert floating point argument as [-]ddd.ddd,
- * | where the precision determines the number of digits after
- * | the decimal point.
- * G | Equivalent to `g', but use an uppercase `E' in exponent form.
- * g | Convert a floating point number using exponential form
- * | if the exponent is less than -4 or greater than or
- * | equal to the precision, or in d.dddd form otherwise.
- * i | Identical to `d'.
- * o | Convert argument as an octal number.
- * p | The valuing of argument.inspect.
- * s | Argument is a string to be substituted. If the format
- * | sequence contains a precision, at most that many characters
- * | will be copied.
- * u | Treat argument as an unsigned decimal number.
- * X | Convert argument as a hexadecimal number using uppercase
- * | letters. Negative numbers will be displayed with two
- * | leading periods (representing an infinite string of
- * | leading 'FF's.
- * x | Convert argument as a hexadecimal number.
- * | Negative numbers will be displayed with two
- * | leading periods (representing an infinite string of
- * | leading 'ff's.
- *
- * Examples:
- *
- * sprintf("%d %04x", 123, 123) #=> "123 007b"
- * sprintf("%08b '%4s'", 123, 123) #=> "01111011 ' 123'"
- * sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello"
- * sprintf("%1$*2$s %2$d", "hello", -8) #=> "hello -8"
- * sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23) #=> "+1.23: 1.23:1.23"
- */
-
-VALUE
-rb_f_sprintf(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE fmt;
- const char *p, *end;
- char *buf;
- int blen, bsiz;
- VALUE result;
-
- int width, prec, flags = FNONE;
- int nextarg = 1;
- int posarg = 0;
- int tainted = 0;
- VALUE nextvalue;
- VALUE tmp;
- VALUE str;
-
- fmt = GETNTHARG(0);
- if (OBJ_TAINTED(fmt)) tainted = 1;
- StringValue(fmt);
- fmt = rb_str_new4(fmt);
- p = RSTRING(fmt)->ptr;
- end = p + RSTRING(fmt)->len;
- blen = 0;
- bsiz = 120;
- result = rb_str_buf_new(bsiz);
- buf = RSTRING(result)->ptr;
-
- for (; p < end; p++) {
- const char *t;
- int n;
-
- for (t = p; t < end && *t != '%'; t++) ;
- PUSH(p, t - p);
- if (t >= end) {
- /* end of fmt string */
- goto sprint_exit;
- }
- p = t + 1; /* skip `%' */
-
- width = prec = -1;
- nextvalue = Qundef;
- retry:
- switch (*p) {
- default:
- if (ISPRINT(*p))
- rb_raise(rb_eArgError, "malformed format string - %%%c", *p);
- else
- rb_raise(rb_eArgError, "malformed format string");
- break;
-
- case ' ':
- flags |= FSPACE;
- p++;
- goto retry;
-
- case '#':
- flags |= FSHARP;
- p++;
- goto retry;
-
- case '+':
- flags |= FPLUS;
- p++;
- goto retry;
-
- case '-':
- flags |= FMINUS;
- p++;
- goto retry;
-
- case '0':
- flags |= FZERO;
- p++;
- goto retry;
-
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = 0;
- for (; p < end && ISDIGIT(*p); p++) {
- n = 10 * n + (*p - '0');
- }
- if (p >= end) {
- rb_raise(rb_eArgError, "malformed format string - %%[0-9]");
- }
- if (*p == '$') {
- if (nextvalue != Qundef) {
- rb_raise(rb_eArgError, "value given twice - %d$", n);
- }
- nextvalue = GETPOSARG(n);
- p++;
- goto retry;
- }
- width = n;
- flags |= FWIDTH;
- goto retry;
-
- case '*':
- if (flags & FWIDTH) {
- rb_raise(rb_eArgError, "width given twice");
- }
-
- flags |= FWIDTH;
- GETASTER(width);
- if (width < 0) {
- flags |= FMINUS;
- width = -width;
- }
- p++;
- goto retry;
-
- case '.':
- if (flags & FPREC) {
- rb_raise(rb_eArgError, "precision given twice");
- }
- flags |= FPREC;
-
- prec = 0;
- p++;
- if (*p == '*') {
- GETASTER(prec);
- if (prec < 0) { /* ignore negative precision */
- flags &= ~FPREC;
- }
- p++;
- goto retry;
- }
-
- for (; p < end && ISDIGIT(*p); p++) {
- prec = 10 * prec + (*p - '0');
- }
- if (p >= end) {
- rb_raise(rb_eArgError, "malformed format string - %%.[0-9]");
- }
- goto retry;
-
- case '\n':
- p--;
- case '\0':
- case '%':
- if (flags != FNONE) {
- rb_raise(rb_eArgError, "illegal format character - %%");
- }
- PUSH("%", 1);
- break;
-
- case 'c':
- {
- VALUE val = GETARG();
- char c;
-
- if (!(flags & FMINUS))
- while (--width > 0)
- PUSH(" ", 1);
- c = NUM2INT(val) & 0xff;
- PUSH(&c, 1);
- while (--width > 0)
- PUSH(" ", 1);
- }
- break;
-
- case 's':
- case 'p':
- {
- VALUE arg = GETARG();
- long len;
-
- if (*p == 'p') arg = rb_inspect(arg);
- str = rb_obj_as_string(arg);
- if (OBJ_TAINTED(str)) tainted = 1;
- len = RSTRING(str)->len;
- if (flags&FPREC) {
- if (prec < len) {
- len = prec;
- }
- }
- if (flags&FWIDTH) {
- if (width > len) {
- CHECK(width);
- width -= len;
- if (!(flags&FMINUS)) {
- while (width--) {
- buf[blen++] = ' ';
- }
- }
- memcpy(&buf[blen], RSTRING(str)->ptr, len);
- blen += len;
- if (flags&FMINUS) {
- while (width--) {
- buf[blen++] = ' ';
- }
- }
- break;
- }
- }
- PUSH(RSTRING(str)->ptr, len);
- }
- break;
-
- case 'd':
- case 'i':
- case 'o':
- case 'x':
- case 'X':
- case 'b':
- case 'B':
- case 'u':
- {
- volatile VALUE val = GETARG();
- char fbuf[32], nbuf[64], *s, *t;
- char *prefix = 0;
- int sign = 0;
- char sc = 0;
- long v = 0;
- int base, bignum = 0;
- int len, pos;
-
- switch (*p) {
- case 'd':
- case 'i':
- sign = 1; break;
- case 'o':
- case 'x':
- case 'X':
- case 'b':
- case 'B':
- case 'u':
- default:
- if (flags&(FPLUS|FSPACE)) sign = 1;
- break;
- }
- if (flags & FSHARP) {
- switch (*p) {
- case 'o':
- prefix = "0"; break;
- case 'x':
- prefix = "0x"; break;
- case 'X':
- prefix = "0X"; break;
- case 'b':
- prefix = "0b"; break;
- case 'B':
- prefix = "0B"; break;
- }
- if (prefix) {
- width -= strlen(prefix);
- }
- }
-
- bin_retry:
- switch (TYPE(val)) {
- case T_FLOAT:
- val = rb_dbl2big(RFLOAT(val)->value);
- if (FIXNUM_P(val)) goto bin_retry;
- bignum = 1;
- break;
- case T_STRING:
- val = rb_str_to_inum(val, 0, Qtrue);
- goto bin_retry;
- case T_BIGNUM:
- bignum = 1;
- break;
- case T_FIXNUM:
- v = FIX2LONG(val);
- break;
- default:
- val = rb_Integer(val);
- goto bin_retry;
- }
-
- switch (*p) {
- case 'o':
- base = 8; break;
- case 'x':
- case 'X':
- base = 16; break;
- case 'b':
- case 'B':
- base = 2; break;
- case 'u':
- case 'd':
- case 'i':
- default:
- base = 10; break;
- }
-
- if (!bignum) {
- if (base == 2) {
- val = rb_int2big(v);
- goto bin_retry;
- }
- if (sign) {
- char c = *p;
- if (c == 'i') c = 'd'; /* %d and %i are identical */
- if (v < 0) {
- v = -v;
- sc = '-';
- width--;
- }
- else if (flags & FPLUS) {
- sc = '+';
- width--;
- }
- else if (flags & FSPACE) {
- sc = ' ';
- width--;
- }
- sprintf(fbuf, "%%l%c", c);
- sprintf(nbuf, fbuf, v);
- }
- else {
- s = nbuf;
- if (v < 0) {
- if (base == 10) {
- rb_warning("negative number for %%u specifier");
- }
- else if (!(flags&(FPREC|FZERO))) {
- strcpy(s, "..");
- s += 2;
- }
- }
- sprintf(fbuf, "%%l%c", *p == 'X' ? 'x' : *p);
- sprintf(s, fbuf, v);
- if (v < 0) {
- char d = 0;
-
- remove_sign_bits(s, base);
- switch (base) {
- case 16:
- d = 'f'; break;
- case 8:
- d = '7'; break;
- }
- if (d && *s != d) {
- memmove(s+1, s, strlen(s)+1);
- *s = d;
- }
- }
- }
- s = nbuf;
- }
- else {
- if (sign) {
- tmp = rb_big2str(val, base);
- s = RSTRING(tmp)->ptr;
- if (s[0] == '-') {
- s++;
- sc = '-';
- width--;
- }
- else if (flags & FPLUS) {
- sc = '+';
- width--;
- }
- else if (flags & FSPACE) {
- sc = ' ';
- width--;
- }
- }
- else {
- if (!RBIGNUM(val)->sign) {
- val = rb_big_clone(val);
- rb_big_2comp(val);
- }
- tmp = rb_big2str(val, base);
- s = RSTRING(tmp)->ptr;
- if (*s == '-') {
- if (base == 10) {
- rb_warning("negative number for %%u specifier");
- }
- else {
- remove_sign_bits(++s, base);
- tmp = rb_str_new(0, 3+strlen(s));
- t = RSTRING(tmp)->ptr;
- if (!(flags&(FPREC|FZERO))) {
- strcpy(t, "..");
- t += 2;
- }
- switch (base) {
- case 16:
- if (s[0] != 'f') strcpy(t++, "f"); break;
- case 8:
- if (s[0] != '7') strcpy(t++, "7"); break;
- case 2:
- if (s[0] != '1') strcpy(t++, "1"); break;
- }
- strcpy(t, s);
- s = RSTRING(tmp)->ptr;
- }
- }
- }
- }
-
- pos = -1;
- len = strlen(s);
-
- if (*p == 'X') {
- char *pp = s;
- while (*pp) {
- *pp = toupper(*pp);
- pp++;
- }
- }
- if ((flags&(FZERO|FPREC)) == FZERO) {
- prec = width;
- width = 0;
- }
- else {
- if (prec < len) prec = len;
- width -= prec;
- }
- if (!(flags&FMINUS)) {
- CHECK(width);
- while (width-- > 0) {
- buf[blen++] = ' ';
- }
- }
- if (sc) PUSH(&sc, 1);
- if (prefix) {
- int plen = strlen(prefix);
- PUSH(prefix, plen);
- }
- CHECK(prec - len);
- if (!bignum && v < 0) {
- char c = sign_bits(base, p);
- while (len < prec--) {
- buf[blen++] = c;
- }
- }
- else {
- char c;
-
- if (!sign && bignum && !RBIGNUM(val)->sign)
- c = sign_bits(base, p);
- else
- c = '0';
- while (len < prec--) {
- buf[blen++] = c;
- }
- }
- PUSH(s, len);
- CHECK(width);
- while (width-- > 0) {
- buf[blen++] = ' ';
- }
- }
- break;
-
- case 'f':
- case 'g':
- case 'G':
- case 'e':
- case 'E':
- {
- VALUE val = GETARG();
- double fval;
- int i, need = 6;
- char fbuf[32];
-
- fval = RFLOAT(rb_Float(val))->value;
- if (isnan(fval) || isinf(fval)) {
- char *expr;
-
- if (isnan(fval)) {
- expr = "NaN";
- }
- else {
- expr = "Inf";
- }
- need = strlen(expr);
- if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS))
- need++;
- if ((flags & FWIDTH) && need < width)
- need = width;
-
- CHECK(need);
- sprintf(&buf[blen], "%*s", need, "");
- if (flags & FMINUS) {
- if (!isnan(fval) && fval < 0.0)
- buf[blen++] = '-';
- else if (flags & FPLUS)
- buf[blen++] = '+';
- else if (flags & FSPACE)
- blen++;
- strncpy(&buf[blen], expr, strlen(expr));
- }
- else if (flags & FZERO) {
- if (!isnan(fval) && fval < 0.0) {
- buf[blen++] = '-';
- need--;
- }
- else if (flags & FPLUS) {
- buf[blen++] = '+';
- need--;
- }
- else if (flags & FSPACE) {
- blen++;
- need--;
- }
- while (need-- - strlen(expr) > 0) {
- buf[blen++] = '0';
- }
- strncpy(&buf[blen], expr, strlen(expr));
- }
- else {
- if (!isnan(fval) && fval < 0.0)
- buf[blen + need - strlen(expr) - 1] = '-';
- else if (flags & FPLUS)
- buf[blen + need - strlen(expr) - 1] = '+';
- strncpy(&buf[blen + need - strlen(expr)], expr,
- strlen(expr));
- }
- blen += strlen(&buf[blen]);
- break;
- }
-
- fmt_setup(fbuf, *p, flags, width, prec);
- need = 0;
- if (*p != 'e' && *p != 'E') {
- i = INT_MIN;
- frexp(fval, &i);
- if (i > 0)
- need = BIT_DIGITS(i);
- }
- need += (flags&FPREC) ? prec : 6;
- if ((flags&FWIDTH) && need < width)
- need = width;
- need += 20;
-
- CHECK(need);
- sprintf(&buf[blen], fbuf, fval);
- blen += strlen(&buf[blen]);
- }
- break;
- }
- flags = FNONE;
- }
-
- sprint_exit:
- /* XXX - We cannot validiate the number of arguments if (digit)$ style used.
- */
- if (RTEST(ruby_verbose) && posarg >= 0 && nextarg < argc) {
- rb_raise(rb_eArgError, "too many arguments for format string");
- }
- rb_str_resize(result, blen);
-
- if (tainted) OBJ_TAINT(result);
- return result;
-}
-
-static void
-fmt_setup(buf, c, flags, width, prec)
- char *buf;
- int c;
- int flags, width, prec;
-{
- *buf++ = '%';
- if (flags & FSHARP) *buf++ = '#';
- if (flags & FPLUS) *buf++ = '+';
- if (flags & FMINUS) *buf++ = '-';
- if (flags & FZERO) *buf++ = '0';
- if (flags & FSPACE) *buf++ = ' ';
-
- if (flags & FWIDTH) {
- sprintf(buf, "%d", width);
- buf += strlen(buf);
- }
-
- if (flags & FPREC) {
- sprintf(buf, ".%d", prec);
- buf += strlen(buf);
- }
-
- *buf++ = c;
- *buf = '\0';
-}
-/* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */
-
-/* static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */
-
-#include "config.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef _WIN32
-#include <malloc.h>
-#endif
-
-#ifdef NOT_RUBY
-#include "regint.h"
-#else
-#ifdef RUBY_PLATFORM
-#define xmalloc ruby_xmalloc
-#define xcalloc ruby_xcalloc
-#define xrealloc ruby_xrealloc
-#define xfree ruby_xfree
-
-void *xmalloc(long);
-void *xcalloc(long, long);
-void *xrealloc(void *, long);
-void xfree(void *);
-#endif
-#endif
-
-#include "st.h"
-
-typedef struct st_table_entry st_table_entry;
-
-struct st_table_entry {
- unsigned int hash;
- st_data_t key;
- st_data_t record;
- st_table_entry *next;
-};
-
-#define ST_DEFAULT_MAX_DENSITY 5
-#define ST_DEFAULT_INIT_TABLE_SIZE 11
-
- /*
- * DEFAULT_MAX_DENSITY is the default for the largest we allow the
- * average number of items per bin before increasing the number of
- * bins
- *
- * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins
- * allocated initially
- *
- */
-
-static int numcmp(long, long);
-static int numhash(long);
-static struct st_hash_type type_numhash = {
- numcmp,
- numhash,
-};
-
-/* extern int strcmp(const char *, const char *); */
-static int strhash(const char *);
-static struct st_hash_type type_strhash = {
- strcmp,
- strhash,
-};
-
-static void rehash(st_table *);
-
-#define alloc(type) (type*)xmalloc((unsigned)sizeof(type))
-#define Calloc(n,s) (char*)xcalloc((n),(s))
-
-#define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)((x),(y)) == 0)
-
-#define do_hash(key,table) (unsigned int)(*(table)->type->hash)((key))
-#define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins)
-
-/*
- * MINSIZE is the minimum size of a dictionary.
- */
-
-#define MINSIZE 8
-
-/*
-Table of prime numbers 2^n+a, 2<=n<=30.
-*/
-static long primes[] = {
- 8 + 3,
- 16 + 3,
- 32 + 5,
- 64 + 3,
- 128 + 3,
- 256 + 27,
- 512 + 9,
- 1024 + 9,
- 2048 + 5,
- 4096 + 3,
- 8192 + 27,
- 16384 + 43,
- 32768 + 3,
- 65536 + 45,
- 131072 + 29,
- 262144 + 3,
- 524288 + 21,
- 1048576 + 7,
- 2097152 + 17,
- 4194304 + 15,
- 8388608 + 9,
- 16777216 + 43,
- 33554432 + 35,
- 67108864 + 15,
- 134217728 + 29,
- 268435456 + 3,
- 536870912 + 11,
- 1073741824 + 85,
- 0
-};
-
-static int
-new_size(size)
- int size;
-{
- int i;
-
-#if 0
- for (i=3; i<31; i++) {
- if ((1<<i) > size) return 1<<i;
- }
- return -1;
-#else
- int newsize;
-
- for (i = 0, newsize = MINSIZE;
- i < (int )(sizeof(primes)/sizeof(primes[0]));
- i++, newsize <<= 1)
- {
- if (newsize > size) return primes[i];
- }
- /* Ran out of polynomials */
- return -1; /* should raise exception */
-#endif
-}
-
-#ifdef HASH_LOG
-static int collision = 0;
-static int init_st = 0;
-
-static void
-stat_col()
-{
- FILE *f = fopen("/tmp/col", "w");
- fprintf(f, "collision: %d\n", collision);
- fclose(f);
-}
-#endif
-
-st_table*
-st_init_table_with_size(type, size)
- struct st_hash_type *type;
- int size;
-{
- st_table *tbl;
-
-#ifdef HASH_LOG
- if (init_st == 0) {
- init_st = 1;
- atexit(stat_col);
- }
-#endif
-
- size = new_size(size); /* round up to prime number */
-
- tbl = alloc(st_table);
- tbl->type = type;
- tbl->num_entries = 0;
- tbl->num_bins = size;
- tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*));
-
- return tbl;
-}
-
-st_table*
-st_init_table(type)
- struct st_hash_type *type;
-{
- return st_init_table_with_size(type, 0);
-}
-
-st_table*
-st_init_numtable(void)
-{
- return st_init_table(&type_numhash);
-}
-
-st_table*
-st_init_numtable_with_size(size)
- int size;
-{
- return st_init_table_with_size(&type_numhash, size);
-}
-
-st_table*
-st_init_strtable(void)
-{
- return st_init_table(&type_strhash);
-}
-
-st_table*
-st_init_strtable_with_size(size)
- int size;
-{
- return st_init_table_with_size(&type_strhash, size);
-}
-
-void
-st_free_table(table)
- st_table *table;
-{
- register st_table_entry *ptr, *next;
- int i;
-
- for(i = 0; i < table->num_bins; i++) {
- ptr = table->bins[i];
- while (ptr != 0) {
- next = ptr->next;
- free(ptr);
- ptr = next;
- }
- }
- free(table->bins);
- free(table);
-}
-
-#define PTR_NOT_EQUAL(table, ptr, hash_val, key) \
-((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key)))
-
-#ifdef HASH_LOG
-#define COLLISION collision++
-#else
-#define COLLISION
-#endif
-
-#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\
- bin_pos = hash_val%(table)->num_bins;\
- ptr = (table)->bins[bin_pos];\
- if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\
- COLLISION;\
- while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\
- ptr = ptr->next;\
- }\
- ptr = ptr->next;\
- }\
-} while (0)
-
-int
-st_lookup(table, key, value)
- st_table *table;
- register st_data_t key;
- st_data_t *value;
-{
- unsigned int hash_val, bin_pos;
- register st_table_entry *ptr;
-
- hash_val = do_hash(key, table);
- FIND_ENTRY(table, ptr, hash_val, bin_pos);
-
- if (ptr == 0) {
- return 0;
- }
- else {
- if (value != 0) *value = ptr->record;
- return 1;
- }
-}
-
-#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\
-do {\
- st_table_entry *entry;\
- if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) {\
- rehash(table);\
- bin_pos = hash_val % table->num_bins;\
- }\
- \
- entry = alloc(st_table_entry);\
- \
- entry->hash = hash_val;\
- entry->key = key;\
- entry->record = value;\
- entry->next = table->bins[bin_pos];\
- table->bins[bin_pos] = entry;\
- table->num_entries++;\
-} while (0)
-
-int
-st_insert(table, key, value)
- register st_table *table;
- register st_data_t key;
- st_data_t value;
-{
- unsigned int hash_val, bin_pos;
- register st_table_entry *ptr;
-
- hash_val = do_hash(key, table);
- FIND_ENTRY(table, ptr, hash_val, bin_pos);
-
- if (ptr == 0) {
- ADD_DIRECT(table, key, value, hash_val, bin_pos);
- return 0;
- }
- else {
- ptr->record = value;
- return 1;
- }
-}
-
-void
-st_add_direct(table, key, value)
- st_table *table;
- st_data_t key;
- st_data_t value;
-{
- unsigned int hash_val, bin_pos;
-
- hash_val = do_hash(key, table);
- bin_pos = hash_val % table->num_bins;
- ADD_DIRECT(table, key, value, hash_val, bin_pos);
-}
-
-static void
-rehash(table)
- register st_table *table;
-{
- register st_table_entry *ptr, *next, **new_bins;
- int i, old_num_bins = table->num_bins, new_num_bins;
- unsigned int hash_val;
-
- new_num_bins = new_size(old_num_bins+1);
- new_bins = (st_table_entry**)Calloc(new_num_bins, sizeof(st_table_entry*));
-
- for(i = 0; i < old_num_bins; i++) {
- ptr = table->bins[i];
- while (ptr != 0) {
- next = ptr->next;
- hash_val = ptr->hash % new_num_bins;
- ptr->next = new_bins[hash_val];
- new_bins[hash_val] = ptr;
- ptr = next;
- }
- }
- free(table->bins);
- table->num_bins = new_num_bins;
- table->bins = new_bins;
-}
-
-st_table*
-st_copy(old_table)
- st_table *old_table;
-{
- st_table *new_table;
- st_table_entry *ptr, *entry;
- int i, num_bins = old_table->num_bins;
-
- new_table = alloc(st_table);
- if (new_table == 0) {
- return 0;
- }
-
- *new_table = *old_table;
- new_table->bins = (st_table_entry**)
- Calloc((unsigned)num_bins, sizeof(st_table_entry*));
-
- if (new_table->bins == 0) {
- free(new_table);
- return 0;
- }
-
- for(i = 0; i < num_bins; i++) {
- new_table->bins[i] = 0;
- ptr = old_table->bins[i];
- while (ptr != 0) {
- entry = alloc(st_table_entry);
- if (entry == 0) {
- free(new_table->bins);
- free(new_table);
- return 0;
- }
- *entry = *ptr;
- entry->next = new_table->bins[i];
- new_table->bins[i] = entry;
- ptr = ptr->next;
- }
- }
- return new_table;
-}
-
-int
-st_delete(table, key, value)
- register st_table *table;
- register st_data_t *key;
- st_data_t *value;
-{
- unsigned int hash_val;
- st_table_entry *tmp;
- register st_table_entry *ptr;
-
- hash_val = do_hash_bin(*key, table);
- ptr = table->bins[hash_val];
-
- if (ptr == 0) {
- if (value != 0) *value = 0;
- return 0;
- }
-
- if (EQUAL(table, *key, ptr->key)) {
- table->bins[hash_val] = ptr->next;
- table->num_entries--;
- if (value != 0) *value = ptr->record;
- *key = ptr->key;
- free(ptr);
- return 1;
- }
-
- for(; ptr->next != 0; ptr = ptr->next) {
- if (EQUAL(table, ptr->next->key, *key)) {
- tmp = ptr->next;
- ptr->next = ptr->next->next;
- table->num_entries--;
- if (value != 0) *value = tmp->record;
- *key = tmp->key;
- free(tmp);
- return 1;
- }
- }
-
- return 0;
-}
-
-int
-st_delete_safe(table, key, value, never)
- register st_table *table;
- register st_data_t *key;
- st_data_t *value;
- st_data_t never;
-{
- unsigned int hash_val;
- register st_table_entry *ptr;
-
- hash_val = do_hash_bin(*key, table);
- ptr = table->bins[hash_val];
-
- if (ptr == 0) {
- if (value != 0) *value = 0;
- return 0;
- }
-
- for(; ptr != 0; ptr = ptr->next) {
- if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) {
- table->num_entries--;
- *key = ptr->key;
- if (value != 0) *value = ptr->record;
- ptr->key = ptr->record = never;
- return 1;
- }
- }
-
- return 0;
-}
-
-static int
-delete_never(key, value, never)
- st_data_t key, value, never;
-{
- if (value == never) return ST_DELETE;
- return ST_CONTINUE;
-}
-
-void
-st_cleanup_safe(table, never)
- st_table *table;
- st_data_t never;
-{
- int num_entries = table->num_entries;
-
- st_foreach(table, delete_never, never);
- table->num_entries = num_entries;
-}
-
-int
-st_foreach(table, func, arg)
- st_table *table;
- int (*func)();
- st_data_t arg;
-{
- st_table_entry *ptr, *last, *tmp;
- enum st_retval retval;
- int i;
-
- for(i = 0; i < table->num_bins; i++) {
- last = 0;
- for(ptr = table->bins[i]; ptr != 0;) {
- retval = (*func)(ptr->key, ptr->record, arg);
- switch (retval) {
- case ST_CHECK: /* check if hash is modified during iteration */
- tmp = 0;
- if (i < table->num_bins) {
- for (tmp = table->bins[i]; tmp; tmp=tmp->next) {
- if (tmp == ptr) break;
- }
- }
- if (!tmp) {
- /* call func with error notice */
- return 1;
- }
- /* fall through */
- case ST_CONTINUE:
- last = ptr;
- ptr = ptr->next;
- break;
- case ST_STOP:
- return 0;
- case ST_DELETE:
- tmp = ptr;
- if (last == 0) {
- table->bins[i] = ptr->next;
- }
- else {
- last->next = ptr->next;
- }
- ptr = ptr->next;
- free(tmp);
- table->num_entries--;
- }
- }
- }
- return 0;
-}
-
-static int
-strhash(string)
- register const char *string;
-{
- register int c;
-
-#ifdef HASH_ELFHASH
- register unsigned int h = 0, g;
-
- while ((c = *string++) != '\0') {
- h = ( h << 4 ) + c;
- if ( g = h & 0xF0000000 )
- h ^= g >> 24;
- h &= ~g;
- }
- return h;
-#elif HASH_PERL
- register int val = 0;
-
- while ((c = *string++) != '\0') {
- val += c;
- val += (val << 10);
- val ^= (val >> 6);
- }
- val += (val << 3);
- val ^= (val >> 11);
-
- return val + (val << 15);
-#else
- register int val = 0;
-
- while ((c = *string++) != '\0') {
- val = val*997 + c;
- }
-
- return val + (val>>5);
-#endif
-}
-
-static int
-numcmp(x, y)
- long x, y;
-{
- return x != y;
-}
-
-static int
-numhash(n)
- long n;
-{
- return n;
-}
-/**********************************************************************
-
- string.c -
-
- $Author: matz $
- $Date: 2005/03/04 06:47:41 $
- created at: Mon Aug 9 17:12:58 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 "re.h"
-
-#define BEG(no) regs->beg[no]
-#define END(no) regs->end[no]
-
-#include <math.h>
-#include <ctype.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-VALUE rb_cString;
-
-#define STR_TMPLOCK FL_USER1
-#define STR_ASSOC FL_USER3
-#define STR_NOCAPA (ELTS_SHARED|STR_ASSOC)
-
-#define RESIZE_CAPA(str,capacity) do {\
- REALLOC_N(RSTRING(str)->ptr, char, (capacity)+1);\
- if (!FL_TEST(str, STR_NOCAPA))\
- RSTRING(str)->aux.capa = (capacity);\
-} while (0)
-
-VALUE rb_fs;
-
-static inline void
-str_mod_check(s, p, len)
- VALUE s;
- char *p;
- long len;
-{
- if (RSTRING(s)->ptr != p || RSTRING(s)->len != len){
- rb_raise(rb_eRuntimeError, "string modified");
- }
-}
-
-static inline void
-str_frozen_check(s)
- VALUE s;
-{
- if (OBJ_FROZEN(s)) {
- rb_raise(rb_eRuntimeError, "string frozen");
- }
-}
-
-static VALUE str_alloc _((VALUE));
-static VALUE
-str_alloc(klass)
- VALUE klass;
-{
- NEWOBJ(str, struct RString);
- OBJSETUP(str, klass, T_STRING);
-
- str->ptr = 0;
- str->len = 0;
- str->aux.capa = 0;
-
- return (VALUE)str;
-}
-
-static VALUE
-str_new(klass, ptr, len)
- VALUE klass;
- const char *ptr;
- long len;
-{
- VALUE str;
-
- if (len < 0) {
- rb_raise(rb_eArgError, "negative string size (or size too big)");
- }
-
- str = str_alloc(klass);
- RSTRING(str)->len = len;
- RSTRING(str)->aux.capa = len;
- RSTRING(str)->ptr = ALLOC_N(char,len+1);
- if (ptr) {
- memcpy(RSTRING(str)->ptr, ptr, len);
- }
- RSTRING(str)->ptr[len] = '\0';
- return str;
-}
-
-VALUE
-rb_str_new(ptr, len)
- const char *ptr;
- long len;
-{
- return str_new(rb_cString, ptr, len);
-}
-
-VALUE
-rb_str_new2(ptr)
- const char *ptr;
-{
- if (!ptr) {
- rb_raise(rb_eArgError, "NULL pointer given");
- }
- return rb_str_new(ptr, strlen(ptr));
-}
-
-VALUE
-rb_tainted_str_new(ptr, len)
- const char *ptr;
- long len;
-{
- VALUE str = rb_str_new(ptr, len);
-
- OBJ_TAINT(str);
- return str;
-}
-
-VALUE
-rb_tainted_str_new2(ptr)
- const char *ptr;
-{
- VALUE str = rb_str_new2(ptr);
-
- OBJ_TAINT(str);
- return str;
-}
-
-static VALUE
-str_new3(klass, str)
- VALUE klass, str;
-{
- VALUE str2 = str_alloc(klass);
-
- RSTRING(str2)->len = RSTRING(str)->len;
- RSTRING(str2)->ptr = RSTRING(str)->ptr;
- RSTRING(str2)->aux.shared = str;
- FL_SET(str2, ELTS_SHARED);
- OBJ_INFECT(str2, str);
-
- return str2;
-}
-
-VALUE
-rb_str_new3(str)
- VALUE str;
-{
- return str_new3(rb_obj_class(str), str);
-}
-
-static VALUE
-str_new4(klass, str)
- VALUE klass, str;
-{
- VALUE str2 = str_alloc(klass);
-
- RSTRING(str2)->len = RSTRING(str)->len;
- RSTRING(str2)->ptr = RSTRING(str)->ptr;
- if (FL_TEST(str, ELTS_SHARED)) {
- FL_SET(str2, ELTS_SHARED);
- RSTRING(str2)->aux.shared = RSTRING(str)->aux.shared;
- }
- else {
- FL_SET(str, ELTS_SHARED);
- RSTRING(str)->aux.shared = str2;
- }
-
- return str2;
-}
-
-VALUE
-rb_str_new4(orig)
- VALUE orig;
-{
- VALUE klass, str;
-
- if (OBJ_FROZEN(orig)) return orig;
- klass = rb_obj_class(orig);
- if (FL_TEST(orig, ELTS_SHARED) && (str = RSTRING(orig)->aux.shared) && klass == RBASIC(str)->klass) {
- long ofs;
- ofs = RSTRING(str)->len - RSTRING(orig)->len;
- if (ofs > 0) {
- str = str_new3(klass, str);
- RSTRING(str)->ptr += ofs;
- RSTRING(str)->len -= ofs;
- }
- }
- else if (FL_TEST(orig, STR_ASSOC)) {
- str = str_new(klass, RSTRING(orig)->ptr, RSTRING(orig)->len);
- }
- else {
- str = str_new4(klass, orig);
- }
- OBJ_INFECT(str, orig);
- OBJ_FREEZE(str);
- return str;
-}
-
-VALUE
-rb_str_new5(obj, ptr, len)
- VALUE obj;
- const char *ptr;
- long len;
-{
- return str_new(rb_obj_class(obj), ptr, len);
-}
-
-#define STR_BUF_MIN_SIZE 128
-
-VALUE
-rb_str_buf_new(capa)
- long capa;
-{
- VALUE str = str_alloc(rb_cString);
-
- if (capa < STR_BUF_MIN_SIZE) {
- capa = STR_BUF_MIN_SIZE;
- }
- RSTRING(str)->ptr = 0;
- RSTRING(str)->len = 0;
- RSTRING(str)->aux.capa = capa;
- RSTRING(str)->ptr = ALLOC_N(char, capa+1);
- RSTRING(str)->ptr[0] = '\0';
-
- return str;
-}
-
-VALUE
-rb_str_buf_new2(ptr)
- const char *ptr;
-{
- VALUE str;
- long len = strlen(ptr);
-
- str = rb_str_buf_new(len);
- rb_str_buf_cat(str, ptr, len);
-
- return str;
-}
-
-VALUE
-rb_str_to_str(str)
- VALUE str;
-{
- return rb_convert_type(str, T_STRING, "String", "to_str");
-}
-
-static void
-rb_str_shared_replace(str, str2)
- VALUE str, str2;
-{
- if (str == str2) return;
- rb_str_modify(str);
- if (!FL_TEST(str, ELTS_SHARED)) free(RSTRING(str)->ptr);
- RSTRING(str)->ptr = RSTRING(str2)->ptr;
- RSTRING(str)->len = RSTRING(str2)->len;
- FL_UNSET(str, STR_NOCAPA);
- if (FL_TEST(str2, STR_NOCAPA)) {
- FL_SET(str, RBASIC(str2)->flags & STR_NOCAPA);
- RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared;
- }
- else {
- RSTRING(str)->aux.capa = RSTRING(str2)->aux.capa;
- }
- RSTRING(str2)->ptr = 0; /* abandon str2 */
- RSTRING(str2)->len = 0;
- RSTRING(str2)->aux.capa = 0;
- FL_UNSET(str2, STR_NOCAPA);
- if (OBJ_TAINTED(str2)) OBJ_TAINT(str);
-}
-
-static ID id_to_s;
-
-VALUE
-rb_obj_as_string(obj)
- VALUE obj;
-{
- VALUE str;
-
- if (TYPE(obj) == T_STRING) {
- return obj;
- }
- str = rb_funcall(obj, id_to_s, 0);
- if (TYPE(str) != T_STRING)
- return rb_any_to_s(obj);
- if (OBJ_TAINTED(obj)) OBJ_TAINT(str);
- return str;
-}
-
-static VALUE rb_str_replace _((VALUE, VALUE));
-
-VALUE
-rb_str_dup(str)
- VALUE str;
-{
- VALUE dup = str_alloc(rb_obj_class(str));
- rb_str_replace(dup, str);
- return dup;
-}
-
-
-/*
- * call-seq:
- * String.new(str="") => new_str
- *
- * Returns a new string object containing a copy of <i>str</i>.
- */
-
-static VALUE
-rb_str_init(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- VALUE orig;
-
- if (rb_scan_args(argc, argv, "01", &orig) == 1)
- rb_str_replace(str, orig);
- return str;
-}
-
-/*
- * call-seq:
- * str.length => integer
- *
- * Returns the length of <i>str</i>.
- */
-
-static VALUE
-rb_str_length(str)
- VALUE str;
-{
- return LONG2NUM(RSTRING(str)->len);
-}
-
-/*
- * call-seq:
- * str.empty? => true or false
- *
- * Returns <code>true</code> if <i>str</i> has a length of zero.
- *
- * "hello".empty? #=> false
- * "".empty? #=> true
- */
-
-static VALUE
-rb_str_empty(str)
- VALUE str;
-{
- if (RSTRING(str)->len == 0)
- return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * str + other_str => new_str
- *
- * Concatenation---Returns a new <code>String</code> containing
- * <i>other_str</i> concatenated to <i>str</i>.
- *
- * "Hello from " + self.to_s #=> "Hello from main"
- */
-
-VALUE
-rb_str_plus(str1, str2)
- VALUE str1, str2;
-{
- VALUE str3;
-
- StringValue(str2);
- str3 = rb_str_new(0, RSTRING(str1)->len+RSTRING(str2)->len);
- memcpy(RSTRING(str3)->ptr, RSTRING(str1)->ptr, RSTRING(str1)->len);
- memcpy(RSTRING(str3)->ptr + RSTRING(str1)->len,
- RSTRING(str2)->ptr, RSTRING(str2)->len);
- RSTRING(str3)->ptr[RSTRING(str3)->len] = '\0';
-
- if (OBJ_TAINTED(str1) || OBJ_TAINTED(str2))
- OBJ_TAINT(str3);
- return str3;
-}
-
-/*
- * call-seq:
- * str * integer => new_str
- *
- * Copy---Returns a new <code>String</code> containing <i>integer</i> copies of
- * the receiver.
- *
- * "Ho! " * 3 #=> "Ho! Ho! Ho! "
- */
-
-VALUE
-rb_str_times(str, times)
- VALUE str;
- VALUE times;
-{
- VALUE str2;
- long i, len;
-
- len = NUM2LONG(times);
- if (len == 0) return rb_str_new5(str,0,0);
- if (len < 0) {
- rb_raise(rb_eArgError, "negative argument");
- }
- if (LONG_MAX/len < RSTRING(str)->len) {
- rb_raise(rb_eArgError, "argument too big");
- }
-
- str2 = rb_str_new5(str,0, RSTRING(str)->len*len);
- for (i=0; i<len; i++) {
- memcpy(RSTRING(str2)->ptr+(i*RSTRING(str)->len),
- RSTRING(str)->ptr, RSTRING(str)->len);
- }
- RSTRING(str2)->ptr[RSTRING(str2)->len] = '\0';
-
- OBJ_INFECT(str2, str);
-
- return str2;
-}
-
-/*
- * call-seq:
- * str % arg => new_str
- *
- * Format---Uses <i>str</i> as a format specification, and returns the result
- * of applying it to <i>arg</i>. If the format specification contains more than
- * one substitution, then <i>arg</i> must be an <code>Array</code> containing
- * the values to be substituted. See <code>Kernel::sprintf</code> for details
- * of the format string.
- *
- * "%05d" % 123 #=> "00123"
- * "%-5s: %08x" % [ "ID", self.id ] #=> "ID : 200e14d6"
- */
-
-static VALUE
-rb_str_format(str, arg)
- VALUE str, arg;
-{
- VALUE *argv;
-
- if (TYPE(arg) == T_ARRAY) {
- argv = ALLOCA_N(VALUE, RARRAY(arg)->len + 1);
- argv[0] = str;
- MEMCPY(argv+1, RARRAY(arg)->ptr, VALUE, RARRAY(arg)->len);
- return rb_f_sprintf(RARRAY(arg)->len+1, argv);
- }
-
- argv = ALLOCA_N(VALUE, 2);
- argv[0] = str;
- argv[1] = arg;
- return rb_f_sprintf(2, argv);
-}
-
-static int
-str_independent(str)
- VALUE str;
-{
- if (FL_TEST(str, STR_TMPLOCK)) {
- rb_raise(rb_eRuntimeError, "can't modify string; temporarily locked");
- }
- if (OBJ_FROZEN(str)) rb_error_frozen("string");
- if (!OBJ_TAINTED(str) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't modify string");
- if (!FL_TEST(str, ELTS_SHARED)) return 1;
- return 0;
-}
-
-static void
-str_make_independent(str)
- VALUE str;
-{
- char *ptr;
-
- ptr = ALLOC_N(char, RSTRING(str)->len+1);
- if (RSTRING(str)->ptr) {
- memcpy(ptr, RSTRING(str)->ptr, RSTRING(str)->len);
- }
- ptr[RSTRING(str)->len] = 0;
- RSTRING(str)->ptr = ptr;
- RSTRING(str)->aux.capa = RSTRING(str)->len;
- FL_UNSET(str, STR_NOCAPA);
-}
-
-void
-rb_str_modify(str)
- VALUE str;
-{
- if (!str_independent(str))
- str_make_independent(str);
-}
-
-void
-rb_str_associate(str, add)
- VALUE str, add;
-{
- if (FL_TEST(str, STR_ASSOC)) {
- /* already associated */
- rb_ary_concat(RSTRING(str)->aux.shared, add);
- }
- else {
- if (FL_TEST(str, ELTS_SHARED)) {
- str_make_independent(str);
- }
- else if (RSTRING(str)->aux.capa != RSTRING(str)->len) {
- RESIZE_CAPA(str, RSTRING(str)->len);
- }
- RSTRING(str)->aux.shared = add;
- FL_SET(str, STR_ASSOC);
- }
-}
-
-VALUE
-rb_str_associated(str)
- VALUE str;
-{
- if (FL_TEST(str, STR_ASSOC)) {
- return RSTRING(str)->aux.shared;
- }
- return Qfalse;
-}
-
-static char *null_str = "";
-
-VALUE
-rb_string_value(ptr)
- volatile VALUE *ptr;
-{
- VALUE s = *ptr;
- if (TYPE(s) != T_STRING) {
- s = rb_str_to_str(s);
- *ptr = s;
- }
- if (!RSTRING(s)->ptr) {
- FL_SET(s, ELTS_SHARED);
- RSTRING(s)->ptr = null_str;
- }
- return s;
-}
-
-char *
-rb_string_value_ptr(ptr)
- volatile VALUE *ptr;
-{
- return RSTRING(rb_string_value(ptr))->ptr;
-}
-
-char *
-rb_string_value_cstr(ptr)
- volatile VALUE *ptr;
-{
- VALUE str = rb_string_value(ptr);
- char *s = RSTRING(str)->ptr;
-
- if (!s || RSTRING(str)->len != strlen(s)) {
- rb_raise(rb_eArgError, "string contains null byte");
- }
- return s;
-}
-
-VALUE
-rb_check_string_type(str)
- VALUE str;
-{
- str = rb_check_convert_type(str, T_STRING, "String", "to_str");
- if (!NIL_P(str) && !RSTRING(str)->ptr) {
- FL_SET(str, ELTS_SHARED);
- RSTRING(str)->ptr = null_str;
- }
- return str;
-}
-
-VALUE
-rb_str_substr(str, beg, len)
- VALUE str;
- long beg, len;
-{
- VALUE str2;
-
- if (len < 0) return Qnil;
- if (beg > RSTRING(str)->len) return Qnil;
- if (beg < 0) {
- beg += RSTRING(str)->len;
- if (beg < 0) return Qnil;
- }
- if (beg + len > RSTRING(str)->len) {
- len = RSTRING(str)->len - beg;
- }
- if (len < 0) {
- len = 0;
- }
- if (len == 0) return rb_str_new5(str,0,0);
-
- if (len > sizeof(struct RString)/2 &&
- beg + len == RSTRING(str)->len && !FL_TEST(str, STR_ASSOC)) {
- str2 = rb_str_new3(rb_str_new4(str));
- RSTRING(str2)->ptr += RSTRING(str2)->len - len;
- RSTRING(str2)->len = len;
- }
- else {
- str2 = rb_str_new5(str, RSTRING(str)->ptr+beg, len);
- }
- OBJ_INFECT(str2, str);
-
- return str2;
-}
-
-VALUE
-rb_str_freeze(str)
- VALUE str;
-{
- return rb_obj_freeze(str);
-}
-
-VALUE
-rb_str_dup_frozen(str)
- VALUE str;
-{
- if (FL_TEST(str, ELTS_SHARED) && RSTRING(str)->aux.shared) {
- VALUE shared = RSTRING(str)->aux.shared;
- if (RSTRING(shared)->len == RSTRING(str)->len) {
- OBJ_FREEZE(shared);
- return shared;
- }
- }
- if (OBJ_FROZEN(str)) return str;
- str = rb_str_dup(str);
- OBJ_FREEZE(str);
- return str;
-}
-
-VALUE
-rb_str_locktmp(str)
- VALUE str;
-{
- if (FL_TEST(str, STR_TMPLOCK)) {
- rb_raise(rb_eRuntimeError, "temporal locking already locked string");
- }
- FL_SET(str, STR_TMPLOCK);
- return str;
-}
-
-VALUE
-rb_str_unlocktmp(str)
- VALUE str;
-{
- if (!FL_TEST(str, STR_TMPLOCK)) {
- rb_raise(rb_eRuntimeError, "temporal unlocking already unlocked string");
- }
- FL_UNSET(str, STR_TMPLOCK);
- return str;
-}
-
-VALUE
-rb_str_resize(str, len)
- VALUE str;
- long len;
-{
- if (len < 0) {
- rb_raise(rb_eArgError, "negative string size (or size too big)");
- }
-
- rb_str_modify(str);
- if (len != RSTRING(str)->len) {
- if (RSTRING(str)->len < len || RSTRING(str)->len - len > 1024) {
- REALLOC_N(RSTRING(str)->ptr, char, len+1);
- if (!FL_TEST(str, STR_NOCAPA)) {
- RSTRING(str)->aux.capa = len;
- }
- }
- RSTRING(str)->len = len;
- RSTRING(str)->ptr[len] = '\0'; /* sentinel */
- }
- return str;
-}
-
-VALUE
-rb_str_buf_cat(str, ptr, len)
- VALUE str;
- const char *ptr;
- long len;
-{
- long capa, total;
-
- if (len == 0) return str;
- if (len < 0) {
- rb_raise(rb_eArgError, "negative string size (or size too big)");
- }
- rb_str_modify(str);
- if (FL_TEST(str, STR_ASSOC)) {
- FL_UNSET(str, STR_ASSOC);
- capa = RSTRING(str)->aux.capa = RSTRING(str)->len;
- }
- else {
- capa = RSTRING(str)->aux.capa;
- }
- total = RSTRING(str)->len+len;
- if (capa <= total) {
- while (total > capa) {
- capa = (capa + 1) * 2;
- }
- RESIZE_CAPA(str, capa);
- }
- memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
- RSTRING(str)->len = total;
- RSTRING(str)->ptr[total] = '\0'; /* sentinel */
-
- return str;
-}
-
-VALUE
-rb_str_buf_cat2(str, ptr)
- VALUE str;
- const char *ptr;
-{
- return rb_str_buf_cat(str, ptr, strlen(ptr));
-}
-
-VALUE
-rb_str_cat(str, ptr, len)
- VALUE str;
- const char *ptr;
- long len;
-{
- if (len < 0) {
- rb_raise(rb_eArgError, "negative string size (or size too big)");
- }
- if (FL_TEST(str, STR_ASSOC)) {
- rb_str_modify(str);
- REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+len);
- memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
- RSTRING(str)->len += len;
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
- return str;
- }
-
- return rb_str_buf_cat(str, ptr, len);
-}
-
-VALUE
-rb_str_cat2(str, ptr)
- VALUE str;
- const char *ptr;
-{
- return rb_str_cat(str, ptr, strlen(ptr));
-}
-
-VALUE
-rb_str_buf_append(str, str2)
- VALUE str, str2;
-{
- long capa, len;
-
- rb_str_modify(str);
- if (FL_TEST(str, STR_ASSOC)) {
- FL_UNSET(str, STR_ASSOC);
- capa = RSTRING(str)->aux.capa = RSTRING(str)->len;
- }
- else {
- capa = RSTRING(str)->aux.capa;
- }
- len = RSTRING(str)->len+RSTRING(str2)->len;
- if (capa <= len) {
- while (len > capa) {
- capa = (capa + 1) * 2;
- }
- RESIZE_CAPA(str, capa);
- }
- memcpy(RSTRING(str)->ptr + RSTRING(str)->len,
- RSTRING(str2)->ptr, RSTRING(str2)->len);
- RSTRING(str)->len += RSTRING(str2)->len;
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
- OBJ_INFECT(str, str2);
-
- return str;
-}
-
-VALUE
-rb_str_append(str, str2)
- VALUE str, str2;
-{
- StringValue(str2);
- rb_str_modify(str);
- if (RSTRING(str2)->len > 0) {
- if (FL_TEST(str, STR_ASSOC)) {
- long len = RSTRING(str)->len+RSTRING(str2)->len;
- REALLOC_N(RSTRING(str)->ptr, char, len+1);
- memcpy(RSTRING(str)->ptr + RSTRING(str)->len,
- RSTRING(str2)->ptr, RSTRING(str2)->len);
- RSTRING(str)->ptr[len] = '\0'; /* sentinel */
- RSTRING(str)->len = len;
- }
- else {
- return rb_str_buf_append(str, str2);
- }
- }
- OBJ_INFECT(str, str2);
- return str;
-}
-
-
-/*
- * call-seq:
- * str << fixnum => str
- * str.concat(fixnum) => str
- * str << obj => str
- * str.concat(obj) => str
- *
- * Append---Concatenates the given object to <i>str</i>. If the object is a
- * <code>Fixnum</code> between 0 and 255, it is converted to a character before
- * concatenation.
- *
- * a = "hello "
- * a << "world" #=> "hello world"
- * a.concat(33) #=> "hello world!"
- */
-
-VALUE
-rb_str_concat(str1, str2)
- VALUE str1, str2;
-{
- if (FIXNUM_P(str2)) {
- int i = FIX2INT(str2);
- if (0 <= i && i <= 0xff) { /* byte */
- char c = i;
- return rb_str_cat(str1, &c, 1);
- }
- }
- str1 = rb_str_append(str1, str2);
-
- return str1;
-}
-
-int
-rb_str_hash(str)
- VALUE str;
-{
- register long len = RSTRING(str)->len;
- register char *p = RSTRING(str)->ptr;
- register int key = 0;
-
-#ifdef HASH_ELFHASH
- register unsigned int g;
-
- while (len--) {
- key = (key << 4) + *p++;
- if (g = key & 0xF0000000)
- key ^= g >> 24;
- key &= ~g;
- }
-#elif HASH_PERL
- while (len--) {
- key += *p++;
- key += (key << 10);
- key ^= (key >> 6);
- }
- key += (key << 3);
- key ^= (key >> 11);
- key += (key << 15);
-#else
- while (len--) {
- key = key*65599 + *p;
- p++;
- }
- key = key + (key>>5);
-#endif
- return key;
-}
-
-/*
- * call-seq:
- * str.hash => fixnum
- *
- * Return a hash based on the string's length and content.
- */
-
-static VALUE
-rb_str_hash_m(str)
- VALUE str;
-{
- int key = rb_str_hash(str);
- return INT2FIX(key);
-}
-
-#define lesser(a,b) (((a)>(b))?(b):(a))
-
-int
-rb_str_cmp(str1, str2)
- VALUE str1, str2;
-{
- long len;
- int retval;
-
- len = lesser(RSTRING(str1)->len, RSTRING(str2)->len);
- retval = rb_memcmp(RSTRING(str1)->ptr, RSTRING(str2)->ptr, len);
- if (retval == 0) {
- if (RSTRING(str1)->len == RSTRING(str2)->len) return 0;
- if (RSTRING(str1)->len > RSTRING(str2)->len) return 1;
- return -1;
- }
- if (retval > 0) return 1;
- return -1;
-}
-
-
-/*
- * call-seq:
- * str == obj => true or false
- *
- * Equality---If <i>obj</i> is not a <code>String</code>, returns
- * <code>false</code>. Otherwise, returns <code>true</code> if <i>str</i>
- * <code><=></code> <i>obj</i> returns zero.
- */
-
-static VALUE
-rb_str_equal(str1, str2)
- VALUE str1, str2;
-{
- if (str1 == str2) return Qtrue;
- if (TYPE(str2) != T_STRING) {
- if (!rb_respond_to(str2, rb_intern("to_str"))) {
- return Qfalse;
- }
- return rb_equal(str2, str1);
- }
- if (RSTRING(str1)->len == RSTRING(str2)->len &&
- rb_str_cmp(str1, str2) == 0) {
- return Qtrue;
- }
- return Qfalse;
-}
-
-/*
- * call-seq:
- * str.eql?(other) => true or false
- *
- * Two strings are equal if the have the same length and content.
- */
-
-static VALUE
-rb_str_eql(str1, str2)
- VALUE str1, str2;
-{
- if (TYPE(str2) != T_STRING || RSTRING(str1)->len != RSTRING(str2)->len)
- return Qfalse;
-
- if (memcmp(RSTRING(str1)->ptr, RSTRING(str2)->ptr,
- lesser(RSTRING(str1)->len, RSTRING(str2)->len)) == 0)
- return Qtrue;
-
- return Qfalse;
-}
-
-/*
- * call-seq:
- * str <=> other_str => -1, 0, +1
- *
- * Comparison---Returns -1 if <i>other_str</i> is less than, 0 if
- * <i>other_str</i> is equal to, and +1 if <i>other_str</i> is greater than
- * <i>str</i>. If the strings are of different lengths, and the strings are
- * equal when compared up to the shortest length, then the longer string is
- * considered greater than the shorter one. If the variable <code>$=</code> is
- * <code>false</code>, the comparison is based on comparing the binary values
- * of each character in the string. In older versions of Ruby, setting
- * <code>$=</code> allowed case-insensitive comparisons; this is now deprecated
- * in favor of using <code>String#casecmp</code>.
- *
- * <code><=></code> is the basis for the methods <code><</code>,
- * <code><=</code>, <code>></code>, <code>>=</code>, and <code>between?</code>,
- * included from module <code>Comparable</code>. The method
- * <code>String#==</code> does not use <code>Comparable#==</code>.
- *
- * "abcdef" <=> "abcde" #=> 1
- * "abcdef" <=> "abcdef" #=> 0
- * "abcdef" <=> "abcdefg" #=> -1
- * "abcdef" <=> "ABCDEF" #=> 1
- */
-
-static VALUE
-rb_str_cmp_m(str1, str2)
- VALUE str1, str2;
-{
- long result;
-
- if (TYPE(str2) != T_STRING) {
- if (!rb_respond_to(str2, rb_intern("to_str"))) {
- return Qnil;
- }
- else if (!rb_respond_to(str2, rb_intern("<=>"))) {
- return Qnil;
- }
- else {
- VALUE tmp = rb_funcall(str2, rb_intern("<=>"), 1, str1);
-
- if (NIL_P(tmp)) return Qnil;
- if (!FIXNUM_P(tmp)) {
- return rb_funcall(LONG2FIX(0), '-', 1, tmp);
- }
- result = -FIX2LONG(tmp);
- }
- }
- else {
- result = rb_str_cmp(str1, str2);
- }
- return LONG2NUM(result);
-}
-
-/*
- * call-seq:
- * str.casecmp(other_str) => -1, 0, +1
- *
- * Case-insensitive version of <code>String#<=></code>.
- *
- * "abcdef".casecmp("abcde") #=> 1
- * "aBcDeF".casecmp("abcdef") #=> 0
- * "abcdef".casecmp("abcdefg") #=> -1
- * "abcdef".casecmp("ABCDEF") #=> 0
- */
-
-static VALUE
-rb_str_casecmp(str1, str2)
- VALUE str1, str2;
-{
- long len;
- int retval;
-
- StringValue(str2);
- len = lesser(RSTRING(str1)->len, RSTRING(str2)->len);
- retval = rb_memcicmp(RSTRING(str1)->ptr, RSTRING(str2)->ptr, len);
- if (retval == 0) {
- if (RSTRING(str1)->len == RSTRING(str2)->len) return INT2FIX(0);
- if (RSTRING(str1)->len > RSTRING(str2)->len) return INT2FIX(1);
- return INT2FIX(-1);
- }
- if (retval == 0) return INT2FIX(0);
- if (retval > 0) return INT2FIX(1);
- return INT2FIX(-1);
-}
-
-static long
-rb_str_index(str, sub, offset)
- VALUE str, sub;
- long offset;
-{
- long pos;
-
- if (offset < 0) {
- offset += RSTRING(str)->len;
- if (offset < 0) return -1;
- }
- if (RSTRING(str)->len - offset < RSTRING(sub)->len) return -1;
- if (RSTRING(sub)->len == 0) return offset;
- pos = rb_memsearch(RSTRING(sub)->ptr, RSTRING(sub)->len,
- RSTRING(str)->ptr+offset, RSTRING(str)->len-offset);
- if (pos < 0) return pos;
- return pos + offset;
-}
-
-
-/*
- * call-seq:
- * str.index(substring [, offset]) => fixnum or nil
- * str.index(fixnum [, offset]) => fixnum or nil
- * str.index(regexp [, offset]) => fixnum or nil
- *
- * Returns the index of the first occurrence of the given <i>substring</i>,
- * character (<i>fixnum</i>), or pattern (<i>regexp</i>) in <i>str</i>. Returns
- * <code>nil</code> if not found. If the second parameter is present, it
- * specifies the position in the string to begin the search.
- *
- * "hello".index('e') #=> 1
- * "hello".index('lo') #=> 3
- * "hello".index('a') #=> nil
- * "hello".index(101) #=> 1
- * "hello".index(/[aeiou]/, -3) #=> 4
- */
-
-static VALUE
-rb_str_index_m(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- VALUE sub;
- VALUE initpos;
- long pos;
-
- if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
- pos = NUM2LONG(initpos);
- }
- else {
- pos = 0;
- }
- if (pos < 0) {
- pos += RSTRING(str)->len;
- if (pos < 0) {
- if (TYPE(sub) == T_REGEXP) {
- rb_backref_set(Qnil);
- }
- return Qnil;
- }
- }
-
- switch (TYPE(sub)) {
- case T_REGEXP:
- pos = rb_reg_adjust_startpos(sub, str, pos, 0);
- pos = rb_reg_search(sub, str, pos, 0);
- break;
-
- case T_FIXNUM:
- {
- int c = FIX2INT(sub);
- long len = RSTRING(str)->len;
- char *p = RSTRING(str)->ptr;
-
- for (;pos<len;pos++) {
- if ((unsigned char)p[pos] == c) return LONG2NUM(pos);
- }
- return Qnil;
- }
-
- default: {
- VALUE tmp;
-
- tmp = rb_check_string_type(sub);
- if (NIL_P(tmp)) {
- rb_raise(rb_eTypeError, "type mismatch: %s given",
- rb_obj_classname(sub));
- }
- sub = tmp;
- }
- /* fall through */
- case T_STRING:
- pos = rb_str_index(str, sub, pos);
- break;
- }
-
- if (pos == -1) return Qnil;
- return LONG2NUM(pos);
-}
-
-static long
-rb_str_rindex(str, sub, pos)
- VALUE str, sub;
- long pos;
-{
- long len = RSTRING(sub)->len;
- char *s, *sbeg, *t;
-
- /* substring longer than string */
- if (RSTRING(str)->len < len) return -1;
- if (RSTRING(str)->len - pos < len) {
- pos = RSTRING(str)->len - len;
- }
- sbeg = RSTRING(str)->ptr;
- s = RSTRING(str)->ptr + pos;
- t = RSTRING(sub)->ptr;
- if (len) {
- while (sbeg <= s) {
- if (rb_memcmp(s, t, len) == 0) {
- return s - RSTRING(str)->ptr;
- }
- s--;
- }
- return -1;
- }
- else {
- return pos;
- }
-}
-
-
-/*
- * call-seq:
- * str.rindex(substring [, fixnum]) => fixnum or nil
- * str.rindex(fixnum [, fixnum]) => fixnum or nil
- * str.rindex(regexp [, fixnum]) => fixnum or nil
- *
- * Returns the index of the last occurrence of the given <i>substring</i>,
- * character (<i>fixnum</i>), or pattern (<i>regexp</i>) in <i>str</i>. Returns
- * <code>nil</code> if not found. If the second parameter is present, it
- * specifies the position in the string to end the search---characters beyond
- * this point will not be considered.
- *
- * "hello".rindex('e') #=> 1
- * "hello".rindex('l') #=> 3
- * "hello".rindex('a') #=> nil
- * "hello".rindex(101) #=> 1
- * "hello".rindex(/[aeiou]/, -2) #=> 1
- */
-
-static VALUE
-rb_str_rindex_m(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- VALUE sub;
- VALUE position;
- long pos;
-
- if (rb_scan_args(argc, argv, "11", &sub, &position) == 2) {
- pos = NUM2LONG(position);
- if (pos < 0) {
- pos += RSTRING(str)->len;
- if (pos < 0) {
- if (TYPE(sub) == T_REGEXP) {
- rb_backref_set(Qnil);
- }
- return Qnil;
- }
- }
- if (pos > RSTRING(str)->len) pos = RSTRING(str)->len;
- }
- else {
- pos = RSTRING(str)->len;
- }
-
- switch (TYPE(sub)) {
- case T_REGEXP:
- if (RREGEXP(sub)->len) {
- pos = rb_reg_adjust_startpos(sub, str, pos, 1);
- pos = rb_reg_search(sub, str, pos, 1);
- }
- if (pos >= 0) return LONG2NUM(pos);
- break;
-
- case T_STRING:
- pos = rb_str_rindex(str, sub, pos);
- if (pos >= 0) return LONG2NUM(pos);
- break;
-
- case T_FIXNUM:
- {
- int c = FIX2INT(sub);
- char *p = RSTRING(str)->ptr + pos;
- char *pbeg = RSTRING(str)->ptr;
-
- if (pos == RSTRING(str)->len) {
- if (pos == 0) return Qnil;
- --p;
- }
- while (pbeg <= p) {
- if ((unsigned char)*p == c)
- return LONG2NUM((char*)p - RSTRING(str)->ptr);
- p--;
- }
- return Qnil;
- }
-
- default:
- rb_raise(rb_eTypeError, "type mismatch: %s given",
- rb_obj_classname(sub));
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * str =~ obj => fixnum or nil
- *
- * Match---If <i>obj</i> is a <code>Regexp</code>, use it as a pattern to match
- * against <i>str</i>. If <i>obj</i> is a <code>String</code>, look for it in
- * <i>str</i> (similar to <code>String#index</code>). Returns the position the
- * match starts, or <code>nil</code> if there is no match. Otherwise, invokes
- * <i>obj.=~</i>, passing <i>str</i> as an argument. The default
- * <code>=~</code> in <code>Object</code> returns <code>false</code>.
- *
- * "cat o' 9 tails" =~ '\d' #=> nil
- * "cat o' 9 tails" =~ /\d/ #=> 7
- * "cat o' 9 tails" =~ 9 #=> false
- */
-
-static VALUE
-rb_str_match(x, y)
- VALUE x, y;
-{
- switch (TYPE(y)) {
- case T_STRING:
- rb_raise(rb_eTypeError, "type mismatch: String given");
-
- case T_REGEXP:
- return rb_reg_match(y, x);
-
- default:
- return rb_funcall(y, rb_intern("=~"), 1, x);
- }
-}
-
-
-static VALUE get_pat _((VALUE, int));
-
-
-/*
- * call-seq:
- * str.match(pattern) => matchdata or nil
- *
- * Converts <i>pattern</i> to a <code>Regexp</code> (if it isn't already one),
- * then invokes its <code>match</code> method on <i>str</i>. If the second
- * parameter is present, it specifies the position in the string to begin the
- * search.
- *
- * 'hello'.match('(.)\1') #=> #<MatchData:0x401b3d30>
- * 'hello'.match('(.)\1')[0] #=> "ll"
- * 'hello'.match(/(.)\1/)[0] #=> "ll"
- * 'hello'.match('xx') #=> nil
- */
-
-static VALUE
-rb_str_match_m(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- VALUE re;
- if (argc < 1)
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
- re = argv[0];
- argv[0] = str;
- return rb_funcall2(get_pat(re, 0), rb_intern("match"), argc, argv);
-}
-
-static char
-succ_char(s)
- char *s;
-{
- char c = *s;
-
- /* numerics */
- if ('0' <= c && c < '9') (*s)++;
- else if (c == '9') {
- *s = '0';
- return '1';
- }
- /* small alphabets */
- else if ('a' <= c && c < 'z') (*s)++;
- else if (c == 'z') {
- return *s = 'a';
- }
- /* capital alphabets */
- else if ('A' <= c && c < 'Z') (*s)++;
- else if (c == 'Z') {
- return *s = 'A';
- }
- return 0;
-}
-
-
-/*
- * call-seq:
- * str.succ => new_str
- * str.next => new_str
- *
- * Returns the successor to <i>str</i>. The successor is calculated by
- * incrementing characters starting from the rightmost alphanumeric (or
- * the rightmost character if there are no alphanumerics) in the
- * string. Incrementing a digit always results in another digit, and
- * incrementing a letter results in another letter of the same case.
- * Incrementing nonalphanumerics uses the underlying character set's
- * collating sequence.
- *
- * If the increment generates a ``carry,'' the character to the left of
- * it is incremented. This process repeats until there is no carry,
- * adding an additional character if necessary.
- *
- * "abcd".succ #=> "abce"
- * "THX1138".succ #=> "THX1139"
- * "<<koala>>".succ #=> "<<koalb>>"
- * "1999zzz".succ #=> "2000aaa"
- * "ZZZ9999".succ #=> "AAAA0000"
- * "***".succ #=> "**+"
- */
-
-static VALUE
-rb_str_succ(orig)
- VALUE orig;
-{
- VALUE str;
- char *sbeg, *s;
- int c = -1;
- long n = 0;
-
- str = rb_str_new5(orig, RSTRING(orig)->ptr, RSTRING(orig)->len);
- OBJ_INFECT(str, orig);
- if (RSTRING(str)->len == 0) return str;
-
- sbeg = RSTRING(str)->ptr; s = sbeg + RSTRING(str)->len - 1;
-
- while (sbeg <= s) {
- if (ISALNUM(*s)) {
- if ((c = succ_char(s)) == 0) break;
- n = s - sbeg;
- }
- s--;
- }
- if (c == -1) { /* str contains no alnum */
- sbeg = RSTRING(str)->ptr; s = sbeg + RSTRING(str)->len - 1;
- c = '\001';
- while (sbeg <= s) {
- if ((*s += 1) != 0) break;
- s--;
- }
- }
- if (s < sbeg) {
- RESIZE_CAPA(str, RSTRING(str)->len + 1);
- s = RSTRING(str)->ptr + n;
- memmove(s+1, s, RSTRING(str)->len - n);
- *s = c;
- RSTRING(str)->len += 1;
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
- }
-
- return str;
-}
-
-
-/*
- * call-seq:
- * str.succ! => str
- * str.next! => str
- *
- * Equivalent to <code>String#succ</code>, but modifies the receiver in
- * place.
- */
-
-static VALUE
-rb_str_succ_bang(str)
- VALUE str;
-{
- rb_str_shared_replace(str, rb_str_succ(str));
-
- return str;
-}
-
-VALUE
-rb_str_upto(beg, end, excl)
- VALUE beg, end;
- int excl;
-{
- VALUE current, after_end;
- ID succ = rb_intern("succ");
- int n;
-
- StringValue(end);
- n = rb_str_cmp(beg, end);
- if (n > 0 || (excl && n == 0)) return beg;
- after_end = rb_funcall(end, succ, 0, 0);
- current = beg;
- while (!rb_str_equal(current, after_end)) {
- rb_yield(current);
- if (!excl && rb_str_equal(current, end)) break;
- current = rb_funcall(current, succ, 0, 0);
- StringValue(current);
- if (excl && rb_str_equal(current, end)) break;
- StringValue(current);
- if (RSTRING(current)->len > RSTRING(end)->len)
- break;
- }
-
- return beg;
-}
-
-
-/*
- * call-seq:
- * str.upto(other_str) {|s| block } => str
- *
- * Iterates through successive values, starting at <i>str</i> and
- * ending at <i>other_str</i> inclusive, passing each value in turn to
- * the block. The <code>String#succ</code> method is used to generate
- * each value.
- *
- * "a8".upto("b6") {|s| print s, ' ' }
- * for s in "a8".."b6"
- * print s, ' '
- * end
- *
- * <em>produces:</em>
- *
- * a8 a9 b0 b1 b2 b3 b4 b5 b6
- * a8 a9 b0 b1 b2 b3 b4 b5 b6
- */
-
-static VALUE
-rb_str_upto_m(beg, end)
- VALUE beg, end;
-{
- return rb_str_upto(beg, end, Qfalse);
-}
-
-static VALUE
-rb_str_subpat(str, re, nth)
- VALUE str, re;
- int nth;
-{
- if (rb_reg_search(re, str, 0, 0) >= 0) {
- return rb_reg_nth_match(nth, rb_backref_get());
- }
- return Qnil;
-}
-
-static VALUE
-rb_str_aref(str, indx)
- VALUE str;
- VALUE indx;
-{
- long idx;
-
- switch (TYPE(indx)) {
- case T_FIXNUM:
- idx = FIX2LONG(indx);
-
- num_index:
- if (idx < 0) {
- idx = RSTRING(str)->len + idx;
- }
- if (idx < 0 || RSTRING(str)->len <= idx) {
- return Qnil;
- }
- return INT2FIX(RSTRING(str)->ptr[idx] & 0xff);
-
- case T_REGEXP:
- return rb_str_subpat(str, indx, 0);
-
- case T_STRING:
- if (rb_str_index(str, indx, 0) != -1)
- return rb_str_dup(indx);
- return Qnil;
-
- default:
- /* check if indx is Range */
- {
- long beg, len;
- switch (rb_range_beg_len(indx, &beg, &len, RSTRING(str)->len, 0)) {
- case Qfalse:
- break;
- case Qnil:
- return Qnil;
- default:
- return rb_str_substr(str, beg, len);
- }
- }
- idx = NUM2LONG(indx);
- goto num_index;
- }
- return Qnil; /* not reached */
-}
-
-
-/*
- * call-seq:
- * str[fixnum] => fixnum or nil
- * str[fixnum, fixnum] => new_str or nil
- * str[range] => new_str or nil
- * str[regexp] => new_str or nil
- * str[regexp, fixnum] => new_str or nil
- * str[other_str] => new_str or nil
- * str.slice(fixnum) => fixnum or nil
- * str.slice(fixnum, fixnum) => new_str or nil
- * str.slice(range) => new_str or nil
- * str.slice(regexp) => new_str or nil
- * str.slice(regexp, fixnum) => new_str or nil
- * str.slice(other_str) => new_str or nil
- *
- * Element Reference---If passed a single <code>Fixnum</code>, returns the code
- * of the character at that position. If passed two <code>Fixnum</code>
- * objects, returns a substring starting at the offset given by the first, and
- * a length given by the second. If given a range, a substring containing
- * characters at offsets given by the range is returned. In all three cases, if
- * an offset is negative, it is counted from the end of <i>str</i>. Returns
- * <code>nil</code> if the initial offset falls outside the string, the length
- * is negative, or the beginning of the range is greater than the end.
- *
- * If a <code>Regexp</code> is supplied, the matching portion of <i>str</i> is
- * returned. If a numeric parameter follows the regular expression, that
- * component of the <code>MatchData</code> is returned instead. If a
- * <code>String</code> is given, that string is returned if it occurs in
- * <i>str</i>. In both cases, <code>nil</code> is returned if there is no
- * match.
- *
- * a = "hello there"
- * a[1] #=> 101
- * a[1,3] #=> "ell"
- * a[1..3] #=> "ell"
- * a[-3,2] #=> "er"
- * a[-4..-2] #=> "her"
- * a[12..-1] #=> nil
- * a[-2..-4] #=> ""
- * a[/[aeiou](.)\1/] #=> "ell"
- * a[/[aeiou](.)\1/, 0] #=> "ell"
- * a[/[aeiou](.)\1/, 1] #=> "l"
- * a[/[aeiou](.)\1/, 2] #=> nil
- * a["lo"] #=> "lo"
- * a["bye"] #=> nil
- */
-
-static VALUE
-rb_str_aref_m(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- if (argc == 2) {
- if (TYPE(argv[0]) == T_REGEXP) {
- return rb_str_subpat(str, argv[0], NUM2INT(argv[1]));
- }
- return rb_str_substr(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]));
- }
- if (argc != 1) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
- }
- return rb_str_aref(str, argv[0]);
-}
-
-static void
-rb_str_splice(str, beg, len, val)
- VALUE str;
- long beg, len;
- VALUE val;
-{
- if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
-
- StringValue(val);
- rb_str_modify(str);
-
- if (RSTRING(str)->len < beg) {
- out_of_range:
- rb_raise(rb_eIndexError, "index %ld out of string", beg);
- }
- if (beg < 0) {
- if (-beg > RSTRING(str)->len) {
- goto out_of_range;
- }
- beg += RSTRING(str)->len;
- }
- if (RSTRING(str)->len < beg + len) {
- len = RSTRING(str)->len - beg;
- }
-
- if (len < RSTRING(val)->len) {
- /* expand string */
- RESIZE_CAPA(str, RSTRING(str)->len + RSTRING(val)->len - len + 1);
- }
-
- if (RSTRING(val)->len != len) {
- memmove(RSTRING(str)->ptr + beg + RSTRING(val)->len,
- RSTRING(str)->ptr + beg + len,
- RSTRING(str)->len - (beg + len));
- }
- if (RSTRING(str)->len < beg && len < 0) {
- MEMZERO(RSTRING(str)->ptr + RSTRING(str)->len, char, -len);
- }
- if (RSTRING(val)->len > 0) {
- memmove(RSTRING(str)->ptr+beg, RSTRING(val)->ptr, RSTRING(val)->len);
- }
- RSTRING(str)->len += RSTRING(val)->len - len;
- if (RSTRING(str)->ptr) {
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
- }
- OBJ_INFECT(str, val);
-}
-
-void
-rb_str_update(str, beg, len, val)
- VALUE str;
- long beg, len;
- VALUE val;
-{
- rb_str_splice(str, beg, len, val);
-}
-
-static void
-rb_str_subpat_set(str, re, nth, val)
- VALUE str, re;
- int nth;
- VALUE val;
-{
- VALUE match;
- long start, end, len;
-
- if (rb_reg_search(re, str, 0, 0) < 0) {
- rb_raise(rb_eIndexError, "regexp not matched");
- }
- match = rb_backref_get();
- if (nth >= RMATCH(match)->regs->num_regs) {
- out_of_range:
- rb_raise(rb_eIndexError, "index %d out of regexp", nth);
- }
- if (nth < 0) {
- if (-nth >= RMATCH(match)->regs->num_regs) {
- goto out_of_range;
- }
- nth += RMATCH(match)->regs->num_regs;
- }
-
- start = RMATCH(match)->BEG(nth);
- if (start == -1) {
- rb_raise(rb_eIndexError, "regexp group %d not matched", nth);
- }
- end = RMATCH(match)->END(nth);
- len = end - start;
- rb_str_splice(str, start, len, val);
-}
-
-static VALUE
-rb_str_aset(str, indx, val)
- VALUE str;
- VALUE indx, val;
-{
- long idx, beg;
-
- switch (TYPE(indx)) {
- case T_FIXNUM:
- num_index:
- idx = FIX2LONG(indx);
- if (RSTRING(str)->len <= idx) {
- out_of_range:
- rb_raise(rb_eIndexError, "index %ld out of string", idx);
- }
- if (idx < 0) {
- if (-idx > RSTRING(str)->len)
- goto out_of_range;
- idx += RSTRING(str)->len;
- }
- if (FIXNUM_P(val)) {
- rb_str_modify(str);
- if (RSTRING(str)->len == idx) {
- RSTRING(str)->len += 1;
- RESIZE_CAPA(str, RSTRING(str)->len);
- }
- RSTRING(str)->ptr[idx] = FIX2INT(val) & 0xff;
- }
- else {
- rb_str_splice(str, idx, 1, val);
- }
- return val;
-
- case T_REGEXP:
- rb_str_subpat_set(str, indx, 0, val);
- return val;
-
- case T_STRING:
- beg = rb_str_index(str, indx, 0);
- if (beg < 0) {
- rb_raise(rb_eIndexError, "string not matched");
- }
- rb_str_splice(str, beg, RSTRING(indx)->len, val);
- return val;
-
- default:
- /* check if indx is Range */
- {
- long beg, len;
- if (rb_range_beg_len(indx, &beg, &len, RSTRING(str)->len, 2)) {
- rb_str_splice(str, beg, len, val);
- return val;
- }
- }
- idx = NUM2LONG(indx);
- goto num_index;
- }
-}
-
-/*
- * call-seq:
- * str[fixnum] = fixnum
- * str[fixnum] = new_str
- * str[fixnum, fixnum] = new_str
- * str[range] = aString
- * str[regexp] = new_str
- * str[regexp, fixnum] = new_str
- * str[other_str] = new_str
- *
- * Element Assignment---Replaces some or all of the content of <i>str</i>. The
- * portion of the string affected is determined using the same criteria as
- * <code>String#[]</code>. If the replacement string is not the same length as
- * the text it is replacing, the string will be adjusted accordingly. If the
- * regular expression or string is used as the index doesn't match a position
- * in the string, <code>IndexError</code> is raised. If the regular expression
- * form is used, the optional second <code>Fixnum</code> allows you to specify
- * which portion of the match to replace (effectively using the
- * <code>MatchData</code> indexing rules. The forms that take a
- * <code>Fixnum</code> will raise an <code>IndexError</code> if the value is
- * out of range; the <code>Range</code> form will raise a
- * <code>RangeError</code>, and the <code>Regexp</code> and <code>String</code>
- * forms will silently ignore the assignment.
- */
-
-static VALUE
-rb_str_aset_m(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- if (argc == 3) {
- if (TYPE(argv[0]) == T_REGEXP) {
- rb_str_subpat_set(str, argv[0], NUM2INT(argv[1]), argv[2]);
- }
- else {
- rb_str_splice(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
- }
- return argv[2];
- }
- if (argc != 2) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
- }
- return rb_str_aset(str, argv[0], argv[1]);
-}
-
-/*
- * call-seq:
- * str.insert(index, other_str) => str
- *
- * Inserts <i>other_str</i> before the character at the given
- * <i>index</i>, modifying <i>str</i>. Negative indices count from the
- * end of the string, and insert <em>after</em> the given character.
- * The intent is insert <i>aString</i> so that it starts at the given
- * <i>index</i>.
- *
- * "abcd".insert(0, 'X') #=> "Xabcd"
- * "abcd".insert(3, 'X') #=> "abcXd"
- * "abcd".insert(4, 'X') #=> "abcdX"
- * "abcd".insert(-3, 'X') #=> "abXcd"
- * "abcd".insert(-1, 'X') #=> "abcdX"
- */
-
-static VALUE
-rb_str_insert(str, idx, str2)
- VALUE str, idx, str2;
-{
- long pos = NUM2LONG(idx);
-
- if (pos == -1) {
- pos = RSTRING(str)->len;
- }
- else if (pos < 0) {
- pos++;
- }
- rb_str_splice(str, pos, 0, str2);
- return str;
-}
-
-
-/*
- * call-seq:
- * str.slice!(fixnum) => fixnum or nil
- * str.slice!(fixnum, fixnum) => new_str or nil
- * str.slice!(range) => new_str or nil
- * str.slice!(regexp) => new_str or nil
- * str.slice!(other_str) => new_str or nil
- *
- * Deletes the specified portion from <i>str</i>, and returns the portion
- * deleted. The forms that take a <code>Fixnum</code> will raise an
- * <code>IndexError</code> if the value is out of range; the <code>Range</code>
- * form will raise a <code>RangeError</code>, and the <code>Regexp</code> and
- * <code>String</code> forms will silently ignore the assignment.
- *
- * string = "this is a string"
- * string.slice!(2) #=> 105
- * string.slice!(3..6) #=> " is "
- * string.slice!(/s.*t/) #=> "sa st"
- * string.slice!("r") #=> "r"
- * string #=> "thing"
- */
-
-static VALUE
-rb_str_slice_bang(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- VALUE result;
- VALUE buf[3];
- int i;
-
- if (argc < 1 || 2 < argc) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
- }
- for (i=0; i<argc; i++) {
- buf[i] = argv[i];
- }
- buf[i] = rb_str_new(0,0);
- result = rb_str_aref_m(argc, buf, str);
- if (!NIL_P(result)) {
- rb_str_aset_m(argc+1, buf, str);
- }
- return result;
-}
-
-static VALUE
-get_pat(pat, quote)
- VALUE pat;
- int quote;
-{
- VALUE val;
-
- switch (TYPE(pat)) {
- case T_REGEXP:
- return pat;
-
- case T_STRING:
- break;
-
- default:
- val = rb_check_string_type(pat);
- if (NIL_P(val)) {
- Check_Type(pat, T_REGEXP);
- }
- pat = val;
- }
-
- if (quote) {
- pat = rb_reg_quote(pat);
- }
-
- return rb_reg_regcomp(pat);
-}
-
-
-/*
- * call-seq:
- * str.sub!(pattern, replacement) => str or nil
- * str.sub!(pattern) {|match| block } => str or nil
- *
- * Performs the substitutions of <code>String#sub</code> in place,
- * returning <i>str</i>, or <code>nil</code> if no substitutions were
- * performed.
- */
-
-static VALUE
-rb_str_sub_bang(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- VALUE pat, repl, match;
- struct re_registers *regs;
- int iter = 0;
- int tainted = 0;
- long plen;
-
- if (argc == 1 && rb_block_given_p()) {
- iter = 1;
- }
- else if (argc == 2) {
- repl = argv[1];
- StringValue(repl);
- if (OBJ_TAINTED(repl)) tainted = 1;
- }
- else {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
- }
-
- pat = get_pat(argv[0], 1);
- if (rb_reg_search(pat, str, 0, 0) >= 0) {
- rb_str_modify(str);
- match = rb_backref_get();
- regs = RMATCH(match)->regs;
-
- if (iter) {
- char *p = RSTRING(str)->ptr; long len = RSTRING(str)->len;
-
- rb_match_busy(match);
- repl = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
- str_mod_check(str, p, len);
- str_frozen_check(str);
- rb_backref_set(match);
- }
- else {
- repl = rb_reg_regsub(repl, str, regs);
- }
- if (OBJ_TAINTED(repl)) tainted = 1;
- plen = END(0) - BEG(0);
- if (RSTRING(repl)->len > plen) {
- RESIZE_CAPA(str, RSTRING(str)->len + RSTRING(repl)->len - plen);
- }
- if (RSTRING(repl)->len != plen) {
- memmove(RSTRING(str)->ptr + BEG(0) + RSTRING(repl)->len,
- RSTRING(str)->ptr + BEG(0) + plen,
- RSTRING(str)->len - BEG(0) - plen);
- }
- memcpy(RSTRING(str)->ptr + BEG(0),
- RSTRING(repl)->ptr, RSTRING(repl)->len);
- RSTRING(str)->len += RSTRING(repl)->len - plen;
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
- if (tainted) OBJ_TAINT(str);
-
- return str;
- }
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.sub(pattern, replacement) => new_str
- * str.sub(pattern) {|match| block } => new_str
- *
- * Returns a copy of <i>str</i> with the <em>first</em> occurrence of
- * <i>pattern</i> replaced with either <i>replacement</i> or the value of the
- * block. The <i>pattern</i> will typically be a <code>Regexp</code>; if it is
- * a <code>String</code> then no regular expression metacharacters will be
- * interpreted (that is <code>/\d/</code> will match a digit, but
- * <code>'\d'</code> will match a backslash followed by a 'd').
- *
- * If the method call specifies <i>replacement</i>, special variables such as
- * <code>$&</code> will not be useful, as substitution into the string occurs
- * before the pattern match starts. However, the sequences <code>\1</code>,
- * <code>\2</code>, etc., may be used.
- *
- * In the block form, the current match string is passed in as a parameter, and
- * variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>,
- * <code>$&</code>, and <code>$'</code> will be set appropriately. The value
- * returned by the block will be substituted for the match on each call.
- *
- * The result inherits any tainting in the original string or any supplied
- * replacement string.
- *
- * "hello".sub(/[aeiou]/, '*') #=> "h*llo"
- * "hello".sub(/([aeiou])/, '<\1>') #=> "h<e>llo"
- * "hello".sub(/./) {|s| s[0].to_s + ' ' } #=> "104 ello"
- */
-
-static VALUE
-rb_str_sub(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- str = rb_str_dup(str);
- rb_str_sub_bang(argc, argv, str);
- return str;
-}
-
-static VALUE
-str_gsub(argc, argv, str, bang)
- int argc;
- VALUE *argv;
- VALUE str;
- int bang;
-{
- VALUE pat, val, repl, match, dest;
- struct re_registers *regs;
- long beg, n;
- long offset, blen, slen, len;
- int iter = 0;
- char *buf, *bp, *sp, *cp;
- int tainted = 0;
-
- if (argc == 1 && rb_block_given_p()) {
- iter = 1;
- }
- else if (argc == 2) {
- repl = argv[1];
- StringValue(repl);
- if (OBJ_TAINTED(repl)) tainted = 1;
- }
- else {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
- }
-
- pat = get_pat(argv[0], 1);
- offset=0; n=0;
- beg = rb_reg_search(pat, str, 0, 0);
- if (beg < 0) {
- if (bang) return Qnil; /* no match, no substitution */
- return rb_str_dup(str);
- }
-
- blen = RSTRING(str)->len + 30; /* len + margin */
- dest = str_new(0, 0, blen);
- buf = RSTRING(dest)->ptr;
- bp = buf;
- sp = cp = RSTRING(str)->ptr;
- slen = RSTRING(str)->len;
-
- rb_str_locktmp(dest);
- while (beg >= 0) {
- n++;
- match = rb_backref_get();
- regs = RMATCH(match)->regs;
- if (iter) {
- rb_match_busy(match);
- val = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
- str_mod_check(str, sp, slen);
- if (bang) str_frozen_check(str);
- if (val == dest) { /* paranoid chack [ruby-dev:24827] */
- rb_raise(rb_eRuntimeError, "block should not cheat");
- }
- rb_backref_set(match);
- }
- else {
- val = rb_reg_regsub(repl, str, regs);
- }
- if (OBJ_TAINTED(val)) tainted = 1;
- len = (bp - buf) + (beg - offset) + RSTRING(val)->len + 3;
- if (blen < len) {
- while (blen < len) blen *= 2;
- len = bp - buf;
- RESIZE_CAPA(dest, blen);
- RSTRING(dest)->len = blen;
- buf = RSTRING(dest)->ptr;
- bp = buf + len;
- }
- len = beg - offset; /* copy pre-match substr */
- memcpy(bp, cp, len);
- bp += len;
- memcpy(bp, RSTRING(val)->ptr, RSTRING(val)->len);
- bp += RSTRING(val)->len;
- offset = END(0);
- if (BEG(0) == END(0)) {
- /*
- * Always consume at least one character of the input string
- * in order to prevent infinite loops.
- */
- if (RSTRING(str)->len <= END(0)) break;
- len = mbclen2(RSTRING(str)->ptr[END(0)], pat);
- memcpy(bp, RSTRING(str)->ptr+END(0), len);
- bp += len;
- offset = END(0) + len;
- }
- cp = RSTRING(str)->ptr + offset;
- if (offset > RSTRING(str)->len) break;
- beg = rb_reg_search(pat, str, offset, 0);
- }
- if (RSTRING(str)->len > offset) {
- len = bp - buf;
- if (blen - len < RSTRING(str)->len - offset) {
- blen = len + RSTRING(str)->len - offset;
- RESIZE_CAPA(dest, blen);
- buf = RSTRING(dest)->ptr;
- bp = buf + len;
- }
- memcpy(bp, cp, RSTRING(str)->len - offset);
- bp += RSTRING(str)->len - offset;
- }
- rb_backref_set(match);
- *bp = '\0';
- rb_str_unlocktmp(dest);
- if (bang) {
- if (str_independent(str)) {
- free(RSTRING(str)->ptr);
- }
- FL_UNSET(str, STR_NOCAPA);
- RSTRING(str)->ptr = buf;
- RSTRING(str)->aux.capa = blen;
- RSTRING(dest)->ptr = 0;
- RSTRING(dest)->len = 0;
- }
- else {
- RBASIC(dest)->klass = rb_obj_class(str);
- OBJ_INFECT(dest, str);
- str = dest;
- }
- RSTRING(str)->len = bp - buf;
-
- if (tainted) OBJ_TAINT(str);
- return str;
-}
-
-
-/*
- * call-seq:
- * str.gsub!(pattern, replacement) => str or nil
- * str.gsub!(pattern) {|match| block } => str or nil
- *
- * Performs the substitutions of <code>String#gsub</code> in place, returning
- * <i>str</i>, or <code>nil</code> if no substitutions were performed.
- */
-
-static VALUE
-rb_str_gsub_bang(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- return str_gsub(argc, argv, str, 1);
-}
-
-
-/*
- * call-seq:
- * str.gsub(pattern, replacement) => new_str
- * str.gsub(pattern) {|match| block } => new_str
- *
- * Returns a copy of <i>str</i> with <em>all</em> occurrences of <i>pattern</i>
- * replaced with either <i>replacement</i> or the value of the block. The
- * <i>pattern</i> will typically be a <code>Regexp</code>; if it is a
- * <code>String</code> then no regular expression metacharacters will be
- * interpreted (that is <code>/\d/</code> will match a digit, but
- * <code>'\d'</code> will match a backslash followed by a 'd').
- *
- * If a string is used as the replacement, special variables from the match
- * (such as <code>$&</code> and <code>$1</code>) cannot be substituted into it,
- * as substitution into the string occurs before the pattern match
- * starts. However, the sequences <code>\1</code>, <code>\2</code>, and so on
- * may be used to interpolate successive groups in the match.
- *
- * In the block form, the current match string is passed in as a parameter, and
- * variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>,
- * <code>$&</code>, and <code>$'</code> will be set appropriately. The value
- * returned by the block will be substituted for the match on each call.
- *
- * The result inherits any tainting in the original string or any supplied
- * replacement string.
- *
- * "hello".gsub(/[aeiou]/, '*') #=> "h*ll*"
- * "hello".gsub(/([aeiou])/, '<\1>') #=> "h<e>ll<o>"
- * "hello".gsub(/./) {|s| s[0].to_s + ' '} #=> "104 101 108 108 111 "
- */
-
-static VALUE
-rb_str_gsub(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- return str_gsub(argc, argv, str, 0);
-}
-
-
-/*
- * call-seq:
- * str.replace(other_str) => str
- *
- * Replaces the contents and taintedness of <i>str</i> with the corresponding
- * values in <i>other_str</i>.
- *
- * s = "hello" #=> "hello"
- * s.replace "world" #=> "world"
- */
-
-static VALUE
-rb_str_replace(str, str2)
- VALUE str, str2;
-{
- if (str == str2) return str;
-
- StringValue(str2);
- if (FL_TEST(str2, ELTS_SHARED)) {
- if (str_independent(str)) {
- free(RSTRING(str)->ptr);
- }
- RSTRING(str)->len = RSTRING(str2)->len;
- RSTRING(str)->ptr = RSTRING(str2)->ptr;
- FL_SET(str, ELTS_SHARED);
- FL_UNSET(str, STR_ASSOC);
- RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared;
- }
- else {
- rb_str_modify(str);
- rb_str_resize(str, RSTRING(str2)->len);
- memcpy(RSTRING(str)->ptr, RSTRING(str2)->ptr, RSTRING(str2)->len);
- if (FL_TEST(str2, STR_ASSOC)) {
- FL_SET(str, STR_ASSOC);
- RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared;
- }
- }
-
- OBJ_INFECT(str, str2);
- return str;
-}
-
-/*
- * call-seq:
- * string.clear -> string
- *
- * Makes string empty.
- *
- * a = "abcde"
- * a.clear #=> ""
- */
-
-static VALUE
-rb_str_clear(str)
- VALUE str;
-{
- /* rb_str_modify() */ /* no need for str_make_independent */
- if (str_independent(str)) {
- free(RSTRING(str)->ptr);
- }
- RSTRING(str)->aux.shared = 0;
- FL_UNSET(str, STR_NOCAPA);
- FL_SET(str, ELTS_SHARED);
- RSTRING(str)->ptr = null_str;
- RARRAY(str)->len = 0;
- return str;
-}
-
-static VALUE
-uscore_get()
-{
- VALUE line;
-
- line = rb_lastline_get();
- if (TYPE(line) != T_STRING) {
- rb_raise(rb_eTypeError, "$_ value need to be String (%s given)",
- NIL_P(line) ? "nil" : rb_obj_classname(line));
- }
- return line;
-}
-
-/*
- * call-seq:
- * sub!(pattern, replacement) => $_ or nil
- * sub!(pattern) {|...| block } => $_ or nil
- *
- * Equivalent to <code>$_.sub!(<i>args</i>)</code>.
- */
-
-static VALUE
-rb_f_sub_bang(argc, argv)
- int argc;
- VALUE *argv;
-{
- return rb_str_sub_bang(argc, argv, uscore_get());
-}
-
-/*
- * call-seq:
- * sub(pattern, replacement) => $_
- * sub(pattern) { block } => $_
- *
- * Equivalent to <code>$_.sub(<i>args</i>)</code>, except that
- * <code>$_</code> will be updated if substitution occurs.
- */
-
-static VALUE
-rb_f_sub(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE str = rb_str_dup(uscore_get());
-
- if (NIL_P(rb_str_sub_bang(argc, argv, str)))
- return str;
- rb_lastline_set(str);
- return str;
-}
-
-/*
- * call-seq:
- * gsub!(pattern, replacement) => string or nil
- * gsub!(pattern) {|...| block } => string or nil
- *
- * Equivalent to <code>Kernel::gsub</code>, except <code>nil</code> is
- * returned if <code>$_</code> is not modified.
- *
- * $_ = "quick brown fox"
- * gsub! /cat/, '*' #=> nil
- * $_ #=> "quick brown fox"
- */
-
-static VALUE
-rb_f_gsub_bang(argc, argv)
- int argc;
- VALUE *argv;
-{
- return rb_str_gsub_bang(argc, argv, uscore_get());
-}
-
-/*
- * call-seq:
- * gsub(pattern, replacement) => string
- * gsub(pattern) {|...| block } => string
- *
- * Equivalent to <code>$_.gsub...</code>, except that <code>$_</code>
- * receives the modified result.
- *
- * $_ = "quick brown fox"
- * gsub /[aeiou]/, '*' #=> "q**ck br*wn f*x"
- * $_ #=> "q**ck br*wn f*x"
- */
-
-static VALUE
-rb_f_gsub(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE str = rb_str_dup(uscore_get());
-
- if (NIL_P(rb_str_gsub_bang(argc, argv, str)))
- return str;
- rb_lastline_set(str);
- return str;
-}
-
-
-/*
- * call-seq:
- * str.reverse! => str
- *
- * Reverses <i>str</i> in place.
- */
-
-static VALUE
-rb_str_reverse_bang(str)
- VALUE str;
-{
- char *s, *e;
- char c;
-
- if (RSTRING(str)->len > 1) {
- rb_str_modify(str);
- s = RSTRING(str)->ptr;
- e = s + RSTRING(str)->len - 1;
- while (s < e) {
- c = *s;
- *s++ = *e;
- *e-- = c;
- }
- }
- return str;
-}
-
-
-/*
- * call-seq:
- * str.reverse => new_str
- *
- * Returns a new string with the characters from <i>str</i> in reverse order.
- *
- * "stressed".reverse #=> "desserts"
- */
-
-static VALUE
-rb_str_reverse(str)
- VALUE str;
-{
- VALUE obj;
- char *s, *e, *p;
-
- if (RSTRING(str)->len <= 1) return rb_str_dup(str);
-
- obj = rb_str_new5(str, 0, RSTRING(str)->len);
- s = RSTRING(str)->ptr; e = s + RSTRING(str)->len - 1;
- p = RSTRING(obj)->ptr;
-
- while (e >= s) {
- *p++ = *e--;
- }
- OBJ_INFECT(obj, str);
-
- return obj;
-}
-
-
-/*
- * call-seq:
- * str.include? other_str => true or false
- * str.include? fixnum => true or false
- *
- * Returns <code>true</code> if <i>str</i> contains the given string or
- * character.
- *
- * "hello".include? "lo" #=> true
- * "hello".include? "ol" #=> false
- * "hello".include? ?h #=> true
- */
-
-static VALUE
-rb_str_include(str, arg)
- VALUE str, arg;
-{
- long i;
-
- if (FIXNUM_P(arg)) {
- if (memchr(RSTRING(str)->ptr, FIX2INT(arg), RSTRING(str)->len))
- return Qtrue;
- return Qfalse;
- }
-
- StringValue(arg);
- i = rb_str_index(str, arg, 0);
-
- if (i == -1) return Qfalse;
- return Qtrue;
-}
-
-
-/*
- * call-seq:
- * str.to_i(base=10) => integer
- *
- * Returns the result of interpreting leading characters in <i>str</i> as an
- * integer base <i>base</i> (2, 8, 10, or 16). Extraneous characters past the
- * end of a valid number are ignored. If there is not a valid number at the
- * start of <i>str</i>, <code>0</code> is returned. This method never raises an
- * exception.
- *
- * "12345".to_i #=> 12345
- * "99 red balloons".to_i #=> 99
- * "0a".to_i #=> 0
- * "0a".to_i(16) #=> 10
- * "hello".to_i #=> 0
- * "1100101".to_i(2) #=> 101
- * "1100101".to_i(8) #=> 294977
- * "1100101".to_i(10) #=> 1100101
- * "1100101".to_i(16) #=> 17826049
- */
-
-static VALUE
-rb_str_to_i(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- VALUE b;
- int base;
-
- rb_scan_args(argc, argv, "01", &b);
- if (argc == 0) base = 10;
- else base = NUM2INT(b);
-
- if (base < 0) {
- rb_raise(rb_eArgError, "illegal radix %d", base);
- }
- return rb_str_to_inum(str, base, Qfalse);
-}
-
-
-/*
- * call-seq:
- * str.to_f => float
- *
- * Returns the result of interpreting leading characters in <i>str</i> as a
- * floating point number. Extraneous characters past the end of a valid number
- * are ignored. If there is not a valid number at the start of <i>str</i>,
- * <code>0.0</code> is returned. This method never raises an exception.
- *
- * "123.45e1".to_f #=> 1234.5
- * "45.67 degrees".to_f #=> 45.67
- * "thx1138".to_f #=> 0.0
- */
-
-static VALUE
-rb_str_to_f(str)
- VALUE str;
-{
- return rb_float_new(rb_str_to_dbl(str, Qfalse));
-}
-
-
-/*
- * call-seq:
- * str.to_s => str
- * str.to_str => str
- *
- * Returns the receiver.
- */
-
-static VALUE
-rb_str_to_s(str)
- VALUE str;
-{
- if (rb_obj_class(str) != rb_cString) {
- VALUE dup = str_alloc(rb_cString);
- rb_str_replace(dup, str);
- return dup;
- }
- return str;
-}
-
-#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
-
-/*
- * call-seq:
- * str.inspect => string
- *
- * Returns a printable version of _str_, with special characters
- * escaped.
- *
- * str = "hello"
- * str[3] = 8
- * str.inspect #=> "hel\010o"
- */
-
-VALUE
-rb_str_inspect(str)
- VALUE str;
-{
- char *p, *pend;
- VALUE result = rb_str_buf_new2("\"");
- char s[5];
-
- p = RSTRING(str)->ptr; pend = p + RSTRING(str)->len;
- while (p < pend) {
- char c = *p++;
- if (ismbchar(c) && p < pend) {
- int len = mbclen(c);
- rb_str_buf_cat(result, p - 1, len);
- p += len - 1;
- }
- else if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p, pend))) {
- s[0] = '\\'; s[1] = c;
- rb_str_buf_cat(result, s, 2);
- }
- else if (ISPRINT(c)) {
- s[0] = c;
- rb_str_buf_cat(result, s, 1);
- }
- else if (c == '\n') {
- s[0] = '\\'; s[1] = 'n';
- rb_str_buf_cat(result, s, 2);
- }
- else if (c == '\r') {
- s[0] = '\\'; s[1] = 'r';
- rb_str_buf_cat(result, s, 2);
- }
- else if (c == '\t') {
- s[0] = '\\'; s[1] = 't';
- rb_str_buf_cat(result, s, 2);
- }
- else if (c == '\f') {
- s[0] = '\\'; s[1] = 'f';
- rb_str_buf_cat(result, s, 2);
- }
- else if (c == '\013') {
- s[0] = '\\'; s[1] = 'v';
- rb_str_buf_cat(result, s, 2);
- }
- else if (c == '\007') {
- s[0] = '\\'; s[1] = 'a';
- rb_str_buf_cat(result, s, 2);
- }
- else if (c == 033) {
- s[0] = '\\'; s[1] = 'e';
- rb_str_buf_cat(result, s, 2);
- }
- else {
- sprintf(s, "\\%03o", c & 0377);
- rb_str_buf_cat2(result, s);
- }
- }
- rb_str_buf_cat2(result, "\"");
-
- OBJ_INFECT(result, str);
- return result;
-}
-
-
-/*
- * call-seq:
- * str.dump => new_str
- *
- * Produces a version of <i>str</i> with all nonprinting characters replaced by
- * <code>\nnn</code> notation and all special characters escaped.
- */
-
-VALUE
-rb_str_dump(str)
- VALUE str;
-{
- long len;
- char *p, *pend;
- char *q, *qend;
- VALUE result;
-
- len = 2; /* "" */
- p = RSTRING(str)->ptr; pend = p + RSTRING(str)->len;
- while (p < pend) {
- char c = *p++;
- switch (c) {
- case '"': case '\\':
- case '\n': case '\r':
- case '\t': case '\f':
- case '\013': case '\007': case '\033':
- len += 2;
- break;
-
- case '#':
- len += IS_EVSTR(p, pend) ? 2 : 1;
- break;
-
- default:
- if (ISPRINT(c)) {
- len++;
- }
- else {
- len += 4; /* \nnn */
- }
- break;
- }
- }
-
- result = rb_str_new5(str, 0, len);
- p = RSTRING(str)->ptr; pend = p + RSTRING(str)->len;
- q = RSTRING(result)->ptr; qend = q + len;
-
- *q++ = '"';
- while (p < pend) {
- char c = *p++;
-
- if (c == '"' || c == '\\') {
- *q++ = '\\';
- *q++ = c;
- }
- else if (c == '#') {
- if (IS_EVSTR(p, pend)) *q++ = '\\';
- *q++ = '#';
- }
- else if (ISPRINT(c)) {
- *q++ = c;
- }
- else if (c == '\n') {
- *q++ = '\\';
- *q++ = 'n';
- }
- else if (c == '\r') {
- *q++ = '\\';
- *q++ = 'r';
- }
- else if (c == '\t') {
- *q++ = '\\';
- *q++ = 't';
- }
- else if (c == '\f') {
- *q++ = '\\';
- *q++ = 'f';
- }
- else if (c == '\013') {
- *q++ = '\\';
- *q++ = 'v';
- }
- else if (c == '\007') {
- *q++ = '\\';
- *q++ = 'a';
- }
- else if (c == '\033') {
- *q++ = '\\';
- *q++ = 'e';
- }
- else {
- *q++ = '\\';
- sprintf(q, "%03o", c&0xff);
- q += 3;
- }
- }
- *q++ = '"';
-
- OBJ_INFECT(result, str);
- return result;
-}
-
-
-/*
- * call-seq:
- * str.upcase! => str or nil
- *
- * Upcases the contents of <i>str</i>, returning <code>nil</code> if no changes
- * were made.
- */
-
-static VALUE
-rb_str_upcase_bang(str)
- VALUE str;
-{
- char *s, *send;
- int modify = 0;
-
- rb_str_modify(str);
- s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
- while (s < send) {
- if (ismbchar(*s)) {
- s+=mbclen(*s) - 1;
- }
- else if (ISLOWER(*s)) {
- *s = toupper(*s);
- modify = 1;
- }
- s++;
- }
-
- if (modify) return str;
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.upcase => new_str
- *
- * Returns a copy of <i>str</i> with all lowercase letters replaced with their
- * uppercase counterparts. The operation is locale insensitive---only
- * characters ``a'' to ``z'' are affected.
- *
- * "hEllO".upcase #=> "HELLO"
- */
-
-static VALUE
-rb_str_upcase(str)
- VALUE str;
-{
- str = rb_str_dup(str);
- rb_str_upcase_bang(str);
- return str;
-}
-
-
-/*
- * call-seq:
- * str.downcase! => str or nil
- *
- * Downcases the contents of <i>str</i>, returning <code>nil</code> if no
- * changes were made.
- */
-
-static VALUE
-rb_str_downcase_bang(str)
- VALUE str;
-{
- char *s, *send;
- int modify = 0;
-
- rb_str_modify(str);
- s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
- while (s < send) {
- if (ismbchar(*s)) {
- s+=mbclen(*s) - 1;
- }
- else if (ISUPPER(*s)) {
- *s = tolower(*s);
- modify = 1;
- }
- s++;
- }
-
- if (modify) return str;
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.downcase => new_str
- *
- * Returns a copy of <i>str</i> with all uppercase letters replaced with their
- * lowercase counterparts. The operation is locale insensitive---only
- * characters ``A'' to ``Z'' are affected.
- *
- * "hEllO".downcase #=> "hello"
- */
-
-static VALUE
-rb_str_downcase(str)
- VALUE str;
-{
- str = rb_str_dup(str);
- rb_str_downcase_bang(str);
- return str;
-}
-
-
-/*
- * call-seq:
- * str.capitalize! => str or nil
- *
- * Modifies <i>str</i> by converting the first character to uppercase and the
- * remainder to lowercase. Returns <code>nil</code> if no changes are made.
- *
- * a = "hello"
- * a.capitalize! #=> "Hello"
- * a #=> "Hello"
- * a.capitalize! #=> nil
- */
-
-static VALUE
-rb_str_capitalize_bang(str)
- VALUE str;
-{
- char *s, *send;
- int modify = 0;
-
- rb_str_modify(str);
- if (RSTRING(str)->len == 0 || !RSTRING(str)->ptr) return Qnil;
- s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
- if (ISLOWER(*s)) {
- *s = toupper(*s);
- modify = 1;
- }
- while (++s < send) {
- if (ismbchar(*s)) {
- s+=mbclen(*s) - 1;
- }
- else if (ISUPPER(*s)) {
- *s = tolower(*s);
- modify = 1;
- }
- }
- if (modify) return str;
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.capitalize => new_str
- *
- * Returns a copy of <i>str</i> with the first character converted to uppercase
- * and the remainder to lowercase.
- *
- * "hello".capitalize #=> "Hello"
- * "HELLO".capitalize #=> "Hello"
- * "123ABC".capitalize #=> "123abc"
- */
-
-static VALUE
-rb_str_capitalize(str)
- VALUE str;
-{
- str = rb_str_dup(str);
- rb_str_capitalize_bang(str);
- return str;
-}
-
-
-/*
- * call-seq:
- * str.swapcase! => str or nil
- *
- * Equivalent to <code>String#swapcase</code>, but modifies the receiver in
- * place, returning <i>str</i>, or <code>nil</code> if no changes were made.
- */
-
-static VALUE
-rb_str_swapcase_bang(str)
- VALUE str;
-{
- char *s, *send;
- int modify = 0;
-
- rb_str_modify(str);
- s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
- while (s < send) {
- if (ismbchar(*s)) {
- s+=mbclen(*s) - 1;
- }
- else if (ISUPPER(*s)) {
- *s = tolower(*s);
- modify = 1;
- }
- else if (ISLOWER(*s)) {
- *s = toupper(*s);
- modify = 1;
- }
- s++;
- }
-
- if (modify) return str;
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.swapcase => new_str
- *
- * Returns a copy of <i>str</i> with uppercase alphabetic characters converted
- * to lowercase and lowercase characters converted to uppercase.
- *
- * "Hello".swapcase #=> "hELLO"
- * "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11"
- */
-
-static VALUE
-rb_str_swapcase(str)
- VALUE str;
-{
- str = rb_str_dup(str);
- rb_str_swapcase_bang(str);
- return str;
-}
-
-typedef unsigned char *USTR;
-
-struct tr {
- int gen, now, max;
- char *p, *pend;
-};
-
-static int
-trnext(t)
- struct tr *t;
-{
- for (;;) {
- if (!t->gen) {
- if (t->p == t->pend) return -1;
- if (t->p < t->pend - 1 && *t->p == '\\') {
- t->p++;
- }
- t->now = *(USTR)t->p++;
- if (t->p < t->pend - 1 && *t->p == '-') {
- t->p++;
- if (t->p < t->pend) {
- if (t->now > *(USTR)t->p) {
- t->p++;
- continue;
- }
- t->gen = 1;
- t->max = *(USTR)t->p++;
- }
- }
- return t->now;
- }
- else if (++t->now < t->max) {
- return t->now;
- }
- else {
- t->gen = 0;
- return t->max;
- }
- }
-}
-
-static VALUE rb_str_delete_bang _((int,VALUE*,VALUE));
-
-static VALUE
-tr_trans(str, src, repl, sflag)
- VALUE str, src, repl;
- int sflag;
-{
- struct tr trsrc, trrepl;
- int cflag = 0;
- int trans[256];
- int i, c, modify = 0;
- char *s, *send;
-
- StringValue(src);
- StringValue(repl);
- if (RSTRING(str)->len == 0 || !RSTRING(str)->ptr) return Qnil;
- trsrc.p = RSTRING(src)->ptr; trsrc.pend = trsrc.p + RSTRING(src)->len;
- if (RSTRING(src)->len >= 2 && RSTRING(src)->ptr[0] == '^') {
- cflag++;
- trsrc.p++;
- }
- if (RSTRING(repl)->len == 0) {
- return rb_str_delete_bang(1, &src, str);
- }
- trrepl.p = RSTRING(repl)->ptr;
- trrepl.pend = trrepl.p + RSTRING(repl)->len;
- trsrc.gen = trrepl.gen = 0;
- trsrc.now = trrepl.now = 0;
- trsrc.max = trrepl.max = 0;
-
- if (cflag) {
- for (i=0; i<256; i++) {
- trans[i] = 1;
- }
- while ((c = trnext(&trsrc)) >= 0) {
- trans[c & 0xff] = -1;
- }
- while ((c = trnext(&trrepl)) >= 0)
- /* retrieve last replacer */;
- for (i=0; i<256; i++) {
- if (trans[i] >= 0) {
- trans[i] = trrepl.now;
- }
- }
- }
- else {
- int r;
-
- for (i=0; i<256; i++) {
- trans[i] = -1;
- }
- while ((c = trnext(&trsrc)) >= 0) {
- r = trnext(&trrepl);
- if (r == -1) r = trrepl.now;
- trans[c & 0xff] = r;
- }
- }
-
- rb_str_modify(str);
- s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
- if (sflag) {
- char *t = s;
- int c0, last = -1;
-
- while (s < send) {
- c0 = *s++;
- if ((c = trans[c0 & 0xff]) >= 0) {
- if (last == c) continue;
- last = c;
- *t++ = c & 0xff;
- modify = 1;
- }
- else {
- last = -1;
- *t++ = c0;
- }
- }
- if (RSTRING(str)->len > (t - RSTRING(str)->ptr)) {
- RSTRING(str)->len = (t - RSTRING(str)->ptr);
- modify = 1;
- *t = '\0';
- }
- }
- else {
- while (s < send) {
- if ((c = trans[*s & 0xff]) >= 0) {
- *s = c & 0xff;
- modify = 1;
- }
- s++;
- }
- }
-
- if (modify) return str;
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.tr!(from_str, to_str) => str or nil
- *
- * Translates <i>str</i> in place, using the same rules as
- * <code>String#tr</code>. Returns <i>str</i>, or <code>nil</code> if no
- * changes were made.
- */
-
-static VALUE
-rb_str_tr_bang(str, src, repl)
- VALUE str, src, repl;
-{
- return tr_trans(str, src, repl, 0);
-}
-
-
-/*
- * call-seq:
- * str.tr(from_str, to_str) => new_str
- *
- * Returns a copy of <i>str</i> with the characters in <i>from_str</i> replaced
- * by the corresponding characters in <i>to_str</i>. If <i>to_str</i> is
- * shorter than <i>from_str</i>, it is padded with its last character. Both
- * strings may use the c1--c2 notation to denote ranges of characters, and
- * <i>from_str</i> may start with a <code>^</code>, which denotes all
- * characters except those listed.
- *
- * "hello".tr('aeiou', '*') #=> "h*ll*"
- * "hello".tr('^aeiou', '*') #=> "*e**o"
- * "hello".tr('el', 'ip') #=> "hippo"
- * "hello".tr('a-y', 'b-z') #=> "ifmmp"
- */
-
-static VALUE
-rb_str_tr(str, src, repl)
- VALUE str, src, repl;
-{
- str = rb_str_dup(str);
- tr_trans(str, src, repl, 0);
- return str;
-}
-
-static void
-tr_setup_table(str, table, init)
- VALUE str;
- char table[256];
- int init;
-{
- char buf[256];
- struct tr tr;
- int i, c;
- int cflag = 0;
-
- tr.p = RSTRING(str)->ptr; tr.pend = tr.p + RSTRING(str)->len;
- tr.gen = tr.now = tr.max = 0;
- if (RSTRING(str)->len > 1 && RSTRING(str)->ptr[0] == '^') {
- cflag = 1;
- tr.p++;
- }
-
- if (init) {
- for (i=0; i<256; i++) {
- table[i] = 1;
- }
- }
- for (i=0; i<256; i++) {
- buf[i] = cflag;
- }
- while ((c = trnext(&tr)) >= 0) {
- buf[c & 0xff] = !cflag;
- }
- for (i=0; i<256; i++) {
- table[i] = table[i] && buf[i];
- }
-}
-
-
-/*
- * call-seq:
- * str.delete!([other_str]+>) => str or nil
- *
- * Performs a <code>delete</code> operation in place, returning <i>str</i>, or
- * <code>nil</code> if <i>str</i> was not modified.
- */
-
-static VALUE
-rb_str_delete_bang(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- char *s, *send, *t;
- char squeez[256];
- int modify = 0;
- int init = 1;
- int i;
-
- if (argc < 1) {
- rb_raise(rb_eArgError, "wrong number of arguments");
- }
- for (i=0; i<argc; i++) {
- VALUE s = argv[i];
-
- StringValue(s);
- tr_setup_table(s, squeez, init);
- init = 0;
- }
-
- rb_str_modify(str);
- s = t = RSTRING(str)->ptr;
- if (!s || RSTRING(str)->len == 0) return Qnil;
- send = s + RSTRING(str)->len;
- while (s < send) {
- if (squeez[*s & 0xff])
- modify = 1;
- else
- *t++ = *s;
- s++;
- }
- *t = '\0';
- RSTRING(str)->len = t - RSTRING(str)->ptr;
-
- if (modify) return str;
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.delete([other_str]+) => new_str
- *
- * Returns a copy of <i>str</i> with all characters in the intersection of its
- * arguments deleted. Uses the same rules for building the set of characters as
- * <code>String#count</code>.
- *
- * "hello".delete "l","lo" #=> "heo"
- * "hello".delete "lo" #=> "he"
- * "hello".delete "aeiou", "^e" #=> "hell"
- * "hello".delete "ej-m" #=> "ho"
- */
-
-static VALUE
-rb_str_delete(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- str = rb_str_dup(str);
- rb_str_delete_bang(argc, argv, str);
- return str;
-}
-
-
-/*
- * call-seq:
- * str.squeeze!([other_str]*) => str or nil
- *
- * Squeezes <i>str</i> in place, returning either <i>str</i>, or
- * <code>nil</code> if no changes were made.
- */
-
-static VALUE
-rb_str_squeeze_bang(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- char squeez[256];
- char *s, *send, *t;
- int c, save, modify = 0;
- int init = 1;
- int i;
-
- if (argc == 0) {
- for (i=0; i<256; i++) {
- squeez[i] = 1;
- }
- }
- else {
- for (i=0; i<argc; i++) {
- VALUE s = argv[i];
-
- StringValue(s);
- tr_setup_table(s, squeez, init);
- init = 0;
- }
- }
-
- rb_str_modify(str);
- s = t = RSTRING(str)->ptr;
- if (!s || RSTRING(str)->len == 0) return Qnil;
- send = s + RSTRING(str)->len;
- save = -1;
- while (s < send) {
- c = *s++ & 0xff;
- if (c != save || !squeez[c]) {
- *t++ = save = c;
- }
- }
- *t = '\0';
- if (t - RSTRING(str)->ptr != RSTRING(str)->len) {
- RSTRING(str)->len = t - RSTRING(str)->ptr;
- modify = 1;
- }
-
- if (modify) return str;
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.squeeze([other_str]*) => new_str
- *
- * Builds a set of characters from the <i>other_str</i> parameter(s) using the
- * procedure described for <code>String#count</code>. Returns a new string
- * where runs of the same character that occur in this set are replaced by a
- * single character. If no arguments are given, all runs of identical
- * characters are replaced by a single character.
- *
- * "yellow moon".squeeze #=> "yelow mon"
- * " now is the".squeeze(" ") #=> " now is the"
- * "putters shoot balls".squeeze("m-z") #=> "puters shot balls"
- */
-
-static VALUE
-rb_str_squeeze(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- str = rb_str_dup(str);
- rb_str_squeeze_bang(argc, argv, str);
- return str;
-}
-
-
-/*
- * call-seq:
- * str.tr_s!(from_str, to_str) => str or nil
- *
- * Performs <code>String#tr_s</code> processing on <i>str</i> in place,
- * returning <i>str</i>, or <code>nil</code> if no changes were made.
- */
-
-static VALUE
-rb_str_tr_s_bang(str, src, repl)
- VALUE str, src, repl;
-{
- return tr_trans(str, src, repl, 1);
-}
-
-
-/*
- * call-seq:
- * str.tr_s(from_str, to_str) => new_str
- *
- * Processes a copy of <i>str</i> as described under <code>String#tr</code>,
- * then removes duplicate characters in regions that were affected by the
- * translation.
- *
- * "hello".tr_s('l', 'r') #=> "hero"
- * "hello".tr_s('el', '*') #=> "h*o"
- * "hello".tr_s('el', 'hx') #=> "hhxo"
- */
-
-static VALUE
-rb_str_tr_s(str, src, repl)
- VALUE str, src, repl;
-{
- str = rb_str_dup(str);
- tr_trans(str, src, repl, 1);
- return str;
-}
-
-
-/*
- * call-seq:
- * str.count([other_str]+) => fixnum
- *
- * Each <i>other_str</i> parameter defines a set of characters to count. The
- * intersection of these sets defines the characters to count in
- * <i>str</i>. Any <i>other_str</i> that starts with a caret (^) is
- * negated. The sequence c1--c2 means all characters between c1 and c2.
- *
- * a = "hello world"
- * a.count "lo" #=> 5
- * a.count "lo", "o" #=> 2
- * a.count "hello", "^l" #=> 4
- * a.count "ej-m" #=> 4
- */
-
-static VALUE
-rb_str_count(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- char table[256];
- char *s, *send;
- int init = 1;
- int i;
-
- if (argc < 1) {
- rb_raise(rb_eArgError, "wrong number of arguments");
- }
- for (i=0; i<argc; i++) {
- VALUE s = argv[i];
-
- StringValue(s);
- tr_setup_table(s, table, init);
- init = 0;
- }
-
- s = RSTRING(str)->ptr;
- if (!s || RSTRING(str)->len == 0) return INT2FIX(0);
- send = s + RSTRING(str)->len;
- i = 0;
- while (s < send) {
- if (table[*s++ & 0xff]) {
- i++;
- }
- }
- return INT2NUM(i);
-}
-
-
-/*
- * call-seq:
- * str.split(pattern=$;, [limit]) => anArray
- *
- * Divides <i>str</i> into substrings based on a delimiter, returning an array
- * of these substrings.
- *
- * If <i>pattern</i> is a <code>String</code>, then its contents are used as
- * the delimiter when splitting <i>str</i>. If <i>pattern</i> is a single
- * space, <i>str</i> is split on whitespace, with leading whitespace and runs
- * of contiguous whitespace characters ignored.
- *
- * If <i>pattern</i> is a <code>Regexp</code>, <i>str</i> is divided where the
- * pattern matches. Whenever the pattern matches a zero-length string,
- * <i>str</i> is split into individual characters.
- *
- * If <i>pattern</i> is omitted, the value of <code>$;</code> is used. If
- * <code>$;</code> is <code>nil</code> (which is the default), <i>str</i> is
- * split on whitespace as if ` ' were specified.
- *
- * If the <i>limit</i> parameter is omitted, trailing null fields are
- * suppressed. If <i>limit</i> is a positive number, at most that number of
- * fields will be returned (if <i>limit</i> is <code>1</code>, the entire
- * string is returned as the only entry in an array). If negative, there is no
- * limit to the number of fields returned, and trailing null fields are not
- * suppressed.
- *
- * " now's the time".split #=> ["now's", "the", "time"]
- * " now's the time".split(' ') #=> ["now's", "the", "time"]
- * " now's the time".split(/ /) #=> ["", "now's", "", "the", "time"]
- * "1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"]
- * "hello".split(//) #=> ["h", "e", "l", "l", "o"]
- * "hello".split(//, 3) #=> ["h", "e", "llo"]
- * "hi mom".split(%r{\s*}) #=> ["h", "i", "m", "o", "m"]
- *
- * "mellow yellow".split("ello") #=> ["m", "w y", "w"]
- * "1,2,,3,4,,".split(',') #=> ["1", "2", "", "3", "4"]
- * "1,2,,3,4,,".split(',', 4) #=> ["1", "2", "", "3,4,,"]
- * "1,2,,3,4,,".split(',', -4) #=> ["1", "2", "", "3", "4", "", ""]
- */
-
-static VALUE
-rb_str_split_m(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- VALUE spat;
- VALUE limit;
- int awk_split = Qfalse;
- long beg, end, i = 0;
- int lim = 0;
- VALUE result, tmp;
-
- if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) {
- lim = NUM2INT(limit);
- if (lim <= 0) limit = Qnil;
- else if (lim == 1) {
- if (RSTRING(str)->len == 0)
- return rb_ary_new2(0);
- return rb_ary_new3(1, str);
- }
- i = 1;
- }
-
- if (NIL_P(spat)) {
- if (!NIL_P(rb_fs)) {
- spat = rb_fs;
- goto fs_set;
- }
- awk_split = Qtrue;
- }
- else {
- fs_set:
- if (TYPE(spat) == T_STRING && RSTRING(spat)->len == 1) {
- if (RSTRING(spat)->ptr[0] == ' ') {
- awk_split = Qtrue;
- }
- else {
- spat = rb_reg_regcomp(rb_reg_quote(spat));
- }
- }
- else {
- spat = get_pat(spat, 1);
- }
- }
-
- result = rb_ary_new();
- beg = 0;
- if (awk_split) {
- char *ptr = RSTRING(str)->ptr;
- long len = RSTRING(str)->len;
- char *eptr = ptr + len;
- int skip = 1;
-
- for (end = beg = 0; ptr<eptr; ptr++) {
- if (skip) {
- if (ISSPACE(*ptr)) {
- beg++;
- }
- else {
- end = beg+1;
- skip = 0;
- if (!NIL_P(limit) && lim <= i) break;
- }
- }
- else {
- if (ISSPACE(*ptr)) {
- rb_ary_push(result, rb_str_substr(str, beg, end-beg));
- skip = 1;
- beg = end + 1;
- if (!NIL_P(limit)) ++i;
- }
- else {
- end++;
- }
- }
- }
- }
- else {
- long start = beg;
- long idx;
- int last_null = 0;
- struct re_registers *regs;
-
- while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
- regs = RMATCH(rb_backref_get())->regs;
- if (start == end && BEG(0) == END(0)) {
- if (!RSTRING(str)->ptr) {
- rb_ary_push(result, rb_str_new("", 0));
- break;
- }
- else if (last_null == 1) {
- rb_ary_push(result, rb_str_substr(str, beg, mbclen2(RSTRING(str)->ptr[beg],spat)));
- beg = start;
- }
- else {
- start += mbclen2(RSTRING(str)->ptr[start],spat);
- last_null = 1;
- continue;
- }
- }
- else {
- rb_ary_push(result, rb_str_substr(str, beg, end-beg));
- beg = start = END(0);
- }
- last_null = 0;
-
- for (idx=1; idx < regs->num_regs; idx++) {
- if (BEG(idx) == -1) continue;
- if (BEG(idx) == END(idx))
- tmp = rb_str_new5(str, 0, 0);
- else
- tmp = rb_str_substr(str, BEG(idx), END(idx)-BEG(idx));
- rb_ary_push(result, tmp);
- }
- if (!NIL_P(limit) && lim <= ++i) break;
- }
- }
- if (RSTRING(str)->len > 0 && (!NIL_P(limit) || RSTRING(str)->len > beg || lim < 0)) {
- if (RSTRING(str)->len == beg)
- tmp = rb_str_new5(str, 0, 0);
- else
- tmp = rb_str_substr(str, beg, RSTRING(str)->len-beg);
- rb_ary_push(result, tmp);
- }
- if (NIL_P(limit) && lim == 0) {
- while (RARRAY(result)->len > 0 &&
- RSTRING(RARRAY(result)->ptr[RARRAY(result)->len-1])->len == 0)
- rb_ary_pop(result);
- }
-
- return result;
-}
-
-VALUE
-rb_str_split(str, sep0)
- VALUE str;
- const char *sep0;
-{
- VALUE sep;
-
- StringValue(str);
- sep = rb_str_new2(sep0);
- return rb_str_split_m(1, &sep, str);
-}
-
-/*
- * call-seq:
- * split([pattern [, limit]]) => array
- *
- * Equivalent to <code>$_.split(<i>pattern</i>, <i>limit</i>)</code>.
- * See <code>String#split</code>.
- */
-
-static VALUE
-rb_f_split(argc, argv)
- int argc;
- VALUE *argv;
-{
- return rb_str_split_m(argc, argv, uscore_get());
-}
-
-/*
- * call-seq:
- * str.each(separator=$/) {|substr| block } => str
- * str.each_line(separator=$/) {|substr| block } => str
- *
- * Splits <i>str</i> using the supplied parameter as the record separator
- * (<code>$/</code> by default), passing each substring in turn to the supplied
- * block. If a zero-length record separator is supplied, the string is split on
- * <code>\n</code> characters, except that multiple successive newlines are
- * appended together.
- *
- * print "Example one\n"
- * "hello\nworld".each {|s| p s}
- * print "Example two\n"
- * "hello\nworld".each('l') {|s| p s}
- * print "Example three\n"
- * "hello\n\n\nworld".each('') {|s| p s}
- *
- * <em>produces:</em>
- *
- * Example one
- * "hello\n"
- * "world"
- * Example two
- * "hel"
- * "l"
- * "o\nworl"
- * "d"
- * Example three
- * "hello\n\n\n"
- * "world"
- */
-
-static VALUE
-rb_str_each_line(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- VALUE rs;
- int newline;
- char *p = RSTRING(str)->ptr, *pend = p + RSTRING(str)->len, *s;
- char *ptr = p;
- long len = RSTRING(str)->len, rslen;
- VALUE line;
-
- if (rb_scan_args(argc, argv, "01", &rs) == 0) {
- rs = rb_rs;
- }
-
- if (NIL_P(rs)) {
- rb_yield(str);
- return str;
- }
- StringValue(rs);
- rslen = RSTRING(rs)->len;
- if (rslen == 0) {
- newline = '\n';
- }
- else {
- newline = RSTRING(rs)->ptr[rslen-1];
- }
-
- for (s = p, p += rslen; p < pend; p++) {
- if (rslen == 0 && *p == '\n') {
- if (*++p != '\n') continue;
- while (*p == '\n') p++;
- }
- if (RSTRING(str)->ptr < p && p[-1] == newline &&
- (rslen <= 1 ||
- rb_memcmp(RSTRING(rs)->ptr, p-rslen, rslen) == 0)) {
- line = rb_str_new5(str, s, p - s);
- OBJ_INFECT(line, str);
- rb_yield(line);
- str_mod_check(str, ptr, len);
- s = p;
- }
- }
-
- if (s != pend) {
- if (p > pend) p = pend;
- line = rb_str_new5(str, s, p - s);
- OBJ_INFECT(line, str);
- rb_yield(line);
- }
-
- return str;
-}
-
-
-/*
- * call-seq:
- * str.each_byte {|fixnum| block } => str
- *
- * Passes each byte in <i>str</i> to the given block.
- *
- * "hello".each_byte {|c| print c, ' ' }
- *
- * <em>produces:</em>
- *
- * 104 101 108 108 111
- */
-
-static VALUE
-rb_str_each_byte(str)
- VALUE str;
-{
- long i;
-
- for (i=0; i<RSTRING(str)->len; i++) {
- rb_yield(INT2FIX(RSTRING(str)->ptr[i] & 0xff));
- }
- return str;
-}
-
-
-/*
- * call-seq:
- * str.chop! => str or nil
- *
- * Processes <i>str</i> as for <code>String#chop</code>, returning <i>str</i>,
- * or <code>nil</code> if <i>str</i> is the empty string. See also
- * <code>String#chomp!</code>.
- */
-
-static VALUE
-rb_str_chop_bang(str)
- VALUE str;
-{
- if (RSTRING(str)->len > 0) {
- rb_str_modify(str);
- RSTRING(str)->len--;
- if (RSTRING(str)->ptr[RSTRING(str)->len] == '\n') {
- if (RSTRING(str)->len > 0 &&
- RSTRING(str)->ptr[RSTRING(str)->len-1] == '\r') {
- RSTRING(str)->len--;
- }
- }
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
- return str;
- }
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.chop => new_str
- *
- * Returns a new <code>String</code> with the last character removed. If the
- * string ends with <code>\r\n</code>, both characters are removed. Applying
- * <code>chop</code> to an empty string returns an empty
- * string. <code>String#chomp</code> is often a safer alternative, as it leaves
- * the string unchanged if it doesn't end in a record separator.
- *
- * "string\r\n".chop #=> "string"
- * "string\n\r".chop #=> "string\n"
- * "string\n".chop #=> "string"
- * "string".chop #=> "strin"
- * "x".chop.chop #=> ""
- */
-
-static VALUE
-rb_str_chop(str)
- VALUE str;
-{
- str = rb_str_dup(str);
- rb_str_chop_bang(str);
- return str;
-}
-
-
-/*
- * call-seq:
- * chop! => $_ or nil
- *
- * Equivalent to <code>$_.chop!</code>.
- *
- * a = "now\r\n"
- * $_ = a
- * chop! #=> "now"
- * chop! #=> "no"
- * chop! #=> "n"
- * chop! #=> ""
- * chop! #=> nil
- * $_ #=> ""
- * a #=> ""
- */
-
-static VALUE
-rb_f_chop_bang(str)
- VALUE str;
-{
- return rb_str_chop_bang(uscore_get());
-}
-
-/*
- * call-seq:
- * chop => string
- *
- * Equivalent to <code>($_.dup).chop!</code>, except <code>nil</code>
- * is never returned. See <code>String#chop!</code>.
- *
- * a = "now\r\n"
- * $_ = a
- * chop #=> "now"
- * $_ #=> "now"
- * chop #=> "no"
- * chop #=> "n"
- * chop #=> ""
- * chop #=> ""
- * a #=> "now\r\n"
- */
-
-static VALUE
-rb_f_chop()
-{
- VALUE str = uscore_get();
-
- if (RSTRING(str)->len > 0) {
- str = rb_str_dup(str);
- rb_str_chop_bang(str);
- rb_lastline_set(str);
- }
- return str;
-}
-
-
-/*
- * call-seq:
- * str.chomp!(separator=$/) => str or nil
- *
- * Modifies <i>str</i> in place as described for <code>String#chomp</code>,
- * returning <i>str</i>, or <code>nil</code> if no modifications were made.
- */
-
-static VALUE
-rb_str_chomp_bang(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- VALUE rs;
- int newline;
- char *p;
- long len, rslen;
-
- if (rb_scan_args(argc, argv, "01", &rs) == 0) {
- len = RSTRING(str)->len;
- if (len == 0) return Qnil;
- p = RSTRING(str)->ptr;
- rs = rb_rs;
- if (rs == rb_default_rs) {
- smart_chomp:
- rb_str_modify(str);
- if (RSTRING(str)->ptr[len-1] == '\n') {
- RSTRING(str)->len--;
- if (RSTRING(str)->len > 0 &&
- RSTRING(str)->ptr[RSTRING(str)->len-1] == '\r') {
- RSTRING(str)->len--;
- }
- }
- else if (RSTRING(str)->ptr[len-1] == '\r') {
- RSTRING(str)->len--;
- }
- else {
- return Qnil;
- }
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
- return str;
- }
- }
- if (NIL_P(rs)) return Qnil;
- StringValue(rs);
- len = RSTRING(str)->len;
- if (len == 0) return Qnil;
- p = RSTRING(str)->ptr;
- rslen = RSTRING(rs)->len;
- if (rslen == 0) {
- while (len>0 && p[len-1] == '\n') {
- len--;
- if (len>0 && p[len-1] == '\r')
- len--;
- }
- if (len < RSTRING(str)->len) {
- rb_str_modify(str);
- RSTRING(str)->len = len;
- RSTRING(str)->ptr[len] = '\0';
- return str;
- }
- return Qnil;
- }
- if (rslen > len) return Qnil;
- newline = RSTRING(rs)->ptr[rslen-1];
- if (rslen == 1 && newline == '\n')
- goto smart_chomp;
-
- if (p[len-1] == newline &&
- (rslen <= 1 ||
- rb_memcmp(RSTRING(rs)->ptr, p+len-rslen, rslen) == 0)) {
- rb_str_modify(str);
- RSTRING(str)->len -= rslen;
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
- return str;
- }
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.chomp(separator=$/) => new_str
- *
- * Returns a new <code>String</code> with the given record separator removed
- * from the end of <i>str</i> (if present). If <code>$/</code> has not been
- * changed from the default Ruby record separator, then <code>chomp</code> also
- * removes carriage return characters (that is it will remove <code>\n</code>,
- * <code>\r</code>, and <code>\r\n</code>).
- *
- * "hello".chomp #=> "hello"
- * "hello\n".chomp #=> "hello"
- * "hello\r\n".chomp #=> "hello"
- * "hello\n\r".chomp #=> "hello\n"
- * "hello\r".chomp #=> "hello"
- * "hello \n there".chomp #=> "hello \n there"
- * "hello".chomp("llo") #=> "he"
- */
-
-static VALUE
-rb_str_chomp(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- str = rb_str_dup(str);
- rb_str_chomp_bang(argc, argv, str);
- return str;
-}
-
-/*
- * call-seq:
- * chomp! => $_ or nil
- * chomp!(string) => $_ or nil
- *
- * Equivalent to <code>$_.chomp!(<em>string</em>)</code>. See
- * <code>String#chomp!</code>
- *
- * $_ = "now\n"
- * chomp! #=> "now"
- * $_ #=> "now"
- * chomp! "x" #=> nil
- * $_ #=> "now"
- */
-
-static VALUE
-rb_f_chomp_bang(argc, argv)
- int argc;
- VALUE *argv;
-{
- return rb_str_chomp_bang(argc, argv, uscore_get());
-}
-
-/*
- * call-seq:
- * chomp => $_
- * chomp(string) => $_
- *
- * Equivalent to <code>$_ = $_.chomp(<em>string</em>)</code>. See
- * <code>String#chomp</code>.
- *
- * $_ = "now\n"
- * chomp #=> "now"
- * $_ #=> "now"
- * chomp "ow" #=> "n"
- * $_ #=> "n"
- * chomp "xxx" #=> "n"
- * $_ #=> "n"
- */
-
-static VALUE
-rb_f_chomp(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE str = uscore_get();
- VALUE dup = rb_str_dup(str);
-
- if (NIL_P(rb_str_chomp_bang(argc, argv, dup)))
- return str;
- rb_lastline_set(dup);
- return dup;
-}
-
-
-/*
- * call-seq:
- * str.lstrip! => self or nil
- *
- * Removes leading whitespace from <i>str</i>, returning <code>nil</code> if no
- * change was made. See also <code>String#rstrip!</code> and
- * <code>String#strip!</code>.
- *
- * " hello ".lstrip #=> "hello "
- * "hello".lstrip! #=> nil
- */
-
-static VALUE
-rb_str_lstrip_bang(str)
- VALUE str;
-{
- char *s, *t, *e;
-
- s = RSTRING(str)->ptr;
- if (!s || RSTRING(str)->len == 0) return Qnil;
- e = t = s + RSTRING(str)->len;
- /* remove spaces at head */
- while (s < t && ISSPACE(*s)) s++;
-
- if (s > RSTRING(str)->ptr) {
- rb_str_modify(str);
- RSTRING(str)->len = t-s;
- memmove(RSTRING(str)->ptr, s, RSTRING(str)->len);
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
- return str;
- }
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.lstrip => new_str
- *
- * Returns a copy of <i>str</i> with leading whitespace removed. See also
- * <code>String#rstrip</code> and <code>String#strip</code>.
- *
- * " hello ".lstrip #=> "hello "
- * "hello".lstrip #=> "hello"
- */
-
-static VALUE
-rb_str_lstrip(str)
- VALUE str;
-{
- str = rb_str_dup(str);
- rb_str_lstrip_bang(str);
- return str;
-}
-
-
-/*
- * call-seq:
- * str.rstrip! => self or nil
- *
- * Removes trailing whitespace from <i>str</i>, returning <code>nil</code> if
- * no change was made. See also <code>String#lstrip!</code> and
- * <code>String#strip!</code>.
- *
- * " hello ".rstrip #=> " hello"
- * "hello".rstrip! #=> nil
- */
-
-static VALUE
-rb_str_rstrip_bang(str)
- VALUE str;
-{
- char *s, *t, *e;
-
- s = RSTRING(str)->ptr;
- if (!s || RSTRING(str)->len == 0) return Qnil;
- e = t = s + RSTRING(str)->len;
-
- /* remove trailing '\0's */
- while (s < t && t[-1] == '\0') t--;
-
- /* remove trailing spaces */
- while (s < t && ISSPACE(*(t-1))) t--;
-
- if (t < e) {
- rb_str_modify(str);
- RSTRING(str)->len = t-s;
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
- return str;
- }
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.rstrip => new_str
- *
- * Returns a copy of <i>str</i> with trailing whitespace removed. See also
- * <code>String#lstrip</code> and <code>String#strip</code>.
- *
- * " hello ".rstrip #=> " hello"
- * "hello".rstrip #=> "hello"
- */
-
-static VALUE
-rb_str_rstrip(str)
- VALUE str;
-{
- str = rb_str_dup(str);
- rb_str_rstrip_bang(str);
- return str;
-}
-
-
-/*
- * call-seq:
- * str.strip! => str or nil
- *
- * Removes leading and trailing whitespace from <i>str</i>. Returns
- * <code>nil</code> if <i>str</i> was not altered.
- */
-
-static VALUE
-rb_str_strip_bang(str)
- VALUE str;
-{
- VALUE l = rb_str_lstrip_bang(str);
- VALUE r = rb_str_rstrip_bang(str);
-
- if (NIL_P(l) && NIL_P(r)) return Qnil;
- return str;
-}
-
-
-/*
- * call-seq:
- * str.strip => new_str
- *
- * Returns a copy of <i>str</i> with leading and trailing whitespace removed.
- *
- * " hello ".strip #=> "hello"
- * "\tgoodbye\r\n".strip #=> "goodbye"
- */
-
-static VALUE
-rb_str_strip(str)
- VALUE str;
-{
- str = rb_str_dup(str);
- rb_str_strip_bang(str);
- return str;
-}
-
-static VALUE
-scan_once(str, pat, start)
- VALUE str, pat;
- long *start;
-{
- VALUE result, match;
- struct re_registers *regs;
- long i;
-
- if (rb_reg_search(pat, str, *start, 0) >= 0) {
- match = rb_backref_get();
- regs = RMATCH(match)->regs;
- if (BEG(0) == END(0)) {
- /*
- * Always consume at least one character of the input string
- */
- if (RSTRING(str)->len < END(0))
- *start = END(0)+mbclen2(RSTRING(str)->ptr[END(0)],pat);
- else
- *start = END(0)+1;
- }
- else {
- *start = END(0);
- }
- if (regs->num_regs == 1) {
- return rb_reg_nth_match(0, match);
- }
- result = rb_ary_new2(regs->num_regs);
- for (i=1; i < regs->num_regs; i++) {
- rb_ary_push(result, rb_reg_nth_match(i, match));
- }
-
- return result;
- }
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * str.scan(pattern) => array
- * str.scan(pattern) {|match, ...| block } => str
- *
- * Both forms iterate through <i>str</i>, matching the pattern (which may be a
- * <code>Regexp</code> or a <code>String</code>). For each match, a result is
- * generated and either added to the result array or passed to the block. If
- * the pattern contains no groups, each individual result consists of the
- * matched string, <code>$&</code>. If the pattern contains groups, each
- * individual result is itself an array containing one entry per group.
- *
- * a = "cruel world"
- * a.scan(/\w+/) #=> ["cruel", "world"]
- * a.scan(/.../) #=> ["cru", "el ", "wor"]
- * a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]]
- * a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]]
- *
- * And the block form:
- *
- * a.scan(/\w+/) {|w| print "<<#{w}>> " }
- * print "\n"
- * a.scan(/(.)(.)/) {|a,b| print b, a }
- * print "\n"
- *
- * <em>produces:</em>
- *
- * <<cruel>> <<world>>
- * rceu lowlr
- */
-
-static VALUE
-rb_str_scan(str, pat)
- VALUE str, pat;
-{
- VALUE result;
- long start = 0;
- VALUE match = Qnil;
-
- pat = get_pat(pat, 1);
- if (!rb_block_given_p()) {
- VALUE ary = rb_ary_new();
-
- while (!NIL_P(result = scan_once(str, pat, &start))) {
- match = rb_backref_get();
- rb_ary_push(ary, result);
- }
- rb_backref_set(match);
- return ary;
- }
-
- while (!NIL_P(result = scan_once(str, pat, &start))) {
- match = rb_backref_get();
- rb_match_busy(match);
- rb_yield(result);
- rb_backref_set(match); /* restore $~ value */
- }
- rb_backref_set(match);
- return str;
-}
-
-/*
- * call-seq:
- * scan(pattern) => array
- * scan(pattern) {|///| block } => $_
- *
- * Equivalent to calling <code>$_.scan</code>. See
- * <code>String#scan</code>.
- */
-
-static VALUE
-rb_f_scan(self, pat)
- VALUE self, pat;
-{
- return rb_str_scan(uscore_get(), pat);
-}
-
-
-/*
- * call-seq:
- * str.hex => integer
- *
- * Treats leading characters from <i>str</i> as a string of hexadecimal digits
- * (with an optional sign and an optional <code>0x</code>) and returns the
- * corresponding number. Zero is returned on error.
- *
- * "0x0a".hex #=> 10
- * "-1234".hex #=> -4660
- * "0".hex #=> 0
- * "wombat".hex #=> 0
- */
-
-static VALUE
-rb_str_hex(str)
- VALUE str;
-{
- return rb_str_to_inum(str, 16, Qfalse);
-}
-
-
-/*
- * call-seq:
- * str.oct => integer
- *
- * Treats leading characters of <i>str</i> as a string of octal digits (with an
- * optional sign) and returns the corresponding number. Returns 0 if the
- * conversion fails.
- *
- * "123".oct #=> 83
- * "-377".oct #=> -255
- * "bad".oct #=> 0
- * "0377bad".oct #=> 255
- */
-
-static VALUE
-rb_str_oct(str)
- VALUE str;
-{
- return rb_str_to_inum(str, -8, Qfalse);
-}
-
-
-/*
- * call-seq:
- * str.crypt(other_str) => new_str
- *
- * Applies a one-way cryptographic hash to <i>str</i> by invoking the standard
- * library function <code>crypt</code>. The argument is the salt string, which
- * should be two characters long, each character drawn from
- * <code>[a-zA-Z0-9./]</code>.
- */
-
-static VALUE
-rb_str_crypt(str, salt)
- VALUE str, salt;
-{
- extern char *crypt();
- VALUE result;
- char *s;
-
- StringValue(salt);
- if (RSTRING(salt)->len < 2)
- rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
-
- if (RSTRING(str)->ptr) s = RSTRING(str)->ptr;
- else s = "";
- result = rb_str_new2(crypt(s, RSTRING(salt)->ptr));
- OBJ_INFECT(result, str);
- OBJ_INFECT(result, salt);
- return result;
-}
-
-
-/*
- * call-seq:
- * str.intern => symbol
- * str.to_sym => symbol
- *
- * Returns the <code>Symbol</code> corresponding to <i>str</i>, creating the
- * symbol if it did not previously exist. See <code>Symbol#id2name</code>.
- *
- * "Koala".intern #=> :Koala
- * s = 'cat'.to_sym #=> :cat
- * s == :cat #=> true
- * s = '@cat'.to_sym #=> :@cat
- * s == :@cat #=> true
- *
- * This can also be used to create symbols that cannot be represented using the
- * <code>:xxx</code> notation.
- *
- * 'cat and dog'.to_sym #=> :"cat and dog"
- */
-
-VALUE
-rb_str_intern(s)
- VALUE s;
-{
- volatile VALUE str = s;
- ID id;
-
- if (!RSTRING(str)->ptr || RSTRING(str)->len == 0) {
- rb_raise(rb_eArgError, "interning empty string");
- }
- if (strlen(RSTRING(str)->ptr) != RSTRING(str)->len)
- rb_raise(rb_eArgError, "symbol string may not contain `\\0'");
- id = rb_intern(RSTRING(str)->ptr);
- return ID2SYM(id);
-}
-
-
-/*
- * call-seq:
- * str.sum(n=16) => integer
- *
- * Returns a basic <em>n</em>-bit checksum of the characters in <i>str</i>,
- * where <em>n</em> is the optional <code>Fixnum</code> parameter, defaulting
- * to 16. The result is simply the sum of the binary value of each character in
- * <i>str</i> modulo <code>2n - 1</code>. This is not a particularly good
- * checksum.
- */
-
-static VALUE
-rb_str_sum(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- VALUE vbits;
- int bits;
- char *ptr, *p, *pend;
- long len;
-
- if (rb_scan_args(argc, argv, "01", &vbits) == 0) {
- bits = 16;
- }
- else bits = NUM2INT(vbits);
-
- ptr = p = RSTRING(str)->ptr;
- len = RSTRING(str)->len;
- pend = p + len;
- if (bits >= sizeof(long)*CHAR_BIT) {
- VALUE sum = INT2FIX(0);
-
- while (p < pend) {
- str_mod_check(str, ptr, len);
- sum = rb_funcall(sum, '+', 1, INT2FIX((unsigned char)*p));
- p++;
- }
- if (bits != 0) {
- VALUE mod;
-
- mod = rb_funcall(INT2FIX(1), rb_intern("<<"), 1, INT2FIX(bits));
- mod = rb_funcall(mod, '-', 1, INT2FIX(1));
- sum = rb_funcall(sum, '&', 1, mod);
- }
- return sum;
- }
- else {
- unsigned long sum = 0;
-
- while (p < pend) {
- str_mod_check(str, ptr, len);
- sum += (unsigned char)*p;
- p++;
- }
- if (bits != 0) {
- sum &= (((unsigned long)1)<<bits)-1;
- }
- return rb_int2inum(sum);
- }
-}
-
-static VALUE
-rb_str_justify(argc, argv, str, jflag)
- int argc;
- VALUE *argv;
- VALUE str;
- char jflag;
-{
- VALUE w;
- long width, flen = 0;
- VALUE res;
- char *p, *pend, *f = " ";
- long n;
- VALUE pad;
-
- rb_scan_args(argc, argv, "11", &w, &pad);
- width = NUM2LONG(w);
- if (argc == 2) {
- StringValue(pad);
- f = RSTRING(pad)->ptr;
- flen = RSTRING(pad)->len;
- if (flen == 0) {
- rb_raise(rb_eArgError, "zero width padding");
- }
- }
- if (width < 0 || RSTRING(str)->len >= width) return rb_str_dup(str);
- res = rb_str_new5(str, 0, width);
- p = RSTRING(res)->ptr;
- if (jflag != 'l') {
- n = width - RSTRING(str)->len;
- pend = p + ((jflag == 'r') ? n : n/2);
- if (flen <= 1) {
- while (p < pend) {
- *p++ = *f;
- }
- }
- else {
- char *q = f;
- while (p + flen <= pend) {
- memcpy(p,f,flen);
- p += flen;
- }
- while (p < pend) {
- *p++ = *q++;
- }
- }
- }
- memcpy(p, RSTRING(str)->ptr, RSTRING(str)->len);
- if (jflag != 'r') {
- p += RSTRING(str)->len; pend = RSTRING(res)->ptr + width;
- if (flen <= 1) {
- while (p < pend) {
- *p++ = *f;
- }
- }
- else {
- while (p + flen <= pend) {
- memcpy(p,f,flen);
- p += flen;
- }
- while (p < pend) {
- *p++ = *f++;
- }
- }
- }
- OBJ_INFECT(res, str);
- if (flen > 0) OBJ_INFECT(res, pad);
- return res;
-}
-
-
-/*
- * call-seq:
- * str.ljust(integer, padstr=' ') => new_str
- *
- * If <i>integer</i> is greater than the length of <i>str</i>, returns a new
- * <code>String</code> of length <i>integer</i> with <i>str</i> left justified
- * and padded with <i>padstr</i>; otherwise, returns <i>str</i>.
- *
- * "hello".ljust(4) #=> "hello"
- * "hello".ljust(20) #=> "hello "
- * "hello".ljust(20, '1234') #=> "hello123412341234123"
- */
-
-static VALUE
-rb_str_ljust(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- return rb_str_justify(argc, argv, str, 'l');
-}
-
-
-/*
- * call-seq:
- * str.rjust(integer, padstr=' ') => new_str
- *
- * If <i>integer</i> is greater than the length of <i>str</i>, returns a new
- * <code>String</code> of length <i>integer</i> with <i>str</i> right justified
- * and padded with <i>padstr</i>; otherwise, returns <i>str</i>.
- *
- * "hello".rjust(4) #=> "hello"
- * "hello".rjust(20) #=> " hello"
- * "hello".rjust(20, '1234') #=> "123412341234123hello"
- */
-
-static VALUE
-rb_str_rjust(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- return rb_str_justify(argc, argv, str, 'r');
-}
-
-
-/*
- * call-seq:
- * str.center(integer, padstr) => new_str
- *
- * If <i>integer</i> is greater than the length of <i>str</i>, returns a new
- * <code>String</code> of length <i>integer</i> with <i>str</i> centered and
- * padded with <i>padstr</i>; otherwise, returns <i>str</i>.
- *
- * "hello".center(4) #=> "hello"
- * "hello".center(20) #=> " hello "
- * "hello".center(20, '123') #=> "1231231hello12312312"
- */
-
-static VALUE
-rb_str_center(argc, argv, str)
- int argc;
- VALUE *argv;
- VALUE str;
-{
- return rb_str_justify(argc, argv, str, 'c');
-}
-
-void
-rb_str_setter(val, id, var)
- VALUE val;
- ID id;
- VALUE *var;
-{
- if (!NIL_P(val) && TYPE(val) != T_STRING) {
- rb_raise(rb_eTypeError, "value of %s must be String", rb_id2name(id));
- }
- *var = val;
-}
-
-
-/*
- * A <code>String</code> object holds and manipulates an arbitrary sequence of
- * bytes, typically representing characters. String objects may be created
- * using <code>String::new</code> or as literals.
- *
- * Because of aliasing issues, users of strings should be aware of the methods
- * that modify the contents of a <code>String</code> object. Typically,
- * methods with names ending in ``!'' modify their receiver, while those
- * without a ``!'' return a new <code>String</code>. However, there are
- * exceptions, such as <code>String#[]=</code>.
- *
- */
-
-void
-Init_String()
-{
- rb_cString = rb_define_class("String", rb_cObject);
- rb_include_module(rb_cString, rb_mComparable);
- rb_include_module(rb_cString, rb_mEnumerable);
- rb_define_alloc_func(rb_cString, str_alloc);
- rb_define_method(rb_cString, "initialize", rb_str_init, -1);
- rb_define_method(rb_cString, "initialize_copy", rb_str_replace, 1);
- rb_define_method(rb_cString, "<=>", rb_str_cmp_m, 1);
- rb_define_method(rb_cString, "==", rb_str_equal, 1);
- rb_define_method(rb_cString, "eql?", rb_str_eql, 1);
- rb_define_method(rb_cString, "hash", rb_str_hash_m, 0);
- rb_define_method(rb_cString, "casecmp", rb_str_casecmp, 1);
- rb_define_method(rb_cString, "+", rb_str_plus, 1);
- rb_define_method(rb_cString, "*", rb_str_times, 1);
- rb_define_method(rb_cString, "%", rb_str_format, 1);
- rb_define_method(rb_cString, "[]", rb_str_aref_m, -1);
- rb_define_method(rb_cString, "[]=", rb_str_aset_m, -1);
- rb_define_method(rb_cString, "insert", rb_str_insert, 2);
- rb_define_method(rb_cString, "length", rb_str_length, 0);
- rb_define_method(rb_cString, "size", rb_str_length, 0);
- rb_define_method(rb_cString, "empty?", rb_str_empty, 0);
- rb_define_method(rb_cString, "=~", rb_str_match, 1);
- rb_define_method(rb_cString, "match", rb_str_match_m, -1);
- rb_define_method(rb_cString, "succ", rb_str_succ, 0);
- rb_define_method(rb_cString, "succ!", rb_str_succ_bang, 0);
- rb_define_method(rb_cString, "next", rb_str_succ, 0);
- rb_define_method(rb_cString, "next!", rb_str_succ_bang, 0);
- rb_define_method(rb_cString, "upto", rb_str_upto_m, 1);
- rb_define_method(rb_cString, "index", rb_str_index_m, -1);
- rb_define_method(rb_cString, "rindex", rb_str_rindex_m, -1);
- rb_define_method(rb_cString, "replace", rb_str_replace, 1);
- rb_define_method(rb_cString, "clear", rb_str_clear, 0);
-
- rb_define_method(rb_cString, "to_i", rb_str_to_i, -1);
- rb_define_method(rb_cString, "to_f", rb_str_to_f, 0);
- rb_define_method(rb_cString, "to_s", rb_str_to_s, 0);
- rb_define_method(rb_cString, "to_str", rb_str_to_s, 0);
- rb_define_method(rb_cString, "inspect", rb_str_inspect, 0);
- rb_define_method(rb_cString, "dump", rb_str_dump, 0);
-
- rb_define_method(rb_cString, "upcase", rb_str_upcase, 0);
- rb_define_method(rb_cString, "downcase", rb_str_downcase, 0);
- rb_define_method(rb_cString, "capitalize", rb_str_capitalize, 0);
- rb_define_method(rb_cString, "swapcase", rb_str_swapcase, 0);
-
- rb_define_method(rb_cString, "upcase!", rb_str_upcase_bang, 0);
- rb_define_method(rb_cString, "downcase!", rb_str_downcase_bang, 0);
- rb_define_method(rb_cString, "capitalize!", rb_str_capitalize_bang, 0);
- rb_define_method(rb_cString, "swapcase!", rb_str_swapcase_bang, 0);
-
- rb_define_method(rb_cString, "hex", rb_str_hex, 0);
- rb_define_method(rb_cString, "oct", rb_str_oct, 0);
- rb_define_method(rb_cString, "split", rb_str_split_m, -1);
- rb_define_method(rb_cString, "reverse", rb_str_reverse, 0);
- rb_define_method(rb_cString, "reverse!", rb_str_reverse_bang, 0);
- rb_define_method(rb_cString, "concat", rb_str_concat, 1);
- rb_define_method(rb_cString, "<<", rb_str_concat, 1);
- rb_define_method(rb_cString, "crypt", rb_str_crypt, 1);
- rb_define_method(rb_cString, "intern", rb_str_intern, 0);
- rb_define_method(rb_cString, "to_sym", rb_str_intern, 0);
-
- rb_define_method(rb_cString, "include?", rb_str_include, 1);
-
- rb_define_method(rb_cString, "scan", rb_str_scan, 1);
-
- rb_define_method(rb_cString, "ljust", rb_str_ljust, -1);
- rb_define_method(rb_cString, "rjust", rb_str_rjust, -1);
- rb_define_method(rb_cString, "center", rb_str_center, -1);
-
- rb_define_method(rb_cString, "sub", rb_str_sub, -1);
- rb_define_method(rb_cString, "gsub", rb_str_gsub, -1);
- rb_define_method(rb_cString, "chop", rb_str_chop, 0);
- rb_define_method(rb_cString, "chomp", rb_str_chomp, -1);
- rb_define_method(rb_cString, "strip", rb_str_strip, 0);
- rb_define_method(rb_cString, "lstrip", rb_str_lstrip, 0);
- rb_define_method(rb_cString, "rstrip", rb_str_rstrip, 0);
-
- rb_define_method(rb_cString, "sub!", rb_str_sub_bang, -1);
- rb_define_method(rb_cString, "gsub!", rb_str_gsub_bang, -1);
- rb_define_method(rb_cString, "chop!", rb_str_chop_bang, 0);
- rb_define_method(rb_cString, "chomp!", rb_str_chomp_bang, -1);
- rb_define_method(rb_cString, "strip!", rb_str_strip_bang, 0);
- rb_define_method(rb_cString, "lstrip!", rb_str_lstrip_bang, 0);
- rb_define_method(rb_cString, "rstrip!", rb_str_rstrip_bang, 0);
-
- rb_define_method(rb_cString, "tr", rb_str_tr, 2);
- rb_define_method(rb_cString, "tr_s", rb_str_tr_s, 2);
- rb_define_method(rb_cString, "delete", rb_str_delete, -1);
- rb_define_method(rb_cString, "squeeze", rb_str_squeeze, -1);
- rb_define_method(rb_cString, "count", rb_str_count, -1);
-
- rb_define_method(rb_cString, "tr!", rb_str_tr_bang, 2);
- rb_define_method(rb_cString, "tr_s!", rb_str_tr_s_bang, 2);
- rb_define_method(rb_cString, "delete!", rb_str_delete_bang, -1);
- rb_define_method(rb_cString, "squeeze!", rb_str_squeeze_bang, -1);
-
- rb_define_method(rb_cString, "each_line", rb_str_each_line, -1);
- rb_define_method(rb_cString, "each", rb_str_each_line, -1);
- rb_define_method(rb_cString, "each_byte", rb_str_each_byte, 0);
-
- rb_define_method(rb_cString, "sum", rb_str_sum, -1);
-
- rb_define_global_function("sub", rb_f_sub, -1);
- rb_define_global_function("gsub", rb_f_gsub, -1);
-
- rb_define_global_function("sub!", rb_f_sub_bang, -1);
- rb_define_global_function("gsub!", rb_f_gsub_bang, -1);
-
- rb_define_global_function("chop", rb_f_chop, 0);
- rb_define_global_function("chop!", rb_f_chop_bang, 0);
-
- rb_define_global_function("chomp", rb_f_chomp, -1);
- rb_define_global_function("chomp!", rb_f_chomp_bang, -1);
-
- rb_define_global_function("split", rb_f_split, -1);
- rb_define_global_function("scan", rb_f_scan, 1);
-
- rb_define_method(rb_cString, "slice", rb_str_aref_m, -1);
- rb_define_method(rb_cString, "slice!", rb_str_slice_bang, -1);
-
- id_to_s = rb_intern("to_s");
-
- rb_fs = Qnil;
- rb_define_variable("$;", &rb_fs);
- rb_define_variable("$-F", &rb_fs);
-}
-/**********************************************************************
-
- struct.c -
-
- $Author: matz $
- $Date: 2005/04/18 06:38:30 $
- created at: Tue Mar 22 18:44:30 JST 1995
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-
-VALUE rb_cStruct;
-
-static VALUE struct_alloc _((VALUE));
-
-VALUE
-rb_struct_iv_get(c, name)
- VALUE c;
- char *name;
-{
- ID id;
-
- id = rb_intern(name);
- for (;;) {
- if (rb_ivar_defined(c, id))
- return rb_ivar_get(c, id);
- c = RCLASS(c)->super;
- if (c == 0 || c == rb_cStruct)
- return Qnil;
- }
-}
-
-VALUE
-rb_struct_s_members(klass)
- VALUE klass;
-{
- VALUE members = rb_struct_iv_get(klass, "__members__");
-
- if (NIL_P(members)) {
- rb_bug("non-initialized struct");
- }
- return members;
-}
-
-VALUE
-rb_struct_members(s)
- VALUE s;
-{
- VALUE members = rb_struct_s_members(rb_obj_class(s));
-
- if (RSTRUCT(s)->len != RARRAY(members)->len) {
- rb_raise(rb_eTypeError, "struct size differs (%d required %d given)",
- RARRAY(members)->len, RSTRUCT(s)->len);
- }
- return members;
-}
-
-static VALUE
-rb_struct_s_members_m(klass)
- VALUE klass;
-{
- VALUE members, ary;
- VALUE *p, *pend;
-
- members = rb_struct_s_members(klass);
- ary = rb_ary_new2(RARRAY(members)->len);
- p = RARRAY(members)->ptr; pend = p + RARRAY(members)->len;
- while (p < pend) {
- rb_ary_push(ary, rb_str_new2(rb_id2name(SYM2ID(*p))));
- p++;
- }
-
- return ary;
-}
-
-/*
- * call-seq:
- * struct.members => array
- *
- * Returns an array of strings representing the names of the instance
- * variables.
- *
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joe.members #=> ["name", "address", "zip"]
- */
-
-static VALUE
-rb_struct_members_m(obj)
- VALUE obj;
-{
- return rb_struct_s_members_m(rb_obj_class(obj));
-}
-
-VALUE
-rb_struct_getmember(obj, id)
- VALUE obj;
- ID id;
-{
- VALUE members, slot;
- long i;
-
- members = rb_struct_members(obj);
- slot = ID2SYM(id);
- for (i=0; i<RARRAY(members)->len; i++) {
- if (RARRAY(members)->ptr[i] == slot) {
- return RSTRUCT(obj)->ptr[i];
- }
- }
- rb_name_error(id, "%s is not struct member", rb_id2name(id));
- return Qnil; /* not reached */
-}
-
-static VALUE
-rb_struct_ref(obj)
- VALUE obj;
-{
- return rb_struct_getmember(obj, rb_frame_this_func());
-}
-
-static VALUE rb_struct_ref0(obj) VALUE obj; {return RSTRUCT(obj)->ptr[0];}
-static VALUE rb_struct_ref1(obj) VALUE obj; {return RSTRUCT(obj)->ptr[1];}
-static VALUE rb_struct_ref2(obj) VALUE obj; {return RSTRUCT(obj)->ptr[2];}
-static VALUE rb_struct_ref3(obj) VALUE obj; {return RSTRUCT(obj)->ptr[3];}
-static VALUE rb_struct_ref4(obj) VALUE obj; {return RSTRUCT(obj)->ptr[4];}
-static VALUE rb_struct_ref5(obj) VALUE obj; {return RSTRUCT(obj)->ptr[5];}
-static VALUE rb_struct_ref6(obj) VALUE obj; {return RSTRUCT(obj)->ptr[6];}
-static VALUE rb_struct_ref7(obj) VALUE obj; {return RSTRUCT(obj)->ptr[7];}
-static VALUE rb_struct_ref8(obj) VALUE obj; {return RSTRUCT(obj)->ptr[8];}
-static VALUE rb_struct_ref9(obj) VALUE obj; {return RSTRUCT(obj)->ptr[9];}
-
-static VALUE (*ref_func[10])() = {
- rb_struct_ref0,
- rb_struct_ref1,
- rb_struct_ref2,
- rb_struct_ref3,
- rb_struct_ref4,
- rb_struct_ref5,
- rb_struct_ref6,
- rb_struct_ref7,
- rb_struct_ref8,
- rb_struct_ref9,
-};
-
-static void
-rb_struct_modify(s)
- VALUE s;
-{
- if (OBJ_FROZEN(s)) rb_error_frozen("Struct");
- if (!OBJ_TAINTED(s) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't modify Struct");
-}
-
-static VALUE
-rb_struct_set(obj, val)
- VALUE obj, val;
-{
- VALUE members, slot;
- long i;
-
- members = rb_struct_members(obj);
- rb_struct_modify(obj);
- for (i=0; i<RARRAY(members)->len; i++) {
- slot = RARRAY(members)->ptr[i];
- if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) {
- return RSTRUCT(obj)->ptr[i] = val;
- }
- }
- rb_name_error(rb_frame_this_func(), "`%s' is not a struct member",
- rb_id2name(rb_frame_this_func()));
- return Qnil; /* not reached */
-}
-
-static VALUE
-make_struct(name, members, klass)
- VALUE name, members, klass;
-{
- VALUE nstr;
- ID id;
- long i;
-
- OBJ_FREEZE(members);
- if (NIL_P(name)) {
- nstr = rb_class_new(klass);
- rb_make_metaclass(nstr, RBASIC(klass)->klass);
- rb_class_inherited(klass, nstr);
- }
- else {
- char *cname = StringValuePtr(name);
-
- id = rb_intern(cname);
- if (!rb_is_const_id(id)) {
- rb_name_error(id, "identifier %s needs to be constant", cname);
- }
- if (rb_const_defined_at(klass, id)) {
- rb_warn("redefining constant Struct::%s", cname);
- rb_mod_remove_const(klass, ID2SYM(id));
- }
- nstr = rb_define_class_under(klass, rb_id2name(id), klass);
- }
- rb_iv_set(nstr, "__size__", LONG2NUM(RARRAY(members)->len));
- rb_iv_set(nstr, "__members__", members);
-
- rb_define_alloc_func(nstr, struct_alloc);
- rb_define_singleton_method(nstr, "new", rb_class_new_instance, -1);
- rb_define_singleton_method(nstr, "[]", rb_class_new_instance, -1);
- rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0);
- for (i=0; i< RARRAY(members)->len; i++) {
- ID id = SYM2ID(RARRAY(members)->ptr[i]);
- if (rb_is_local_id(id) || rb_is_const_id(id)) {
- if (i<sizeof(ref_func)) {
- rb_define_method_id(nstr, id, ref_func[i], 0);
- }
- else {
- rb_define_method_id(nstr, id, rb_struct_ref, 0);
- }
- rb_define_method_id(nstr, rb_id_attrset(id), rb_struct_set, 1);
- }
- }
-
- return nstr;
-}
-
-#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
-
-VALUE
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_struct_define(const char *name, ...)
-#else
-rb_struct_define(name, va_alist)
- const char *name;
- va_dcl
-#endif
-{
- va_list ar;
- VALUE nm, ary;
- char *mem;
-
- if (!name) nm = Qnil;
- else nm = rb_str_new2(name);
- ary = rb_ary_new();
-
- va_init_list(ar, name);
- while (mem = va_arg(ar, char*)) {
- ID slot = rb_intern(mem);
- rb_ary_push(ary, ID2SYM(slot));
- }
- va_end(ar);
-
- return make_struct(nm, ary, rb_cStruct);
-}
-
-/*
- * call-seq:
- * Struct.new( [aString] [, aSym]+> ) => StructClass
- * StructClass.new(arg, ...) => obj
- * StructClass[arg, ...] => obj
- *
- * Creates a new class, named by <i>aString</i>, containing accessor
- * methods for the given symbols. If the name <i>aString</i> is
- * omitted, an anonymous structure class will be created. Otherwise,
- * the name of this struct will appear as a constant in class
- * <code>Struct</code>, so it must be unique for all
- * <code>Struct</code>s in the system and should start with a capital
- * letter. Assigning a structure class to a constant effectively gives
- * the class the name of the constant.
- *
- * <code>Struct::new</code> returns a new <code>Class</code> object,
- * which can then be used to create specific instances of the new
- * structure. The number of actual parameters must be
- * less than or equal to the number of attributes defined for this
- * class; unset parameters default to \nil{}. Passing too many
- * parameters will raise an \E{ArgumentError}.
- *
- * The remaining methods listed in this section (class and instance)
- * are defined for this generated class.
- *
- * # Create a structure with a name in Struct
- * Struct.new("Customer", :name, :address) #=> Struct::Customer
- * Struct::Customer.new("Dave", "123 Main") #=> #<Struct::Customer name="Dave", address="123 Main">
- *
- * # Create a structure named by its constant
- * Customer = Struct.new(:name, :address) #=> Customer
- * Customer.new("Dave", "123 Main") #=> #<Customer name="Dave", address="123 Main">
- */
-
-static VALUE
-rb_struct_s_def(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE name, rest;
- long i;
- VALUE st;
- ID id;
-
- rb_scan_args(argc, argv, "1*", &name, &rest);
- for (i=0; i<RARRAY(rest)->len; i++) {
- id = rb_to_id(RARRAY(rest)->ptr[i]);
- RARRAY(rest)->ptr[i] = ID2SYM(id);
- }
- if (!NIL_P(name)) {
- VALUE tmp = rb_check_string_type(name);
-
- if (NIL_P(tmp)) {
- id = rb_to_id(name);
- rb_ary_unshift(rest, ID2SYM(id));
- name = Qnil;
- }
- }
- st = make_struct(name, rest, klass);
- if (rb_block_given_p()) {
- rb_mod_module_eval(0, 0, st);
- }
-
- return st;
-}
-
-/*
- */
-
-static VALUE
-rb_struct_initialize(self, values)
- VALUE self, values;
-{
- VALUE klass = rb_obj_class(self);
- VALUE size;
- long n;
-
- rb_struct_modify(self);
- size = rb_struct_iv_get(klass, "__size__");
- n = FIX2LONG(size);
- if (n < RARRAY(values)->len) {
- rb_raise(rb_eArgError, "struct size differs");
- }
- MEMCPY(RSTRUCT(self)->ptr, RARRAY(values)->ptr, VALUE, RARRAY(values)->len);
- if (n > RARRAY(values)->len) {
- rb_mem_clear(RSTRUCT(self)->ptr+RARRAY(values)->len,
- n-RARRAY(values)->len);
- }
- return Qnil;
-}
-
-static VALUE
-struct_alloc(klass)
- VALUE klass;
-{
- VALUE size;
- long n;
- NEWOBJ(st, struct RStruct);
- OBJSETUP(st, klass, T_STRUCT);
-
- size = rb_struct_iv_get(klass, "__size__");
- n = FIX2LONG(size);
-
- st->ptr = ALLOC_N(VALUE, n);
- rb_mem_clear(st->ptr, n);
- st->len = n;
-
- return (VALUE)st;
-}
-
-VALUE
-rb_struct_alloc(klass, values)
- VALUE klass, values;
-{
- return rb_class_new_instance(RARRAY(values)->len, RARRAY(values)->ptr, klass);
-}
-
-VALUE
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_struct_new(VALUE klass, ...)
-#else
-rb_struct_new(klass, va_alist)
- VALUE klass;
- va_dcl
-#endif
-{
- VALUE sz, *mem;
- long size, i;
- va_list args;
-
- sz = rb_struct_iv_get(klass, "__size__");
- size = FIX2LONG(sz);
- mem = ALLOCA_N(VALUE, size);
- va_init_list(args, klass);
- for (i=0; i<size; i++) {
- mem[i] = va_arg(args, VALUE);
- }
- va_end(args);
-
- return rb_class_new_instance(size, mem, klass);
-}
-
-/*
- * call-seq:
- * struct.each {|obj| block } => struct
- *
- * Calls <i>block</i> once for each instance variable, passing the
- * value as a parameter.
- *
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joe.each {|x| puts(x) }
- *
- * <em>produces:</em>
- *
- * Joe Smith
- * 123 Maple, Anytown NC
- * 12345
- */
-
-static VALUE
-rb_struct_each(s)
- VALUE s;
-{
- long i;
-
- for (i=0; i<RSTRUCT(s)->len; i++) {
- rb_yield(RSTRUCT(s)->ptr[i]);
- }
- return s;
-}
-
-/*
- * call-seq:
- * struct.each_pair {|sym, obj| block } => struct
- *
- * Calls <i>block</i> once for each instance variable, passing the name
- * (as a symbol) and the value as parameters.
- *
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joe.each_pair {|name, value| puts("#{name} => #{value}") }
- *
- * <em>produces:</em>
- *
- * name => Joe Smith
- * address => 123 Maple, Anytown NC
- * zip => 12345
- */
-
-static VALUE
-rb_struct_each_pair(s)
- VALUE s;
-{
- VALUE members;
- long i;
-
- members = rb_struct_members(s);
- for (i=0; i<RSTRUCT(s)->len; i++) {
- rb_yield_values(2, rb_ary_entry(members, i), RSTRUCT(s)->ptr[i]);
- }
- return s;
-}
-
-static VALUE
-inspect_struct(s, dummy, recur)
- VALUE s, dummy;
- int recur;
-{
- char *cname = rb_class2name(rb_obj_class(s));
- VALUE str, members;
- long i;
-
- if (recur) {
- char *cname = rb_class2name(rb_obj_class(s));
- VALUE str = rb_str_new(0, strlen(cname) + 15);
-
- sprintf(RSTRING(str)->ptr, "#<struct %s:...>", cname);
- RSTRING(str)->len = strlen(RSTRING(str)->ptr);
- return str;
- }
-
- members = rb_struct_members(s);
- str = rb_str_buf_new2("#<struct ");
- rb_str_cat2(str, cname);
- rb_str_cat2(str, " ");
- for (i=0; i<RSTRUCT(s)->len; i++) {
- VALUE slot;
- ID id;
- char *p;
-
- if (i > 0) {
- rb_str_cat2(str, ", ");
- }
- slot = RARRAY(members)->ptr[i];
- id = SYM2ID(slot);
- if (rb_is_local_id(id) || rb_is_const_id(id)) {
- p = rb_id2name(id);
- rb_str_cat2(str, p);
- }
- else {
- rb_str_append(str, rb_inspect(slot));
- }
- rb_str_cat2(str, "=");
- rb_str_append(str, rb_inspect(RSTRUCT(s)->ptr[i]));
- }
- rb_str_cat2(str, ">");
- OBJ_INFECT(str, s);
-
- return str;
-}
-
-/*
- * call-seq:
- * struct.to_s => string
- * struct.inspect => string
- *
- * Describe the contents of this struct in a string.
- */
-
-static VALUE
-rb_struct_inspect(s)
- VALUE s;
-{
- return rb_exec_recursive(inspect_struct, s, 0);
-}
-
-/*
- * call-seq:
- * struct.to_a => array
- * struct.values => array
- *
- * Returns the values for this instance as an array.
- *
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joe.to_a[1] #=> "123 Maple, Anytown NC"
- */
-
-static VALUE
-rb_struct_to_a(s)
- VALUE s;
-{
- return rb_ary_new4(RSTRUCT(s)->len, RSTRUCT(s)->ptr);
-}
-
-/* :nodoc: */
-static VALUE
-rb_struct_init_copy(copy, s)
- VALUE copy, s;
-{
- if (copy == s) return copy;
- rb_check_frozen(copy);
- if (!rb_obj_is_instance_of(s, rb_obj_class(copy))) {
- rb_raise(rb_eTypeError, "wrong argument class");
- }
- RSTRUCT(copy)->ptr = ALLOC_N(VALUE, RSTRUCT(s)->len);
- RSTRUCT(copy)->len = RSTRUCT(s)->len;
- MEMCPY(RSTRUCT(copy)->ptr, RSTRUCT(s)->ptr, VALUE, RSTRUCT(copy)->len);
-
- return copy;
-}
-
-static VALUE
-rb_struct_aref_id(s, id)
- VALUE s;
- ID id;
-{
- VALUE members;
- long i, len;
-
- members = rb_struct_members(s);
- len = RARRAY(members)->len;
- for (i=0; i<len; i++) {
- if (SYM2ID(RARRAY(members)->ptr[i]) == id) {
- return RSTRUCT(s)->ptr[i];
- }
- }
- rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
- return Qnil; /* not reached */
-}
-
-/*
- * call-seq:
- * struct[symbol] => anObject
- * struct[fixnum] => anObject
- *
- * Attribute Reference---Returns the value of the instance variable
- * named by <i>symbol</i>, or indexed (0..length-1) by
- * <i>fixnum</i>. Will raise <code>NameError</code> if the named
- * variable does not exist, or <code>IndexError</code> if the index is
- * out of range.
- *
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- *
- * joe["name"] #=> "Joe Smith"
- * joe[:name] #=> "Joe Smith"
- * joe[0] #=> "Joe Smith"
- */
-
-VALUE
-rb_struct_aref(s, idx)
- VALUE s, idx;
-{
- long i;
-
- if (TYPE(idx) == T_STRING || TYPE(idx) == T_SYMBOL) {
- return rb_struct_aref_id(s, rb_to_id(idx));
- }
-
- i = NUM2LONG(idx);
- if (i < 0) i = RSTRUCT(s)->len + i;
- if (i < 0)
- rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
- i, RSTRUCT(s)->len);
- if (RSTRUCT(s)->len <= i)
- rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
- i, RSTRUCT(s)->len);
- return RSTRUCT(s)->ptr[i];
-}
-
-static VALUE
-rb_struct_aset_id(s, id, val)
- VALUE s, val;
- ID id;
-{
- VALUE members;
- long i, len;
-
- members = rb_struct_members(s);
- rb_struct_modify(s);
- len = RARRAY(members)->len;
- if (RSTRUCT(s)->len != RARRAY(members)->len) {
- rb_raise(rb_eTypeError, "struct size differs (%d required %d given)",
- RARRAY(members)->len, RSTRUCT(s)->len);
- }
- for (i=0; i<len; i++) {
- if (SYM2ID(RARRAY(members)->ptr[i]) == id) {
- RSTRUCT(s)->ptr[i] = val;
- return val;
- }
- }
- rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
-}
-
-/*
- * call-seq:
- * struct[symbol] = obj => obj
- * struct[fixnum] = obj => obj
- *
- * Attribute Assignment---Assigns to the instance variable named by
- * <i>symbol</i> or <i>fixnum</i> the value <i>obj</i> and
- * returns it. Will raise a <code>NameError</code> if the named
- * variable does not exist, or an <code>IndexError</code> if the index
- * is out of range.
- *
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- *
- * joe["name"] = "Luke"
- * joe[:zip] = "90210"
- *
- * joe.name #=> "Luke"
- * joe.zip #=> "90210"
- */
-
-VALUE
-rb_struct_aset(s, idx, val)
- VALUE s, idx, val;
-{
- long i;
-
- if (TYPE(idx) == T_STRING || TYPE(idx) == T_SYMBOL) {
- return rb_struct_aset_id(s, rb_to_id(idx), val);
- }
-
- i = NUM2LONG(idx);
- if (i < 0) i = RSTRUCT(s)->len + i;
- if (i < 0) {
- rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
- i, RSTRUCT(s)->len);
- }
- if (RSTRUCT(s)->len <= i) {
- rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
- i, RSTRUCT(s)->len);
- }
- rb_struct_modify(s);
- return RSTRUCT(s)->ptr[i] = val;
-}
-
-static VALUE struct_entry _((VALUE, long));
-static VALUE
-struct_entry(s, n)
- VALUE s;
- long n;
-{
- return rb_struct_aref(s, LONG2NUM(n));
-}
-
-/*
- * call-seq:
- * struct.values_at(selector,... ) => an_array
- *
- * Returns an array containing the elements in
- * _self_ corresponding to the given selector(s). The selectors
- * may be either integer indices or ranges.
- * See also </code>.select<code>.
- *
- * a = %w{ a b c d e f }
- * a.values_at(1, 3, 5)
- * a.values_at(1, 3, 5, 7)
- * a.values_at(-1, -3, -5, -7)
- * a.values_at(1..3, 2...5)
- */
-
-static VALUE
-rb_struct_values_at(argc, argv, s)
- int argc;
- VALUE *argv;
- VALUE s;
-{
- return rb_get_values_at(s, RSTRUCT(s)->len, argc, argv, struct_entry);
-}
-
-/*
- * call-seq:
- * struct.select(fixnum, ... ) => array
- * struct.select {|i| block } => array
- *
- * The first form returns an array containing the elements in
- * <i>struct</i> corresponding to the given indices. The second
- * form invokes the block passing in successive elements from
- * <i>struct</i>, returning an array containing those elements
- * for which the block returns a true value (equivalent to
- * <code>Enumerable#select</code>).
- *
- * Lots = Struct.new(:a, :b, :c, :d, :e, :f)
- * l = Lots.new(11, 22, 33, 44, 55, 66)
- * l.select(1, 3, 5) #=> [22, 44, 66]
- * l.select(0, 2, 4) #=> [11, 33, 55]
- * l.select(-1, -3, -5) #=> [66, 44, 22]
- * l.select {|v| (v % 2).zero? } #=> [22, 44, 66]
- */
-
-static VALUE
-rb_struct_select(argc, argv, s)
- int argc;
- VALUE *argv;
- VALUE s;
-{
- VALUE result;
- long i;
-
- if (argc > 0) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
- }
- result = rb_ary_new();
- for (i = 0; i < RSTRUCT(s)->len; i++) {
- if (RTEST(rb_yield(RSTRUCT(s)->ptr[i]))) {
- rb_ary_push(result, RSTRUCT(s)->ptr[i]);
- }
- }
-
- return result;
-}
-
-/*
- * call-seq:
- * struct == other_struct => true or false
- *
- * Equality---Returns <code>true</code> if <i>other_struct</i> is
- * equal to this one: they must be of the same class as generated by
- * <code>Struct::new</code>, and the values of all instance variables
- * must be equal (according to <code>Object#==</code>).
- *
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
- * joe == joejr #=> true
- * joe == jane #=> false
- */
-
-static VALUE
-rb_struct_equal(s, s2)
- VALUE s, s2;
-{
- long i;
-
- if (s == s2) return Qtrue;
- if (TYPE(s2) != T_STRUCT) return Qfalse;
- if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
- if (RSTRUCT(s)->len != RSTRUCT(s2)->len) {
- rb_bug("inconsistent struct"); /* should never happen */
- }
-
- for (i=0; i<RSTRUCT(s)->len; i++) {
- if (!rb_equal(RSTRUCT(s)->ptr[i], RSTRUCT(s2)->ptr[i])) return Qfalse;
- }
- return Qtrue;
-}
-
-/*
- * call-seq:
- * struct.hash => fixnum
- *
- * Return a hash value based on this struct's contents.
- */
-
-static VALUE
-rb_struct_hash(s)
- VALUE s;
-{
- long i, h;
- VALUE n;
-
- h = rb_hash(rb_obj_class(s));
- for (i = 0; i < RSTRUCT(s)->len; i++) {
- h = (h << 1) | (h<0 ? 1 : 0);
- n = rb_hash(RSTRUCT(s)->ptr[i]);
- h ^= NUM2LONG(n);
- }
- return LONG2FIX(h);
-}
-
-/*
- * code-seq:
- * struct.eql?(other) => true or false
- *
- * Two structures are equal if they are the same object, or if all their
- * fields are equal (using <code>eql?</code>).
- */
-
-static VALUE
-rb_struct_eql(s, s2)
- VALUE s, s2;
-{
- long i;
-
- if (s == s2) return Qtrue;
- if (TYPE(s2) != T_STRUCT) return Qfalse;
- if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
- if (RSTRUCT(s)->len != RSTRUCT(s2)->len) {
- rb_bug("inconsistent struct"); /* should never happen */
- }
-
- for (i=0; i<RSTRUCT(s)->len; i++) {
- if (!rb_eql(RSTRUCT(s)->ptr[i], RSTRUCT(s2)->ptr[i])) return Qfalse;
- }
- return Qtrue;
-}
-
-/*
- * call-seq:
- * struct.length => fixnum
- * struct.size => fixnum
- *
- * Returns the number of instance variables.
- *
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joe.length #=> 3
- */
-
-static VALUE
-rb_struct_size(s)
- VALUE s;
-{
- return LONG2FIX(RSTRUCT(s)->len);
-}
-
-/*
- * A <code>Struct</code> is a convenient way to bundle a number of
- * attributes together, using accessor methods, without having to write
- * an explicit class.
- *
- * The <code>Struct</code> class is a generator of specific classes,
- * each one of which is defined to hold a set of variables and their
- * accessors. In these examples, we'll call the generated class
- * ``<i>Customer</i>Class,'' and we'll show an example instance of that
- * class as ``<i>Customer</i>Inst.''
- *
- * In the descriptions that follow, the parameter <i>symbol</i> refers
- * to a symbol, which is either a quoted string or a
- * <code>Symbol</code> (such as <code>:name</code>).
- */
-void
-Init_Struct()
-{
- rb_cStruct = rb_define_class("Struct", rb_cObject);
- rb_include_module(rb_cStruct, rb_mEnumerable);
-
- rb_undef_alloc_func(rb_cStruct);
- rb_define_singleton_method(rb_cStruct, "new", rb_struct_s_def, -1);
-
- rb_define_method(rb_cStruct, "initialize", rb_struct_initialize, -2);
- rb_define_method(rb_cStruct, "initialize_copy", rb_struct_init_copy, 1);
-
- rb_define_method(rb_cStruct, "==", rb_struct_equal, 1);
- rb_define_method(rb_cStruct, "eql?", rb_struct_eql, 1);
- rb_define_method(rb_cStruct, "hash", rb_struct_hash, 0);
-
- rb_define_method(rb_cStruct, "to_s", rb_struct_inspect, 0);
- rb_define_method(rb_cStruct, "inspect", rb_struct_inspect, 0);
- rb_define_method(rb_cStruct, "to_a", rb_struct_to_a, 0);
- rb_define_method(rb_cStruct, "values", rb_struct_to_a, 0);
- rb_define_method(rb_cStruct, "size", rb_struct_size, 0);
- rb_define_method(rb_cStruct, "length", rb_struct_size, 0);
-
- rb_define_method(rb_cStruct, "each", rb_struct_each, 0);
- rb_define_method(rb_cStruct, "each_pair", rb_struct_each_pair, 0);
- rb_define_method(rb_cStruct, "[]", rb_struct_aref, 1);
- rb_define_method(rb_cStruct, "[]=", rb_struct_aset, 2);
- rb_define_method(rb_cStruct, "select", rb_struct_select, -1);
- rb_define_method(rb_cStruct, "values_at", rb_struct_values_at, -1);
-
- rb_define_method(rb_cStruct, "members", rb_struct_members_m, 0);
-}
-/**********************************************************************
-
- time.c -
-
- $Author: matz $
- $Date: 2005/03/04 06:47:41 $
- created at: Tue Dec 28 14:31:59 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include <sys/types.h>
-#include <time.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <math.h>
-
-VALUE rb_cTime;
-
-struct time_object {
- struct timeval tv;
- struct tm tm;
- int gmt;
- int tm_got;
-};
-
-#define GetTimeval(obj, tobj) \
- Data_Get_Struct(obj, struct time_object, tobj)
-
-static void time_free _((void *));
-
-static void
-time_free(tobj)
- void *tobj;
-{
- if (tobj) free(tobj);
-}
-
-static VALUE time_s_alloc _((VALUE));
-static VALUE
-time_s_alloc(klass)
- VALUE klass;
-{
- VALUE obj;
- struct time_object *tobj;
-
- obj = Data_Make_Struct(klass, struct time_object, 0, time_free, tobj);
- tobj->tm_got=0;
- tobj->tv.tv_sec = 0;
- tobj->tv.tv_usec = 0;
-
- return obj;
-}
-
-static void
-time_modify(time)
- VALUE time;
-{
- rb_check_frozen(time);
- if (!OBJ_TAINTED(time) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't modify Time");
-}
-
-/*
- * Document-method: now
- *
- * Synonym for <code>Time.new</code>. Returns a +Time+ object
- * initialized tot he current system time.
- */
-
-/*
- * call-seq:
- * Time.new -> time
- *
- * Returns a <code>Time</code> object initialized to the current system
- * time. <b>Note:</b> The object created will be created using the
- * resolution available on your system clock, and so may include
- * fractional seconds.
- *
- * a = Time.new #=> Wed Apr 09 08:56:03 CDT 2003
- * b = Time.new #=> Wed Apr 09 08:56:03 CDT 2003
- * a == b #=> false
- * "%.6f" % a.to_f #=> "1049896563.230740"
- * "%.6f" % b.to_f #=> "1049896563.231466"
- *
- */
-
-static VALUE
-time_init(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- time_modify(time);
- GetTimeval(time, tobj);
- tobj->tm_got=0;
- tobj->tv.tv_sec = 0;
- tobj->tv.tv_usec = 0;
- if (gettimeofday(&tobj->tv, 0) < 0) {
- rb_sys_fail("gettimeofday");
- }
-
- return time;
-}
-
-#define NDIV(x,y) (-(-((x)+1)/(y))-1)
-#define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
-
-void
-time_overflow_p(secp, usecp)
- time_t *secp, *usecp;
-{
- time_t tmp, sec = *secp, usec = *usecp;
-
- if (usec >= 1000000) { /* usec positive overflow */
- tmp = sec + usec / 1000000;
- usec %= 1000000;
- if (sec > 0 && tmp < 0) {
- rb_raise(rb_eRangeError, "out of Time range");
- }
- sec = tmp;
- }
- if (usec < 0) { /* usec negative overflow */
- tmp = sec + NDIV(usec,1000000); /* negative div */
- usec = NMOD(usec,1000000); /* negative mod */
- if (sec < 0 && tmp > 0) {
- rb_raise(rb_eRangeError, "out of Time range");
- }
- sec = tmp;
- }
-#ifndef NEGATIVE_TIME_T
- if (sec < 0 || (sec == 0 && usec < 0))
- rb_raise(rb_eArgError, "time must be positive");
-#endif
- *secp = sec;
- *usecp = usec;
-}
-
-static VALUE
-time_new_internal(klass, sec, usec)
- VALUE klass;
- time_t sec, usec;
-{
- VALUE time = time_s_alloc(klass);
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- time_overflow_p(&sec, &usec);
- tobj->tv.tv_sec = sec;
- tobj->tv.tv_usec = usec;
-
- return time;
-}
-
-VALUE
-rb_time_new(sec, usec)
- time_t sec, usec;
-{
- return time_new_internal(rb_cTime, sec, usec);
-}
-
-static struct timeval
-time_timeval(time, interval)
- VALUE time;
- int interval;
-{
- struct timeval t;
- char *tstr = interval ? "time interval" : "time";
-
-#ifndef NEGATIVE_TIME_T
- interval = 1;
-#endif
-
- switch (TYPE(time)) {
- case T_FIXNUM:
- t.tv_sec = FIX2LONG(time);
- if (interval && t.tv_sec < 0)
- rb_raise(rb_eArgError, "%s must be positive", tstr);
- t.tv_usec = 0;
- break;
-
- case T_FLOAT:
- if (interval && RFLOAT(time)->value < 0.0)
- rb_raise(rb_eArgError, "%s must be positive", tstr);
- else {
- double f, d;
-
- d = modf(RFLOAT(time)->value, &f);
- t.tv_sec = (time_t)f;
- if (f != t.tv_sec) {
- rb_raise(rb_eRangeError, "%f out of Time range", RFLOAT(time)->value);
- }
- t.tv_usec = (time_t)(d*1e6);
- }
- break;
-
- case T_BIGNUM:
- t.tv_sec = NUM2LONG(time);
- if (interval && t.tv_sec < 0)
- rb_raise(rb_eArgError, "%s must be positive", tstr);
- t.tv_usec = 0;
- break;
-
- default:
- rb_raise(rb_eTypeError, "can't convert %s into %s",
- rb_obj_classname(time), tstr);
- break;
- }
- return t;
-}
-
-struct timeval
-rb_time_interval(time)
- VALUE time;
-{
- return time_timeval(time, Qtrue);
-}
-
-struct timeval
-rb_time_timeval(time)
- VALUE time;
-{
- struct time_object *tobj;
- struct timeval t;
-
- if (TYPE(time) == T_DATA && RDATA(time)->dfree == time_free) {
- GetTimeval(time, tobj);
- t = tobj->tv;
- return t;
- }
- return time_timeval(time, Qfalse);
-}
-
-/*
- * call-seq:
- * Time.at( aTime ) => time
- * Time.at( seconds [, microseconds] ) => time
- *
- * Creates a new time object with the value given by <i>aTime</i>, or
- * the given number of <i>seconds</i> (and optional
- * <i>microseconds</i>) from epoch. A non-portable feature allows the
- * offset to be negative on some systems.
- *
- * Time.at(0) #=> Wed Dec 31 18:00:00 CST 1969
- * Time.at(946702800) #=> Fri Dec 31 23:00:00 CST 1999
- * Time.at(-284061600) #=> Sat Dec 31 00:00:00 CST 1960
- */
-
-static VALUE
-time_s_at(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- struct timeval tv;
- VALUE time, t;
-
- if (rb_scan_args(argc, argv, "11", &time, &t) == 2) {
- tv.tv_sec = NUM2LONG(time);
- tv.tv_usec = NUM2LONG(t);
- }
- else {
- tv = rb_time_timeval(time);
- }
- t = time_new_internal(klass, tv.tv_sec, tv.tv_usec);
- if (TYPE(time) == T_DATA && RDATA(time)->dfree == time_free) {
- struct time_object *tobj, *tobj2;
-
- GetTimeval(time, tobj);
- GetTimeval(t, tobj2);
- tobj2->gmt = tobj->gmt;
- }
- return t;
-}
-
-static char *months [12] = {
- "jan", "feb", "mar", "apr", "may", "jun",
- "jul", "aug", "sep", "oct", "nov", "dec",
-};
-
-static long
-obj2long(obj)
- VALUE obj;
-{
- if (TYPE(obj) == T_STRING) {
- obj = rb_str_to_inum(obj, 10, Qfalse);
- }
-
- return NUM2LONG(obj);
-}
-
-static void
-time_arg(argc, argv, tm, usec)
- int argc;
- VALUE *argv;
- struct tm *tm;
- time_t *usec;
-{
- VALUE v[8];
- int i;
- long year;
-
- MEMZERO(tm, struct tm, 1);
- *usec = 0;
- if (argc == 10) {
- v[0] = argv[5];
- v[1] = argv[4];
- v[2] = argv[3];
- v[3] = argv[2];
- v[4] = argv[1];
- v[5] = argv[0];
- v[6] = Qnil;
- tm->tm_isdst = RTEST(argv[8]) ? 1 : 0;
- }
- else {
- rb_scan_args(argc, argv, "17", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6],&v[7]);
- /* v[6] may be usec or zone (parsedate) */
- /* v[7] is wday (parsedate; ignored) */
- tm->tm_wday = -1;
- tm->tm_isdst = -1;
- }
-
- year = obj2long(v[0]);
-
- if (0 <= year && year < 39) {
- year += 100;
- rb_warning("2 digits year is used");
- }
- else if (69 <= year && year < 139) {
- rb_warning("2 or 3 digits year is used");
- }
- else {
- year -= 1900;
- }
-
- tm->tm_year = year;
-
- if (NIL_P(v[1])) {
- tm->tm_mon = 0;
- }
- else {
- VALUE s = rb_check_string_type(v[1]);
- if (!NIL_P(s)) {
- tm->tm_mon = -1;
- for (i=0; i<12; i++) {
- if (RSTRING(s)->len == 3 &&
- strcasecmp(months[i], RSTRING(v[1])->ptr) == 0) {
- tm->tm_mon = i;
- break;
- }
- }
- if (tm->tm_mon == -1) {
- char c = RSTRING(s)->ptr[0];
-
- if ('0' <= c && c <= '9') {
- tm->tm_mon = obj2long(s)-1;
- }
- }
- }
- else {
- tm->tm_mon = obj2long(v[1])-1;
- }
- }
- if (NIL_P(v[2])) {
- tm->tm_mday = 1;
- }
- else {
- tm->tm_mday = obj2long(v[2]);
- }
- tm->tm_hour = NIL_P(v[3])?0:obj2long(v[3]);
- tm->tm_min = NIL_P(v[4])?0:obj2long(v[4]);
- tm->tm_sec = NIL_P(v[5])?0:obj2long(v[5]);
- if (!NIL_P(v[6])) {
- /* when argc == 8, v[6] is timezone, but ignored */
- if (argc == 7) {
- *usec = obj2long(v[6]);
- }
- }
-
- /* value validation */
- if (
- tm->tm_year != year ||
-#ifndef NEGATIVE_TIME_T
- tm->tm_year < 69 ||
-#endif
- tm->tm_mon < 0 || tm->tm_mon > 11
- || tm->tm_mday < 1 || tm->tm_mday > 31
- || tm->tm_hour < 0 || tm->tm_hour > 23
- || tm->tm_min < 0 || tm->tm_min > 59
- || tm->tm_sec < 0 || tm->tm_sec > 60)
- rb_raise(rb_eArgError, "argument out of range");
-}
-
-static VALUE time_gmtime _((VALUE));
-static VALUE time_localtime _((VALUE));
-static VALUE time_get_tm _((VALUE, int));
-
-static int
-leap_year_p(y)
- long y;
-{
- return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0);
-}
-
-#define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
-
-static time_t
-timegm_noleapsecond(tm)
- struct tm *tm;
-{
- static int common_year_yday_offset[] = {
- -1,
- -1 + 31,
- -1 + 31 + 28,
- -1 + 31 + 28 + 31,
- -1 + 31 + 28 + 31 + 30,
- -1 + 31 + 28 + 31 + 30 + 31,
- -1 + 31 + 28 + 31 + 30 + 31 + 30,
- -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31,
- -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
- -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
- -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
- -1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
- /* 1 2 3 4 5 6 7 8 9 10 11 */
- };
- static int leap_year_yday_offset[] = {
- -1,
- -1 + 31,
- -1 + 31 + 29,
- -1 + 31 + 29 + 31,
- -1 + 31 + 29 + 31 + 30,
- -1 + 31 + 29 + 31 + 30 + 31,
- -1 + 31 + 29 + 31 + 30 + 31 + 30,
- -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31,
- -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
- -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
- -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
- -1 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
- /* 1 2 3 4 5 6 7 8 9 10 11 */
- };
-
- long tm_year = tm->tm_year;
- int tm_yday = tm->tm_mday;
- if (leap_year_p(tm_year + 1900))
- tm_yday += leap_year_yday_offset[tm->tm_mon];
- else
- tm_yday += common_year_yday_offset[tm->tm_mon];
-
- /*
- * `Seconds Since the Epoch' in SUSv3:
- * tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
- * (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
- * ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400
- */
- return tm->tm_sec + tm->tm_min*60 + tm->tm_hour*3600 +
- (time_t)(tm_yday +
- (tm_year-70)*365 +
- DIV(tm_year-69,4) -
- DIV(tm_year-1,100) +
- DIV(tm_year+299,400))*86400;
-}
-
-static int
-tmcmp(a, b)
- struct tm *a;
- struct tm *b;
-{
- if (a->tm_year != b->tm_year)
- return a->tm_year < b->tm_year ? -1 : 1;
- else if (a->tm_mon != b->tm_mon)
- return a->tm_mon < b->tm_mon ? -1 : 1;
- else if (a->tm_mday != b->tm_mday)
- return a->tm_mday < b->tm_mday ? -1 : 1;
- else if (a->tm_hour != b->tm_hour)
- return a->tm_hour < b->tm_hour ? -1 : 1;
- else if (a->tm_min != b->tm_min)
- return a->tm_min < b->tm_min ? -1 : 1;
- else if (a->tm_sec != b->tm_sec)
- return a->tm_sec < b->tm_sec ? -1 : 1;
- else
- return 0;
-}
-
-static time_t
-search_time_t(tptr, utc_p)
- struct tm *tptr;
- int utc_p;
-{
- time_t guess, guess_lo, guess_hi;
- struct tm *tm, tm_lo, tm_hi;
- int d, have_guess;
- int find_dst;
-
- find_dst = 0 < tptr->tm_isdst;
-
-#ifdef NEGATIVE_TIME_T
- guess_lo = 1L << (8 * sizeof(time_t) - 1);
-#else
- guess_lo = 0;
-#endif
- guess_hi = ((time_t)-1) < ((time_t)0) ?
- (1UL << (8 * sizeof(time_t) - 1)) - 1 :
- ~(time_t)0;
-
- guess = timegm_noleapsecond(tptr);
- tm = (utc_p ? gmtime : localtime)(&guess);
- if (tm) {
- d = tmcmp(tptr, tm);
- if (d == 0) return guess;
- if (d < 0) {
- guess_hi = guess;
- guess -= 24 * 60 * 60;
- }
- else {
- guess_lo = guess;
- guess += 24 * 60 * 60;
- }
- if (guess_lo < guess && guess < guess_hi &&
- (tm = (utc_p ? gmtime : localtime)(&guess)) != NULL) {
- d = tmcmp(tptr, tm);
- if (d == 0) return guess;
- if (d < 0)
- guess_hi = guess;
- else
- guess_lo = guess;
- }
- }
-
- tm = (utc_p ? gmtime : localtime)(&guess_lo);
- if (!tm) goto error;
- d = tmcmp(tptr, tm);
- if (d < 0) goto out_of_range;
- if (d == 0) return guess_lo;
- tm_lo = *tm;
-
- tm = (utc_p ? gmtime : localtime)(&guess_hi);
- if (!tm) goto error;
- d = tmcmp(tptr, tm);
- if (d > 0) goto out_of_range;
- if (d == 0) return guess_hi;
- tm_hi = *tm;
-
- have_guess = 0;
-
- while (guess_lo + 1 < guess_hi) {
- /* there is a gap between guess_lo and guess_hi. */
- unsigned long range = 0;
- if (!have_guess) {
- int a, b;
- /*
- Try precious guess by a linear interpolation at first.
- `a' and `b' is a coefficient of guess_lo and guess_hi as:
-
- guess = (guess_lo * a + guess_hi * b) / (a + b)
-
- However this causes overflow in most cases, following assignment
- is used instead:
-
- guess = guess_lo / d * a + (guess_lo % d) * a / d
- + guess_hi / d * b + (guess_hi % d) * b / d
- where d = a + b
-
- To avoid overflow in this assignment, `d' is restricted to less than
- sqrt(2**31). By this restriction and other reasons, the guess is
- not accurate and some error is expected. `range' approximates
- the maximum error.
-
- When these parameters are not suitable, i.e. guess is not within
- guess_lo and guess_hi, simple guess by binary search is used.
- */
- range = 366 * 24 * 60 * 60;
- a = (tm_hi.tm_year - tptr->tm_year);
- b = (tptr->tm_year - tm_lo.tm_year);
- /* 46000 is selected as `some big number less than sqrt(2**31)'. */
- if (a + b <= 46000 / 12) {
- range = 31 * 24 * 60 * 60;
- a *= 12;
- b *= 12;
- a += tm_hi.tm_mon - tptr->tm_mon;
- b += tptr->tm_mon - tm_lo.tm_mon;
- if (a + b <= 46000 / 31) {
- range = 24 * 60 * 60;
- a *= 31;
- b *= 31;
- a += tm_hi.tm_mday - tptr->tm_mday;
- b += tptr->tm_mday - tm_lo.tm_mday;
- if (a + b <= 46000 / 24) {
- range = 60 * 60;
- a *= 24;
- b *= 24;
- a += tm_hi.tm_hour - tptr->tm_hour;
- b += tptr->tm_hour - tm_lo.tm_hour;
- if (a + b <= 46000 / 60) {
- range = 60;
- a *= 60;
- b *= 60;
- a += tm_hi.tm_min - tptr->tm_min;
- b += tptr->tm_min - tm_lo.tm_min;
- if (a + b <= 46000 / 60) {
- range = 1;
- a *= 60;
- b *= 60;
- a += tm_hi.tm_sec - tptr->tm_sec;
- b += tptr->tm_sec - tm_lo.tm_sec;
- }
- }
- }
- }
- }
- if (a <= 0) a = 1;
- if (b <= 0) b = 1;
- d = a + b;
- /*
- Although `/' and `%' may produce unexpected result with negative
- argument, it doesn't cause serious problem because there is a
- fail safe.
- */
- guess = guess_lo / d * a + (guess_lo % d) * a / d
- + guess_hi / d * b + (guess_hi % d) * b / d;
- have_guess = 1;
- }
-
- if (guess <= guess_lo || guess_hi <= guess) {
- /* Precious guess is invalid. try binary search. */
- guess = guess_lo / 2 + guess_hi / 2;
- if (guess <= guess_lo)
- guess = guess_lo + 1;
- else if (guess >= guess_hi)
- guess = guess_hi - 1;
- range = 0;
- }
-
- tm = (utc_p ? gmtime : localtime)(&guess);
- if (!tm) goto error;
- have_guess = 0;
-
- d = tmcmp(tptr, tm);
- if (d < 0) {
- guess_hi = guess;
- tm_hi = *tm;
- if (range) {
- guess = guess - range;
- range = 0;
- if (guess_lo < guess && guess < guess_hi)
- have_guess = 1;
- }
- }
- else if (d > 0) {
- guess_lo = guess;
- tm_lo = *tm;
- if (range) {
- guess = guess + range;
- range = 0;
- if (guess_lo < guess && guess < guess_hi)
- have_guess = 1;
- }
- }
- else {
- if (!utc_p) {
- /* If localtime is nonmonotonic, another result may exist. */
- time_t guess2;
- if (find_dst) {
- guess2 = guess - 2 * 60 * 60;
- tm = localtime(&guess2);
- if (tm) {
- if (tptr->tm_hour != (tm->tm_hour + 2) % 24 ||
- tptr->tm_min != tm->tm_min ||
- tptr->tm_sec != tm->tm_sec
- ) {
- guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
- (tm->tm_min - tptr->tm_min) * 60 +
- (tm->tm_sec - tptr->tm_sec);
- if (tptr->tm_mday != tm->tm_mday)
- guess2 += 24 * 60 * 60;
- if (guess != guess2) {
- tm = localtime(&guess2);
- if (tmcmp(tptr, tm) == 0) {
- if (guess < guess2)
- return guess;
- else
- return guess2;
- }
- }
- }
- }
- }
- else {
- guess2 = guess + 2 * 60 * 60;
- tm = localtime(&guess2);
- if (tm) {
- if ((tptr->tm_hour + 2) % 24 != tm->tm_hour ||
- tptr->tm_min != tm->tm_min ||
- tptr->tm_sec != tm->tm_sec
- ) {
- guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
- (tm->tm_min - tptr->tm_min) * 60 +
- (tm->tm_sec - tptr->tm_sec);
- if (tptr->tm_mday != tm->tm_mday)
- guess2 -= 24 * 60 * 60;
- if (guess != guess2) {
- tm = localtime(&guess2);
- if (tmcmp(tptr, tm) == 0) {
- if (guess < guess2)
- return guess2;
- else
- return guess;
- }
- }
- }
- }
- }
- }
- return guess;
- }
- }
- /* Given argument has no corresponding time_t. Let's outerpolation. */
- if (tm_lo.tm_year == tptr->tm_year && tm_lo.tm_mon == tptr->tm_mon) {
- return guess_lo +
- (tptr->tm_mday - tm_lo.tm_mday) * 24 * 60 * 60 +
- (tptr->tm_hour - tm_lo.tm_hour) * 60 * 60 +
- (tptr->tm_min - tm_lo.tm_min) * 60 +
- (tptr->tm_sec - tm_lo.tm_sec);
- }
- else if (tm_hi.tm_year == tptr->tm_year && tm_hi.tm_mon == tptr->tm_mon) {
- return guess_hi +
- (tptr->tm_mday - tm_hi.tm_mday) * 24 * 60 * 60 +
- (tptr->tm_hour - tm_hi.tm_hour) * 60 * 60 +
- (tptr->tm_min - tm_hi.tm_min) * 60 +
- (tptr->tm_sec - tm_hi.tm_sec);
- }
-
- out_of_range:
- rb_raise(rb_eArgError, "time out of range");
-
- error:
- rb_raise(rb_eArgError, "gmtime/localtime error");
- return 0; /* not reached */
-}
-
-static time_t
-make_time_t(tptr, utc_p)
- struct tm *tptr;
- int utc_p;
-{
- time_t t;
- struct tm *tmp, buf;
- buf = *tptr;
- if (utc_p) {
-#if defined(HAVE_TIMEGM)
- if ((t = timegm(&buf)) != -1)
- return t;
-#ifdef NEGATIVE_TIME_T
- if ((tmp = gmtime(&t)) &&
- tptr->tm_year == tmp->tm_year &&
- tptr->tm_mon == tmp->tm_mon &&
- tptr->tm_mday == tmp->tm_mday &&
- tptr->tm_hour == tmp->tm_hour &&
- tptr->tm_min == tmp->tm_min &&
- tptr->tm_sec == tmp->tm_sec
- )
- return t;
-#endif
-#endif
- return search_time_t(&buf, utc_p);
- }
- else {
-#if defined(HAVE_MKTIME)
- if ((t = mktime(&buf)) != -1)
- return t;
-#ifdef NEGATIVE_TIME_T
- if ((tmp = localtime(&t)) &&
- tptr->tm_year == tmp->tm_year &&
- tptr->tm_mon == tmp->tm_mon &&
- tptr->tm_mday == tmp->tm_mday &&
- tptr->tm_hour == tmp->tm_hour &&
- tptr->tm_min == tmp->tm_min &&
- tptr->tm_sec == tmp->tm_sec
- )
- return t;
-#endif
-#endif
- return search_time_t(&buf, utc_p);
- }
-}
-
-static VALUE
-time_utc_or_local(argc, argv, utc_p, klass)
- int argc;
- VALUE *argv;
- int utc_p;
- VALUE klass;
-{
- struct tm tm;
- VALUE time;
- time_t usec;
-
- time_arg(argc, argv, &tm, &usec);
- time = time_new_internal(klass, make_time_t(&tm, utc_p), usec);
- if (utc_p) return time_gmtime(time);
- return time_localtime(time);
-}
-
-/*
- * call-seq:
- * Time.utc( year [, month, day, hour, min, sec, usec] ) => time
- * Time.utc( sec, min, hour, day, month, year, wday, yday, isdst, tz
- * ) => time
- * Time.gm( year [, month, day, hour, min, sec, usec] ) => time
- * Time.gm( sec, min, hour, day, month, year, wday, yday, isdst, tz
- * ) => time
- *
- * Creates a time based on given values, interpreted as UTC (GMT). The
- * year must be specified. Other values default to the minimum value
- * for that field (and may be <code>nil</code> or omitted). Months may
- * be specified by numbers from 1 to 12, or by the three-letter English
- * month names. Hours are specified on a 24-hour clock (0..23). Raises
- * an <code>ArgumentError</code> if any values are out of range. Will
- * also accept ten arguments in the order output by
- * <code>Time#to_a</code>.
- *
- * Time.utc(2000,"jan",1,20,15,1) #=> Sat Jan 01 20:15:01 UTC 2000
- * Time.gm(2000,"jan",1,20,15,1) #=> Sat Jan 01 20:15:01 UTC 2000
- */
-static VALUE
-time_s_mkutc(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- return time_utc_or_local(argc, argv, Qtrue, klass);
-}
-
-/*
- * call-seq:
- * Time.local( year [, month, day, hour, min, sec, usec] ) => time
- * Time.local( sec, min, hour, day, month, year, wday, yday, isdst,
- * tz ) => time
- * Time.mktime( year, month, day, hour, min, sec, usec ) => time
- *
- * Same as <code>Time::gm</code>, but interprets the values in the
- * local time zone.
- *
- * Time.local(2000,"jan",1,20,15,1) #=> Sat Jan 01 20:15:01 CST 2000
- */
-
-static VALUE
-time_s_mktime(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- return time_utc_or_local(argc, argv, Qfalse, klass);
-}
-
-/*
- * call-seq:
- * time.to_i => int
- * time.tv_sec => int
- *
- * Returns the value of <i>time</i> as an integer number of seconds
- * since epoch.
- *
- * t = Time.now
- * "%10.5f" % t.to_f #=> "1049896564.17839"
- * t.to_i #=> 1049896564
- */
-
-static VALUE
-time_to_i(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- return LONG2NUM(tobj->tv.tv_sec);
-}
-
-/*
- * call-seq:
- * time.to_f => float
- *
- * Returns the value of <i>time</i> as a floating point number of
- * seconds since epoch.
- *
- * t = Time.now
- * "%10.5f" % t.to_f #=> "1049896564.13654"
- * t.to_i #=> 1049896564
- */
-
-static VALUE
-time_to_f(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- return rb_float_new((double)tobj->tv.tv_sec+(double)tobj->tv.tv_usec/1e6);
-}
-
-/*
- * call-seq:
- * time.usec => int
- * time.tv_usec => int
- *
- * Returns just the number of microseconds for <i>time</i>.
- *
- * t = Time.now #=> Wed Apr 09 08:56:04 CDT 2003
- * "%10.6f" % t.to_f #=> "1049896564.259970"
- * t.usec #=> 259970
- */
-
-static VALUE
-time_usec(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- return LONG2NUM(tobj->tv.tv_usec);
-}
-
-/*
- * call-seq:
- * time <=> other_time => -1, 0, +1
- * time <=> numeric => -1, 0, +1
- *
- * Comparison---Compares <i>time</i> with <i>other_time</i> or with
- * <i>numeric</i>, which is the number of seconds (possibly
- * fractional) since epoch.
- *
- * t = Time.now #=> Wed Apr 09 08:56:03 CDT 2003
- * t2 = t + 2592000 #=> Fri May 09 08:56:03 CDT 2003
- * t <=> t2 #=> -1
- * t2 <=> t #=> 1
- * t <=> t #=> 0
- */
-
-static VALUE
-time_cmp(time1, time2)
- VALUE time1, time2;
-{
- struct time_object *tobj1, *tobj2;
-
- GetTimeval(time1, tobj1);
- if (TYPE(time2) == T_DATA && RDATA(time2)->dfree == time_free) {
- GetTimeval(time2, tobj2);
- if (tobj1->tv.tv_sec == tobj2->tv.tv_sec) {
- if (tobj1->tv.tv_usec == tobj2->tv.tv_usec) return INT2FIX(0);
- if (tobj1->tv.tv_usec > tobj2->tv.tv_usec) return INT2FIX(1);
- return INT2FIX(-1);
- }
- if (tobj1->tv.tv_sec > tobj2->tv.tv_sec) return INT2FIX(1);
- return INT2FIX(-1);
- }
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * time.eql?(other_time)
- *
- * Return <code>true</code> if <i>time</i> and <i>other_time</i> are
- * both <code>Time</code> objects with the same seconds and fractional
- * seconds.
- */
-
-static VALUE
-time_eql(time1, time2)
- VALUE time1, time2;
-{
- struct time_object *tobj1, *tobj2;
-
- GetTimeval(time1, tobj1);
- if (TYPE(time2) == T_DATA && RDATA(time2)->dfree == time_free) {
- GetTimeval(time2, tobj2);
- if (tobj1->tv.tv_sec == tobj2->tv.tv_sec) {
- if (tobj1->tv.tv_usec == tobj2->tv.tv_usec) return Qtrue;
- }
- }
- return Qfalse;
-}
-
-/*
- * call-seq:
- * time.utc? => true or false
- * time.gmt? => true or false
- *
- * Returns <code>true</code> if <i>time</i> represents a time in UTC
- * (GMT).
- *
- * t = Time.now #=> Wed Apr 09 08:56:04 CDT 2003
- * t.utc? #=> false
- * t = Time.gm(2000,"jan",1,20,15,1) #=> Sat Jan 01 20:15:01 UTC 2000
- * t.utc? #=> true
- *
- * t = Time.now #=> Wed Apr 09 08:56:03 CDT 2003
- * t.gmt? #=> false
- * t = Time.gm(2000,1,1,20,15,1) #=> Sat Jan 01 20:15:01 UTC 2000
- * t.gmt? #=> true
- */
-
-static VALUE
-time_utc_p(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- if (tobj->gmt) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * time.hash => fixnum
- *
- * Return a hash code for this time object.
- */
-
-static VALUE
-time_hash(time)
- VALUE time;
-{
- struct time_object *tobj;
- long hash;
-
- GetTimeval(time, tobj);
- hash = tobj->tv.tv_sec ^ tobj->tv.tv_usec;
- return LONG2FIX(hash);
-}
-
-/* :nodoc: */
-static VALUE
-time_init_copy(copy, time)
- VALUE copy, time;
-{
- struct time_object *tobj, *tcopy;
-
- if (copy == time) return copy;
- time_modify(copy);
- if (TYPE(time) != T_DATA || RDATA(time)->dfree != time_free) {
- rb_raise(rb_eTypeError, "wrong argument type");
- }
- GetTimeval(time, tobj);
- GetTimeval(copy, tcopy);
- MEMCPY(tcopy, tobj, struct time_object, 1);
-
- return copy;
-}
-
-static VALUE
-time_dup(time)
- VALUE time;
-{
- VALUE dup = time_s_alloc(rb_cTime);
- time_init_copy(dup, time);
- return dup;
-}
-
-/*
- * call-seq:
- * time.localtime => time
- *
- * Converts <i>time</i> to local time (using the local time zone in
- * effect for this process) modifying the receiver.
- *
- * t = Time.gm(2000, "jan", 1, 20, 15, 1)
- * t.gmt? #=> true
- * t.localtime #=> Sat Jan 01 14:15:01 CST 2000
- * t.gmt? #=> false
- */
-
-static VALUE
-time_localtime(time)
- VALUE time;
-{
- struct time_object *tobj;
- struct tm *tm_tmp;
- time_t t;
-
- GetTimeval(time, tobj);
- if (!tobj->gmt) {
- if (tobj->tm_got)
- return time;
- }
- else {
- time_modify(time);
- }
- t = tobj->tv.tv_sec;
- tm_tmp = localtime(&t);
- if (!tm_tmp)
- rb_raise(rb_eArgError, "localtime error");
- tobj->tm = *tm_tmp;
- tobj->tm_got = 1;
- tobj->gmt = 0;
- return time;
-}
-
-/*
- * call-seq:
- * time.gmtime => time
- * time.utc => time
- *
- * Converts <i>time</i> to UTC (GMT), modifying the receiver.
- *
- * t = Time.now #=> Wed Apr 09 08:56:03 CDT 2003
- * t.gmt? #=> false
- * t.gmtime #=> Wed Apr 09 13:56:03 UTC 2003
- * t.gmt? #=> true
- *
- * t = Time.now #=> Wed Apr 09 08:56:04 CDT 2003
- * t.utc? #=> false
- * t.utc #=> Wed Apr 09 13:56:04 UTC 2003
- * t.utc? #=> true
- */
-
-static VALUE
-time_gmtime(time)
- VALUE time;
-{
- struct time_object *tobj;
- struct tm *tm_tmp;
- time_t t;
-
- GetTimeval(time, tobj);
- if (tobj->gmt) {
- if (tobj->tm_got)
- return time;
- }
- else {
- time_modify(time);
- }
- t = tobj->tv.tv_sec;
- tm_tmp = gmtime(&t);
- if (!tm_tmp)
- rb_raise(rb_eArgError, "gmtime error");
- tobj->tm = *tm_tmp;
- tobj->tm_got = 1;
- tobj->gmt = 1;
- return time;
-}
-
-/*
- * call-seq:
- * time.getlocal => new_time
- *
- * Returns a new <code>new_time</code> object representing <i>time</i> in
- * local time (using the local time zone in effect for this process).
- *
- * t = Time.gm(2000,1,1,20,15,1) #=> Sat Jan 01 20:15:01 UTC 2000
- * t.gmt? #=> true
- * l = t.getlocal #=> Sat Jan 01 14:15:01 CST 2000
- * l.gmt? #=> false
- * t == l #=> true
- */
-
-static VALUE
-time_getlocaltime(time)
- VALUE time;
-{
- return time_localtime(time_dup(time));
-}
-
-/*
- * call-seq:
- * time.getgm => new_time
- * time.getutc => new_time
- *
- * Returns a new <code>new_time</code> object representing <i>time</i> in
- * UTC.
- *
- * t = Time.local(2000,1,1,20,15,1) #=> Sat Jan 01 20:15:01 CST 2000
- * t.gmt? #=> false
- * y = t.getgm #=> Sun Jan 02 02:15:01 UTC 2000
- * y.gmt? #=> true
- * t == y #=> true
- */
-
-static VALUE
-time_getgmtime(time)
- VALUE time;
-{
- return time_gmtime(time_dup(time));
-}
-
-static VALUE
-time_get_tm(time, gmt)
- VALUE time;
- int gmt;
-{
- if (gmt) return time_gmtime(time);
- return time_localtime(time);
-}
-
-/*
- * call-seq:
- * time.asctime => string
- * time.ctime => string
- *
- * Returns a canonical string representation of <i>time</i>.
- *
- * Time.now.asctime #=> "Wed Apr 9 08:56:03 2003"
- */
-
-static VALUE
-time_asctime(time)
- VALUE time;
-{
- struct time_object *tobj;
- char *s;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- s = asctime(&tobj->tm);
- if (s[24] == '\n') s[24] = '\0';
-
- return rb_str_new2(s);
-}
-
-/*
- * call-seq:
- * time.inspect => string
- * time.to_s => string
- *
- * Returns a string representing <i>time</i>. Equivalent to calling
- * <code>Time#strftime</code> with a format string of ``<code>%a</code>
- * <code>%b</code> <code>%d</code> <code>%H:%M:%S</code>
- * <code>%Z</code> <code>%Y</code>''.
- *
- * Time.now.to_s #=> "Wed Apr 09 08:56:04 CDT 2003"
- */
-
-static VALUE
-time_to_s(time)
- VALUE time;
-{
- struct time_object *tobj;
- char buf[128];
- int len;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- if (tobj->gmt == 1) {
- len = strftime(buf, 128, "%a %b %d %H:%M:%S UTC %Y", &tobj->tm);
- }
- else {
- len = strftime(buf, 128, "%a %b %d %H:%M:%S %Z %Y", &tobj->tm);
- }
- return rb_str_new(buf, len);
-}
-
-#if SIZEOF_TIME_T == SIZEOF_LONG
-typedef unsigned long unsigned_time_t;
-#elif SIZEOF_TIME_T == SIZEOF_INT
-typedef unsigned int unsigned_time_t;
-#elif SIZEOF_TIME_T == SIZEOF_LONG_LONG
-typedef unsigned long long unsigned_time_t;
-#else
-# error cannot find integer type which size is same as time_t.
-#endif
-
-static VALUE
-time_add(tobj, offset, sign)
- struct time_object *tobj;
- VALUE offset;
- int sign;
-{
- double v = NUM2DBL(offset);
- double f, d;
- unsigned_time_t sec_off;
- time_t usec_off, sec, usec;
- VALUE result;
-
- if (v < 0) {
- v = -v;
- sign = -sign;
- }
- d = modf(v, &f);
- sec_off = (unsigned_time_t)f;
- if (f != (double)sec_off)
- rb_raise(rb_eRangeError, "time %s %f out of Time range",
- sign < 0 ? "-" : "+", v);
- usec_off = (time_t)(d*1e6);
-
- if (sign < 0) {
- sec = tobj->tv.tv_sec - sec_off;
- usec = tobj->tv.tv_usec - usec_off;
- if (sec > tobj->tv.tv_sec)
- rb_raise(rb_eRangeError, "time - %f out of Time range", v);
- }
- else {
- sec = tobj->tv.tv_sec + sec_off;
- usec = tobj->tv.tv_usec + usec_off;
- if (sec < tobj->tv.tv_sec)
- rb_raise(rb_eRangeError, "time + %f out of Time range", v);
- }
- result = rb_time_new(sec, usec);
- if (tobj->gmt) {
- GetTimeval(result, tobj);
- tobj->gmt = 1;
- }
- return result;
-}
-
-/*
- * call-seq:
- * time + numeric => time
- *
- * Addition---Adds some number of seconds (possibly fractional) to
- * <i>time</i> and returns that value as a new time.
- *
- * t = Time.now #=> Wed Apr 09 08:56:03 CDT 2003
- * t + (60 * 60 * 24) #=> Thu Apr 10 08:56:03 CDT 2003
- */
-
-static VALUE
-time_plus(time1, time2)
- VALUE time1, time2;
-{
- struct time_object *tobj;
- GetTimeval(time1, tobj);
-
- if (TYPE(time2) == T_DATA && RDATA(time2)->dfree == time_free) {
- rb_raise(rb_eTypeError, "time + time?");
- }
- return time_add(tobj, time2, 1);
-}
-
-/*
- * call-seq:
- * time - other_time => float
- * time - numeric => time
- *
- * Difference---Returns a new time that represents the difference
- * between two times, or subtracts the given number of seconds in
- * <i>numeric</i> from <i>time</i>.
- *
- * t = Time.now #=> Wed Apr 09 08:56:03 CDT 2003
- * t2 = t + 2592000 #=> Fri May 09 08:56:03 CDT 2003
- * t2 - t #=> 2592000.0
- * t2 - 2592000 #=> Wed Apr 09 08:56:03 CDT 2003
- */
-
-static VALUE
-time_minus(time1, time2)
- VALUE time1, time2;
-{
- struct time_object *tobj;
-
- GetTimeval(time1, tobj);
- if (TYPE(time2) == T_DATA && RDATA(time2)->dfree == time_free) {
- struct time_object *tobj2;
- double f;
-
- GetTimeval(time2, tobj2);
- f = (double)tobj->tv.tv_sec - (double)tobj2->tv.tv_sec;
- f += ((double)tobj->tv.tv_usec - (double)tobj2->tv.tv_usec)*1e-6;
- /* XXX: should check float overflow on 64bit time_t platforms */
-
- return rb_float_new(f);
- }
- return time_add(tobj, time2, -1);
-}
-
-/*
- * call-seq:
- * time.succ => new_time
- *
- * Return a new time object, one second later than <code>time</code>.
- */
-
-static VALUE
-time_succ(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- return rb_time_new(tobj->tv.tv_sec + 1, tobj->tv.tv_usec);
-}
-
-/*
- * call-seq:
- * time.sec => fixnum
- *
- * Returns the second of the minute (0..60)<em>[Yes, seconds really can
- * range from zero to 60. This allows the system to inject leap seconds
- * every now and then to correct for the fact that years are not really
- * a convenient number of hours long.]</em> for <i>time</i>.
- *
- * t = Time.now #=> Wed Apr 09 08:56:04 CDT 2003
- * t.sec #=> 4
- */
-
-static VALUE
-time_sec(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- return INT2FIX(tobj->tm.tm_sec);
-}
-
-/*
- * call-seq:
- * time.min => fixnum
- *
- * Returns the minute of the hour (0..59) for <i>time</i>.
- *
- * t = Time.now #=> Wed Apr 09 08:56:03 CDT 2003
- * t.min #=> 56
- */
-
-static VALUE
-time_min(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- return INT2FIX(tobj->tm.tm_min);
-}
-
-/*
- * call-seq:
- * time.hour => fixnum
- *
- * Returns the hour of the day (0..23) for <i>time</i>.
- *
- * t = Time.now #=> Wed Apr 09 08:56:03 CDT 2003
- * t.hour #=> 8
- */
-
-static VALUE
-time_hour(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- return INT2FIX(tobj->tm.tm_hour);
-}
-
-/*
- * call-seq:
- * time.day => fixnum
- * time.mday => fixnum
- *
- * Returns the day of the month (1..n) for <i>time</i>.
- *
- * t = Time.now #=> Wed Apr 09 08:56:03 CDT 2003
- * t.day #=> 9
- * t.mday #=> 9
- */
-
-static VALUE
-time_mday(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- return INT2FIX(tobj->tm.tm_mday);
-}
-
-/*
- * call-seq:
- * time.mon => fixnum
- * time.month => fixnum
- *
- * Returns the month of the year (1..12) for <i>time</i>.
- *
- * t = Time.now #=> Wed Apr 09 08:56:03 CDT 2003
- * t.mon #=> 4
- * t.month #=> 4
- */
-
-static VALUE
-time_mon(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- return INT2FIX(tobj->tm.tm_mon+1);
-}
-
-/*
- * call-seq:
- * time.year => fixnum
- *
- * Returns the year for <i>time</i> (including the century).
- *
- * t = Time.now #=> Wed Apr 09 08:56:04 CDT 2003
- * t.year #=> 2003
- */
-
-static VALUE
-time_year(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- return LONG2NUM((long)tobj->tm.tm_year+1900);
-}
-
-/*
- * call-seq:
- * time.wday => fixnum
- *
- * Returns an integer representing the day of the week, 0..6, with
- * Sunday == 0.
- *
- * t = Time.now #=> Wed Apr 09 08:56:04 CDT 2003
- * t.wday #=> 3
- */
-
-static VALUE
-time_wday(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- return INT2FIX(tobj->tm.tm_wday);
-}
-
-/*
- * call-seq:
- * time.yday => fixnum
- *
- * Returns an integer representing the day of the year, 1..366.
- *
- * t = Time.now #=> Wed Apr 09 08:56:04 CDT 2003
- * t.yday #=> 99
- */
-
-static VALUE
-time_yday(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- return INT2FIX(tobj->tm.tm_yday+1);
-}
-
-/*
- * call-seq:
- * time.isdst => true or false
- * time.dst? => true or false
- *
- * Returns <code>true</code> if <i>time</i> occurs during Daylight
- * Saving Time in its time zone.
- *
- * Time.local(2000, 7, 1).isdst #=> true
- * Time.local(2000, 1, 1).isdst #=> false
- * Time.local(2000, 7, 1).dst? #=> true
- * Time.local(2000, 1, 1).dst? #=> false
- */
-
-static VALUE
-time_isdst(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- return tobj->tm.tm_isdst?Qtrue:Qfalse;
-}
-
-/*
- * call-seq:
- * time.zone => string
- *
- * Returns the name of the time zone used for <i>time</i>. As of Ruby
- * 1.8, returns ``UTC'' rather than ``GMT'' for UTC times.
- *
- * t = Time.gm(2000, "jan", 1, 20, 15, 1)
- * t.zone #=> "UTC"
- * t = Time.local(2000, "jan", 1, 20, 15, 1)
- * t.zone #=> "CST"
- */
-
-static VALUE
-time_zone(time)
- VALUE time;
-{
- struct time_object *tobj;
-#if !defined(HAVE_TM_ZONE) && (!defined(HAVE_TZNAME) || !defined(HAVE_DAYLIGHT))
- char buf[64];
- int len;
-#endif
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
-
- if (tobj->gmt == 1) {
- return rb_str_new2("UTC");
- }
-#if defined(HAVE_TM_ZONE)
- return rb_str_new2(tobj->tm.tm_zone);
-#elif defined(HAVE_TZNAME) && defined(HAVE_DAYLIGHT)
- return rb_str_new2(tzname[daylight && tobj->tm.tm_isdst]);
-#else
- len = strftime(buf, 64, "%Z", &tobj->tm);
- return rb_str_new(buf, len);
-#endif
-}
-
-/*
- * call-seq:
- * time.gmt_offset => fixnum
- * time.gmtoff => fixnum
- * time.utc_offset => fixnum
- *
- * Returns the offset in seconds between the timezone of <i>time</i>
- * and UTC.
- *
- * t = Time.gm(2000,1,1,20,15,1) #=> Sat Jan 01 20:15:01 UTC 2000
- * t.gmt_offset #=> 0
- * l = t.getlocal #=> Sat Jan 01 14:15:01 CST 2000
- * l.gmt_offset #=> -21600
- */
-
-static VALUE
-time_utc_offset(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
-
- if (tobj->gmt == 1) {
- return INT2FIX(0);
- }
- else {
-#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
- return INT2NUM(tobj->tm.tm_gmtoff);
-#else
- struct tm *u, *l;
- time_t t;
- long off;
- l = &tobj->tm;
- t = tobj->tv.tv_sec;
- u = gmtime(&t);
- if (!u)
- rb_raise(rb_eArgError, "gmtime error");
- if (l->tm_year != u->tm_year)
- off = l->tm_year < u->tm_year ? -1 : 1;
- else if (l->tm_mon != u->tm_mon)
- off = l->tm_mon < u->tm_mon ? -1 : 1;
- else if (l->tm_mday != u->tm_mday)
- off = l->tm_mday < u->tm_mday ? -1 : 1;
- else
- off = 0;
- off = off * 24 + l->tm_hour - u->tm_hour;
- off = off * 60 + l->tm_min - u->tm_min;
- off = off * 60 + l->tm_sec - u->tm_sec;
- return LONG2FIX(off);
-#endif
- }
-}
-
-/*
- * call-seq:
- * time.to_a => array
- *
- * Returns a ten-element <i>array</i> of values for <i>time</i>:
- * {<code>[ sec, min, hour, day, month, year, wday, yday, isdst, zone
- * ]</code>}. See the individual methods for an explanation of the
- * valid ranges of each value. The ten elements can be passed directly
- * to <code>Time::utc</code> or <code>Time::local</code> to create a
- * new <code>Time</code>.
- *
- * now = Time.now #=> Wed Apr 09 08:56:04 CDT 2003
- * t = now.to_a #=> [4, 56, 8, 9, 4, 2003, 3, 99, true, "CDT"]
- */
-
-static VALUE
-time_to_a(time)
- VALUE time;
-{
- struct time_object *tobj;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- return rb_ary_new3(10,
- INT2FIX(tobj->tm.tm_sec),
- INT2FIX(tobj->tm.tm_min),
- INT2FIX(tobj->tm.tm_hour),
- INT2FIX(tobj->tm.tm_mday),
- INT2FIX(tobj->tm.tm_mon+1),
- LONG2NUM((long)tobj->tm.tm_year+1900),
- INT2FIX(tobj->tm.tm_wday),
- INT2FIX(tobj->tm.tm_yday+1),
- tobj->tm.tm_isdst?Qtrue:Qfalse,
- time_zone(time));
-}
-
-#define SMALLBUF 100
-static int
-rb_strftime(buf, format, time)
- char ** volatile buf;
- char * volatile format;
- struct tm * volatile time;
-{
- volatile int size;
- int len, flen;
-
- (*buf)[0] = '\0';
- flen = strlen(format);
- if (flen == 0) {
- return 0;
- }
- len = strftime(*buf, SMALLBUF, format, time);
- if (len != 0 || **buf == '\0') return len;
- for (size=1024; ; size*=2) {
- *buf = xmalloc(size);
- (*buf)[0] = '\0';
- len = strftime(*buf, size, format, time);
- /*
- * buflen can be zero EITHER because there's not enough
- * room in the string, or because the control command
- * goes to the empty string. Make a reasonable guess that
- * if the buffer is 1024 times bigger than the length of the
- * format string, it's not failing for lack of room.
- */
- if (len > 0 || size >= 1024 * flen) return len;
- free(*buf);
- }
- /* not reached */
-}
-
-/*
- * call-seq:
- * time.strftime( string ) => string
- *
- * Formats <i>time</i> according to the directives in the given format
- * string. Any text not listed as a directive will be passed through
- * to the output string.
- *
- * Format meaning:
- * %a - The abbreviated weekday name (``Sun'')
- * %A - The full weekday name (``Sunday'')
- * %b - The abbreviated month name (``Jan'')
- * %B - The full month name (``January'')
- * %c - The preferred local date and time representation
- * %d - Day of the month (01..31)
- * %H - Hour of the day, 24-hour clock (00..23)
- * %I - Hour of the day, 12-hour clock (01..12)
- * %j - Day of the year (001..366)
- * %m - Month of the year (01..12)
- * %M - Minute of the hour (00..59)
- * %p - Meridian indicator (``AM'' or ``PM'')
- * %S - Second of the minute (00..60)
- * %U - Week number of the current year,
- * starting with the first Sunday as the first
- * day of the first week (00..53)
- * %W - Week number of the current year,
- * starting with the first Monday as the first
- * day of the first week (00..53)
- * %w - Day of the week (Sunday is 0, 0..6)
- * %x - Preferred representation for the date alone, no time
- * %X - Preferred representation for the time alone, no date
- * %y - Year without a century (00..99)
- * %Y - Year with century
- * %Z - Time zone name
- * %% - Literal ``%'' character
- *
- * t = Time.now
- * t.strftime("Printed on %m/%d/%Y") #=> "Printed on 04/09/2003"
- * t.strftime("at %I:%M%p") #=> "at 08:56AM"
- */
-
-static VALUE
-time_strftime(time, format)
- VALUE time, format;
-{
- struct time_object *tobj;
- char buffer[SMALLBUF];
- char *fmt, *buf = buffer;
- long len;
- VALUE str;
-
- GetTimeval(time, tobj);
- if (tobj->tm_got == 0) {
- time_get_tm(time, tobj->gmt);
- }
- StringValue(format);
- format = rb_str_new4(format);
- fmt = RSTRING(format)->ptr;
- len = RSTRING(format)->len;
- if (len == 0) {
- rb_warning("strftime called with empty format string");
- }
- else if (strlen(fmt) < len) {
- /* Ruby string may contain \0's. */
- char *p = fmt, *pe = fmt + len;
-
- str = rb_str_new(0, 0);
- while (p < pe) {
- len = rb_strftime(&buf, p, &tobj->tm);
- rb_str_cat(str, buf, len);
- p += strlen(p) + 1;
- if (p <= pe)
- rb_str_cat(str, "\0", 1);
- if (buf != buffer) {
- free(buf);
- buf = buffer;
- }
- }
- return str;
- }
- else {
- len = rb_strftime(&buf, RSTRING(format)->ptr, &tobj->tm);
- }
- str = rb_str_new(buf, len);
- if (buf != buffer) free(buf);
- return str;
-}
-
-/*
- * call-seq:
- * Time.times => struct_tms
- *
- * Deprecated in favor of <code>Process::times</code>
- */
-
-static VALUE
-time_s_times(obj)
- VALUE obj;
-{
- rb_warn("obsolete method Time::times; use Process::times");
- return rb_proc_times(obj);
-}
-
-/*
- * undocumented
- */
-
-static VALUE
-time_mdump(time)
- VALUE time;
-{
- struct time_object *tobj;
- struct tm *tm;
- unsigned long p, s;
- char buf[8];
- time_t t;
- int i;
-
- GetTimeval(time, tobj);
-
- t = tobj->tv.tv_sec;
- tm = gmtime(&t);
-
- if ((tm->tm_year & 0xffff) != tm->tm_year)
- rb_raise(rb_eArgError, "year too big to marshal");
-
- p = 0x1 << 31 | /* 1 */
- tobj->gmt << 30 | /* 1 */
- tm->tm_year << 14 | /* 16 */
- tm->tm_mon << 10 | /* 4 */
- tm->tm_mday << 5 | /* 5 */
- tm->tm_hour; /* 5 */
- s = tm->tm_min << 26 | /* 6 */
- tm->tm_sec << 20 | /* 6 */
- tobj->tv.tv_usec; /* 20 */
-
- for (i=0; i<4; i++) {
- buf[i] = p & 0xff;
- p = RSHIFT(p, 8);
- }
- for (i=4; i<8; i++) {
- buf[i] = s & 0xff;
- s = RSHIFT(s, 8);
- }
-
- return rb_str_new(buf, 8);
-}
-
-/*
- * call-seq:
- * time._dump => string
- *
- * Dump _time_ for marshaling.
- */
-
-static VALUE
-time_dump(argc, argv, time)
- int argc;
- VALUE *argv;
- VALUE time;
-{
- VALUE str;
-
- rb_scan_args(argc, argv, "01", 0);
- str = time_mdump(time);
- rb_copy_generic_ivar(str, time);
-
- return str;
-}
-
-/*
- * undocumented
- */
-
-static VALUE
-time_mload(time, str)
- VALUE time, str;
-{
- struct time_object *tobj;
- unsigned long p, s;
- time_t sec, usec;
- unsigned char *buf;
- struct tm tm;
- int i, gmt;
-
- time_modify(time);
- StringValue(str);
- buf = (unsigned char *)RSTRING(str)->ptr;
- if (RSTRING(str)->len != 8) {
- rb_raise(rb_eTypeError, "marshaled time format differ");
- }
-
- p = s = 0;
- for (i=0; i<4; i++) {
- p |= buf[i]<<(8*i);
- }
- for (i=4; i<8; i++) {
- s |= buf[i]<<(8*(i-4));
- }
-
- if ((p & (1<<31)) == 0) {
- sec = p;
- usec = s;
- }
- else {
- p &= ~(1<<31);
- gmt = (p >> 30) & 0x1;
- tm.tm_year = (p >> 14) & 0xffff;
- tm.tm_mon = (p >> 10) & 0xf;
- tm.tm_mday = (p >> 5) & 0x1f;
- tm.tm_hour = p & 0x1f;
- tm.tm_min = (s >> 26) & 0x3f;
- tm.tm_sec = (s >> 20) & 0x3f;
- tm.tm_isdst = 0;
-
- sec = make_time_t(&tm, Qtrue);
- usec = (time_t)(s & 0xfffff);
- }
- time_overflow_p(&sec, &usec);
-
- GetTimeval(time, tobj);
- tobj->tm_got = 0;
- tobj->gmt = gmt;
- tobj->tv.tv_sec = sec;
- tobj->tv.tv_usec = usec;
- return time;
-}
-
-/*
- * call-seq:
- * Time._load(string) => time
- *
- * Unmarshal a dumped +Time+ object.
- */
-
-static VALUE
-time_load(klass, str)
- VALUE klass, str;
-{
- VALUE time = time_s_alloc(klass);
-
- rb_copy_generic_ivar(time, str);
- time_mload(time, str);
- return time;
-}
-
-/*
- * <code>Time</code> is an abstraction of dates and times. Time is
- * stored internally as the number of seconds and microseconds since
- * the <em>epoch</em>, January 1, 1970 00:00 UTC. On some operating
- * systems, this offset is allowed to be negative. Also see the
- * library modules <code>Date</code> and <code>ParseDate</code>. The
- * <code>Time</code> class treats GMT (Greenwich Mean Time) and UTC
- * (Coordinated Universal Time)<em>[Yes, UTC really does stand for
- * Coordinated Universal Time. There was a committee involved.]</em>
- * as equivalent. GMT is the older way of referring to these
- * baseline times but persists in the names of calls on Posix
- * systems.
- *
- * All times are stored with some number of microseconds. Be aware of
- * this fact when comparing times with each other---times that are
- * apparently equal when displayed may be different when compared.
- */
-
-void
-Init_Time()
-{
- rb_cTime = rb_define_class("Time", rb_cObject);
- rb_include_module(rb_cTime, rb_mComparable);
-
- rb_define_alloc_func(rb_cTime, time_s_alloc);
- rb_define_singleton_method(rb_cTime, "now", rb_class_new_instance, -1);
- rb_define_singleton_method(rb_cTime, "at", time_s_at, -1);
- rb_define_singleton_method(rb_cTime, "utc", time_s_mkutc, -1);
- rb_define_singleton_method(rb_cTime, "gm", time_s_mkutc, -1);
- rb_define_singleton_method(rb_cTime, "local", time_s_mktime, -1);
- rb_define_singleton_method(rb_cTime, "mktime", time_s_mktime, -1);
-
- rb_define_singleton_method(rb_cTime, "times", time_s_times, 0);
-
- rb_define_method(rb_cTime, "to_i", time_to_i, 0);
- rb_define_method(rb_cTime, "to_f", time_to_f, 0);
- rb_define_method(rb_cTime, "<=>", time_cmp, 1);
- rb_define_method(rb_cTime, "eql?", time_eql, 1);
- rb_define_method(rb_cTime, "hash", time_hash, 0);
- rb_define_method(rb_cTime, "initialize", time_init, 0);
- rb_define_method(rb_cTime, "initialize_copy", time_init_copy, 1);
-
- rb_define_method(rb_cTime, "localtime", time_localtime, 0);
- rb_define_method(rb_cTime, "gmtime", time_gmtime, 0);
- rb_define_method(rb_cTime, "utc", time_gmtime, 0);
- rb_define_method(rb_cTime, "getlocal", time_getlocaltime, 0);
- rb_define_method(rb_cTime, "getgm", time_getgmtime, 0);
- rb_define_method(rb_cTime, "getutc", time_getgmtime, 0);
-
- rb_define_method(rb_cTime, "ctime", time_asctime, 0);
- rb_define_method(rb_cTime, "asctime", time_asctime, 0);
- rb_define_method(rb_cTime, "to_s", time_to_s, 0);
- rb_define_method(rb_cTime, "inspect", time_to_s, 0);
- rb_define_method(rb_cTime, "to_a", time_to_a, 0);
-
- rb_define_method(rb_cTime, "+", time_plus, 1);
- rb_define_method(rb_cTime, "-", time_minus, 1);
-
- rb_define_method(rb_cTime, "succ", time_succ, 0);
- rb_define_method(rb_cTime, "sec", time_sec, 0);
- rb_define_method(rb_cTime, "min", time_min, 0);
- rb_define_method(rb_cTime, "hour", time_hour, 0);
- rb_define_method(rb_cTime, "mday", time_mday, 0);
- rb_define_method(rb_cTime, "day", time_mday, 0);
- rb_define_method(rb_cTime, "mon", time_mon, 0);
- rb_define_method(rb_cTime, "month", time_mon, 0);
- rb_define_method(rb_cTime, "year", time_year, 0);
- rb_define_method(rb_cTime, "wday", time_wday, 0);
- rb_define_method(rb_cTime, "yday", time_yday, 0);
- rb_define_method(rb_cTime, "isdst", time_isdst, 0);
- rb_define_method(rb_cTime, "dst?", time_isdst, 0);
- rb_define_method(rb_cTime, "zone", time_zone, 0);
- rb_define_method(rb_cTime, "gmtoff", time_utc_offset, 0);
- rb_define_method(rb_cTime, "gmt_offset", time_utc_offset, 0);
- rb_define_method(rb_cTime, "utc_offset", time_utc_offset, 0);
-
- rb_define_method(rb_cTime, "utc?", time_utc_p, 0);
- rb_define_method(rb_cTime, "gmt?", time_utc_p, 0);
-
- rb_define_method(rb_cTime, "tv_sec", time_to_i, 0);
- rb_define_method(rb_cTime, "tv_usec", time_usec, 0);
- rb_define_method(rb_cTime, "usec", time_usec, 0);
-
- rb_define_method(rb_cTime, "strftime", time_strftime, 1);
-
- /* methods for marshaling */
- rb_define_method(rb_cTime, "_dump", time_dump, -1);
- rb_define_singleton_method(rb_cTime, "_load", time_load, 1);
-#if 0
- /* Time will support marshal_dump and marshal_load in the future (1.9 maybe) */
- rb_define_method(rb_cTime, "marshal_dump", time_mdump, 0);
- rb_define_method(rb_cTime, "marshal_load", time_mload, 1);
-#endif
-}
-/**********************************************************************
- utf8.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 USE_INVALID_CODE_SCHEME
-
-#ifdef USE_INVALID_CODE_SCHEME
-/* virtual codepoint values for invalid encoding byte 0xfe and 0xff */
-#define INVALID_CODE_FE 0xfffffffe
-#define INVALID_CODE_FF 0xffffffff
-#define VALID_CODE_LIMIT 0x7fffffff
-#endif
-
-#define utf8_islead(c) ((UChar )((c) & 0xc0) != 0x80)
-
-static int EncLen_UTF8[] = {
- 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, 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, 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,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
-};
-
-static int
-utf8_mbc_enc_len(const UChar* p)
-{
- return EncLen_UTF8[*p];
-}
-
-static OnigCodePoint
-utf8_mbc_to_code(const UChar* p, const UChar* end)
-{
- int c, len;
- OnigCodePoint n;
-
- len = enc_len(ONIG_ENCODING_UTF8, p);
- c = *p++;
- if (len > 1) {
- len--;
- n = c & ((1 << (6 - len)) - 1);
- while (len--) {
- c = *p++;
- n = (n << 6) | (c & ((1 << 6) - 1));
- }
- return n;
- }
- else {
-#ifdef USE_INVALID_CODE_SCHEME
- if (c > 0xfd) {
- return ((c == 0xfe) ? INVALID_CODE_FE : INVALID_CODE_FF);
- }
-#endif
- return (OnigCodePoint )c;
- }
-}
-
-static int
-utf8_code_to_mbclen(OnigCodePoint code)
-{
- if ((code & 0xffffff80) == 0) return 1;
- else if ((code & 0xfffff800) == 0) {
- if (code <= 0xff && code >= 0xfe)
- return 1;
- return 2;
- }
- else if ((code & 0xffff0000) == 0) return 3;
- else if ((code & 0xffe00000) == 0) return 4;
- else if ((code & 0xfc000000) == 0) return 5;
- else if ((code & 0x80000000) == 0) return 6;
-#ifdef USE_INVALID_CODE_SCHEME
- else if (code == INVALID_CODE_FE) return 1;
- else if (code == INVALID_CODE_FF) return 1;
-#endif
- else
- return ONIGENCERR_TOO_BIG_WIDE_CHAR_VALUE;
-}
-
-#if 0
-static int
-utf8_code_to_mbc_first(OnigCodePoint code)
-{
- if ((code & 0xffffff80) == 0)
- return code;
- else {
- if ((code & 0xfffff800) == 0)
- return ((code>>6)& 0x1f) | 0xc0;
- else if ((code & 0xffff0000) == 0)
- return ((code>>12) & 0x0f) | 0xe0;
- else if ((code & 0xffe00000) == 0)
- return ((code>>18) & 0x07) | 0xf0;
- else if ((code & 0xfc000000) == 0)
- return ((code>>24) & 0x03) | 0xf8;
- else if ((code & 0x80000000) == 0)
- return ((code>>30) & 0x01) | 0xfc;
- else {
- return ONIGENCERR_TOO_BIG_WIDE_CHAR_VALUE;
- }
- }
-}
-#endif
-
-static int
-utf8_code_to_mbc(OnigCodePoint code, UChar *buf)
-{
-#define UTF8_TRAILS(code, shift) (UChar )((((code) >> (shift)) & 0x3f) | 0x80)
-#define UTF8_TRAIL0(code) (UChar )(((code) & 0x3f) | 0x80)
-
- if ((code & 0xffffff80) == 0) {
- *buf = (UChar )code;
- return 1;
- }
- else {
- UChar *p = buf;
-
- if ((code & 0xfffff800) == 0) {
- *p++ = (UChar )(((code>>6)& 0x1f) | 0xc0);
- }
- else if ((code & 0xffff0000) == 0) {
- *p++ = (UChar )(((code>>12) & 0x0f) | 0xe0);
- *p++ = UTF8_TRAILS(code, 6);
- }
- else if ((code & 0xffe00000) == 0) {
- *p++ = (UChar )(((code>>18) & 0x07) | 0xf0);
- *p++ = UTF8_TRAILS(code, 12);
- *p++ = UTF8_TRAILS(code, 6);
- }
- else if ((code & 0xfc000000) == 0) {
- *p++ = (UChar )(((code>>24) & 0x03) | 0xf8);
- *p++ = UTF8_TRAILS(code, 18);
- *p++ = UTF8_TRAILS(code, 12);
- *p++ = UTF8_TRAILS(code, 6);
- }
- else if ((code & 0x80000000) == 0) {
- *p++ = (UChar )(((code>>30) & 0x01) | 0xfc);
- *p++ = UTF8_TRAILS(code, 24);
- *p++ = UTF8_TRAILS(code, 18);
- *p++ = UTF8_TRAILS(code, 12);
- *p++ = UTF8_TRAILS(code, 6);
- }
-#ifdef USE_INVALID_CODE_SCHEME
- else if (code == INVALID_CODE_FE) {
- *p = 0xfe;
- return 1;
- }
- else if (code == INVALID_CODE_FF) {
- *p = 0xff;
- return 1;
- }
-#endif
- else {
- return ONIGENCERR_TOO_BIG_WIDE_CHAR_VALUE;
- }
-
- *p++ = UTF8_TRAIL0(code);
- return p - buf;
- }
-}
-
-static int
-utf8_mbc_to_normalize(OnigAmbigType flag, const UChar** pp, const UChar* end, UChar* lower)
-{
- const UChar* p = *pp;
-
- if (ONIGENC_IS_MBC_ASCII(p)) {
- if (end > p + 1 &&
- (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0 &&
- ((*p == 's' && *(p+1) == 's') ||
- ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 &&
- (*p == 'S' && *(p+1) == 'S')))) {
- *lower++ = '\303';
- *lower = '\237';
- (*pp) += 2;
- return 2;
- }
-
- if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) {
- *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p);
- }
- else {
- *lower = *p;
- }
- (*pp)++;
- return 1; /* return byte length of converted char to lower */
- }
- else {
- int len;
-
- if (*p == 195) { /* 195 == '\303' */
- int c = *(p + 1);
- if (c >= 128) {
- if (c <= (UChar )'\236' && /* upper */
- (flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0) {
- if (c != (UChar )'\227') {
- *lower++ = *p;
- *lower = (UChar )(c + 32);
- (*pp) += 2;
- return 2;
- }
- }
-#if 0
- else if (c == (UChar )'\237' &&
- (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) {
- *lower++ = '\303';
- *lower = '\237';
- (*pp) += 2;
- return 2;
- }
-#endif
- }
- }
-
- len = enc_len(ONIG_ENCODING_UTF8, 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
-utf8_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end)
-{
- const UChar* p = *pp;
-
- if (ONIGENC_IS_MBC_ASCII(p)) {
- if (end > p + 1 &&
- (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0 &&
- ((*p == 's' && *(p+1) == 's') ||
- ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 &&
- (*p == 'S' && *(p+1) == 'S')))) {
- (*pp) += 2;
- return TRUE;
- }
-
- (*pp)++;
- if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) {
- return ONIGENC_IS_ASCII_CODE_CASE_AMBIG(*p);
- }
- }
- else {
- (*pp) += enc_len(ONIG_ENCODING_UTF8, p);
-
- if (*p == 195) { /* 195 == '\303' */
- int c = *(p + 1);
- if (c >= 128) {
- if ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0) {
- if (c <= (UChar )'\236') { /* upper */
- if (c == (UChar )'\227') return FALSE;
- return TRUE;
- }
- else if (c >= (UChar )'\240' && c <= (UChar )'\276') { /* lower */
- if (c == (UChar )'\267') return FALSE;
- return TRUE;
- }
- }
- else if (c == (UChar )'\237' &&
- (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) {
- return TRUE;
- }
- }
- }
- }
-
- return FALSE;
-}
-
-
-static OnigCodePoint EmptyRange[] = { 0 };
-
-static OnigCodePoint SBAlnum[] = {
- 3,
- 0x0030, 0x0039,
- 0x0041, 0x005a,
- 0x0061, 0x007a
-};
-
-static OnigCodePoint MBAlnum[] = {
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 411,
-#else
- 6,
-#endif
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00ba, 0x00ba,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x0236
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- ,
- 0x0250, 0x02c1,
- 0x02c6, 0x02d1,
- 0x02e0, 0x02e4,
- 0x02ee, 0x02ee,
- 0x0300, 0x0357,
- 0x035d, 0x036f,
- 0x037a, 0x037a,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x03f5,
- 0x03f7, 0x03fb,
- 0x0400, 0x0481,
- 0x0483, 0x0486,
- 0x0488, 0x04ce,
- 0x04d0, 0x04f5,
- 0x04f8, 0x04f9,
- 0x0500, 0x050f,
- 0x0531, 0x0556,
- 0x0559, 0x0559,
- 0x0561, 0x0587,
- 0x0591, 0x05a1,
- 0x05a3, 0x05b9,
- 0x05bb, 0x05bd,
- 0x05bf, 0x05bf,
- 0x05c1, 0x05c2,
- 0x05c4, 0x05c4,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f2,
- 0x0610, 0x0615,
- 0x0621, 0x063a,
- 0x0640, 0x0658,
- 0x0660, 0x0669,
- 0x066e, 0x06d3,
- 0x06d5, 0x06dc,
- 0x06de, 0x06e8,
- 0x06ea, 0x06fc,
- 0x06ff, 0x06ff,
- 0x0710, 0x074a,
- 0x074d, 0x074f,
- 0x0780, 0x07b1,
- 0x0901, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0963,
- 0x0966, 0x096f,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09f1,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae3,
- 0x0ae6, 0x0aef,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b6f,
- 0x0b71, 0x0b71,
- 0x0b82, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb5,
- 0x0bb7, 0x0bb9,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0be7, 0x0bef,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df3,
- 0x0e01, 0x0e3a,
- 0x0e40, 0x0e4e,
- 0x0e50, 0x0e59,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f00,
- 0x0f18, 0x0f19,
- 0x0f20, 0x0f29,
- 0x0f35, 0x0f35,
- 0x0f37, 0x0f37,
- 0x0f39, 0x0f39,
- 0x0f3e, 0x0f47,
- 0x0f49, 0x0f6a,
- 0x0f71, 0x0f84,
- 0x0f86, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fc6, 0x0fc6,
- 0x1000, 0x1021,
- 0x1023, 0x1027,
- 0x1029, 0x102a,
- 0x102c, 0x1032,
- 0x1036, 0x1039,
- 0x1040, 0x1049,
- 0x1050, 0x1059,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10f8,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1200, 0x1206,
- 0x1208, 0x1246,
- 0x1248, 0x1248,
- 0x124a, 0x124d,
- 0x1250, 0x1256,
- 0x1258, 0x1258,
- 0x125a, 0x125d,
- 0x1260, 0x1286,
- 0x1288, 0x1288,
- 0x128a, 0x128d,
- 0x1290, 0x12ae,
- 0x12b0, 0x12b0,
- 0x12b2, 0x12b5,
- 0x12b8, 0x12be,
- 0x12c0, 0x12c0,
- 0x12c2, 0x12c5,
- 0x12c8, 0x12ce,
- 0x12d0, 0x12d6,
- 0x12d8, 0x12ee,
- 0x12f0, 0x130e,
- 0x1310, 0x1310,
- 0x1312, 0x1315,
- 0x1318, 0x131e,
- 0x1320, 0x1346,
- 0x1348, 0x135a,
- 0x1369, 0x1371,
- 0x13a0, 0x13f4,
- 0x1401, 0x166c,
- 0x166f, 0x1676,
- 0x1681, 0x169a,
- 0x16a0, 0x16ea,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1734,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17b3,
- 0x17b6, 0x17d3,
- 0x17d7, 0x17d7,
- 0x17dc, 0x17dd,
- 0x17e0, 0x17e9,
- 0x180b, 0x180d,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18a9,
- 0x1900, 0x191c,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1946, 0x196d,
- 0x1970, 0x1974,
- 0x1d00, 0x1d6b,
- 0x1e00, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x20d0, 0x20ea,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x212d,
- 0x212f, 0x2131,
- 0x2133, 0x2139,
- 0x213d, 0x213f,
- 0x2145, 0x2149,
- 0x3005, 0x3006,
- 0x302a, 0x302f,
- 0x3031, 0x3035,
- 0x303b, 0x303c,
- 0x3041, 0x3096,
- 0x3099, 0x309a,
- 0x309d, 0x309f,
- 0x30a1, 0x30fa,
- 0x30fc, 0x30ff,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x31a0, 0x31b7,
- 0x31f0, 0x31ff,
- 0x3400, 0x4db5,
- 0x4e00, 0x9fa5,
- 0xa000, 0xa48c,
- 0xac00, 0xd7a3,
- 0xf900, 0xfa2d,
- 0xfa30, 0xfa6a,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb28,
- 0xfb2a, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3d,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe23,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xff10, 0xff19,
- 0xff21, 0xff3a,
- 0xff41, 0xff5a,
- 0xff66, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10300, 0x1031e,
- 0x10330, 0x10349,
- 0x10380, 0x1039d,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x1083f,
- 0x1d165, 0x1d169,
- 0x1d16d, 0x1d172,
- 0x1d17b, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a3,
- 0x1d6a8, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7c9,
- 0x1d7ce, 0x1d7ff,
- 0x20000, 0x2a6d6,
- 0x2f800, 0x2fa1d,
- 0xe0100, 0xe01ef
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-}; /* end of MBAlnum */
-
-static OnigCodePoint SBAlpha[] = {
- 2,
- 0x0041, 0x005a,
- 0x0061, 0x007a
-};
-
-static OnigCodePoint MBAlpha[] = {
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 394,
-#else
- 6,
-#endif
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00ba, 0x00ba,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x0236
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- ,
- 0x0250, 0x02c1,
- 0x02c6, 0x02d1,
- 0x02e0, 0x02e4,
- 0x02ee, 0x02ee,
- 0x0300, 0x0357,
- 0x035d, 0x036f,
- 0x037a, 0x037a,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x03f5,
- 0x03f7, 0x03fb,
- 0x0400, 0x0481,
- 0x0483, 0x0486,
- 0x0488, 0x04ce,
- 0x04d0, 0x04f5,
- 0x04f8, 0x04f9,
- 0x0500, 0x050f,
- 0x0531, 0x0556,
- 0x0559, 0x0559,
- 0x0561, 0x0587,
- 0x0591, 0x05a1,
- 0x05a3, 0x05b9,
- 0x05bb, 0x05bd,
- 0x05bf, 0x05bf,
- 0x05c1, 0x05c2,
- 0x05c4, 0x05c4,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f2,
- 0x0610, 0x0615,
- 0x0621, 0x063a,
- 0x0640, 0x0658,
- 0x066e, 0x06d3,
- 0x06d5, 0x06dc,
- 0x06de, 0x06e8,
- 0x06ea, 0x06ef,
- 0x06fa, 0x06fc,
- 0x06ff, 0x06ff,
- 0x0710, 0x074a,
- 0x074d, 0x074f,
- 0x0780, 0x07b1,
- 0x0901, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0963,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09f0, 0x09f1,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a70, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae3,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b71, 0x0b71,
- 0x0b82, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb5,
- 0x0bb7, 0x0bb9,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df3,
- 0x0e01, 0x0e3a,
- 0x0e40, 0x0e4e,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f00,
- 0x0f18, 0x0f19,
- 0x0f35, 0x0f35,
- 0x0f37, 0x0f37,
- 0x0f39, 0x0f39,
- 0x0f3e, 0x0f47,
- 0x0f49, 0x0f6a,
- 0x0f71, 0x0f84,
- 0x0f86, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fc6, 0x0fc6,
- 0x1000, 0x1021,
- 0x1023, 0x1027,
- 0x1029, 0x102a,
- 0x102c, 0x1032,
- 0x1036, 0x1039,
- 0x1050, 0x1059,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10f8,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1200, 0x1206,
- 0x1208, 0x1246,
- 0x1248, 0x1248,
- 0x124a, 0x124d,
- 0x1250, 0x1256,
- 0x1258, 0x1258,
- 0x125a, 0x125d,
- 0x1260, 0x1286,
- 0x1288, 0x1288,
- 0x128a, 0x128d,
- 0x1290, 0x12ae,
- 0x12b0, 0x12b0,
- 0x12b2, 0x12b5,
- 0x12b8, 0x12be,
- 0x12c0, 0x12c0,
- 0x12c2, 0x12c5,
- 0x12c8, 0x12ce,
- 0x12d0, 0x12d6,
- 0x12d8, 0x12ee,
- 0x12f0, 0x130e,
- 0x1310, 0x1310,
- 0x1312, 0x1315,
- 0x1318, 0x131e,
- 0x1320, 0x1346,
- 0x1348, 0x135a,
- 0x13a0, 0x13f4,
- 0x1401, 0x166c,
- 0x166f, 0x1676,
- 0x1681, 0x169a,
- 0x16a0, 0x16ea,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1734,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17b3,
- 0x17b6, 0x17d3,
- 0x17d7, 0x17d7,
- 0x17dc, 0x17dd,
- 0x180b, 0x180d,
- 0x1820, 0x1877,
- 0x1880, 0x18a9,
- 0x1900, 0x191c,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1950, 0x196d,
- 0x1970, 0x1974,
- 0x1d00, 0x1d6b,
- 0x1e00, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x20d0, 0x20ea,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x212d,
- 0x212f, 0x2131,
- 0x2133, 0x2139,
- 0x213d, 0x213f,
- 0x2145, 0x2149,
- 0x3005, 0x3006,
- 0x302a, 0x302f,
- 0x3031, 0x3035,
- 0x303b, 0x303c,
- 0x3041, 0x3096,
- 0x3099, 0x309a,
- 0x309d, 0x309f,
- 0x30a1, 0x30fa,
- 0x30fc, 0x30ff,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x31a0, 0x31b7,
- 0x31f0, 0x31ff,
- 0x3400, 0x4db5,
- 0x4e00, 0x9fa5,
- 0xa000, 0xa48c,
- 0xac00, 0xd7a3,
- 0xf900, 0xfa2d,
- 0xfa30, 0xfa6a,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb28,
- 0xfb2a, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3d,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe23,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xff21, 0xff3a,
- 0xff41, 0xff5a,
- 0xff66, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10300, 0x1031e,
- 0x10330, 0x10349,
- 0x10380, 0x1039d,
- 0x10400, 0x1049d,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x1083f,
- 0x1d165, 0x1d169,
- 0x1d16d, 0x1d172,
- 0x1d17b, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a3,
- 0x1d6a8, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7c9,
- 0x20000, 0x2a6d6,
- 0x2f800, 0x2fa1d,
- 0xe0100, 0xe01ef
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-}; /* end of MBAlpha */
-
-static OnigCodePoint SBBlank[] = {
- 2,
- 0x0009, 0x0009,
- 0x0020, 0x0020
-};
-
-static OnigCodePoint MBBlank[] = {
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 7,
-#else
- 1,
-#endif
- 0x00a0, 0x00a0
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- ,
- 0x1680, 0x1680,
- 0x180e, 0x180e,
- 0x2000, 0x200a,
- 0x202f, 0x202f,
- 0x205f, 0x205f,
- 0x3000, 0x3000
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-}; /* end of MBBlank */
-
-static OnigCodePoint SBCntrl[] = {
- 2,
- 0x0000, 0x001f,
- 0x007f, 0x007f
-};
-
-static OnigCodePoint MBCntrl[] = {
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 18,
-#else
- 2,
-#endif
- 0x0080, 0x009f,
- 0x00ad, 0x00ad
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- ,
- 0x0600, 0x0603,
- 0x06dd, 0x06dd,
- 0x070f, 0x070f,
- 0x17b4, 0x17b5,
- 0x200b, 0x200f,
- 0x202a, 0x202e,
- 0x2060, 0x2063,
- 0x206a, 0x206f,
- 0xd800, 0xf8ff,
- 0xfeff, 0xfeff,
- 0xfff9, 0xfffb,
- 0x1d173, 0x1d17a,
- 0xe0001, 0xe0001,
- 0xe0020, 0xe007f,
- 0xf0000, 0xffffd,
- 0x100000, 0x10fffd
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-}; /* end of MBCntrl */
-
-static OnigCodePoint SBDigit[] = {
- 1,
- 0x0030, 0x0039
-};
-
-static OnigCodePoint MBDigit[] = {
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 22,
-#else
- 0
-#endif
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 0x0660, 0x0669,
- 0x06f0, 0x06f9,
- 0x0966, 0x096f,
- 0x09e6, 0x09ef,
- 0x0a66, 0x0a6f,
- 0x0ae6, 0x0aef,
- 0x0b66, 0x0b6f,
- 0x0be7, 0x0bef,
- 0x0c66, 0x0c6f,
- 0x0ce6, 0x0cef,
- 0x0d66, 0x0d6f,
- 0x0e50, 0x0e59,
- 0x0ed0, 0x0ed9,
- 0x0f20, 0x0f29,
- 0x1040, 0x1049,
- 0x1369, 0x1371,
- 0x17e0, 0x17e9,
- 0x1810, 0x1819,
- 0x1946, 0x194f,
- 0xff10, 0xff19,
- 0x104a0, 0x104a9,
- 0x1d7ce, 0x1d7ff
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-}; /* end of MBDigit */
-
-static OnigCodePoint SBGraph[] = {
- 1,
- 0x0021, 0x007e
-};
-
-static OnigCodePoint MBGraph[] = {
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 404,
-#else
- 1,
-#endif
- 0x00a1, 0x0236
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- ,
- 0x0250, 0x0357,
- 0x035d, 0x036f,
- 0x0374, 0x0375,
- 0x037a, 0x037a,
- 0x037e, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x03fb,
- 0x0400, 0x0486,
- 0x0488, 0x04ce,
- 0x04d0, 0x04f5,
- 0x04f8, 0x04f9,
- 0x0500, 0x050f,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x0591, 0x05a1,
- 0x05a3, 0x05b9,
- 0x05bb, 0x05c4,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x0603,
- 0x060c, 0x0615,
- 0x061b, 0x061b,
- 0x061f, 0x061f,
- 0x0621, 0x063a,
- 0x0640, 0x0658,
- 0x0660, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x074f,
- 0x0780, 0x07b1,
- 0x0901, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0970,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fa,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae3,
- 0x0ae6, 0x0aef,
- 0x0af1, 0x0af1,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b71,
- 0x0b82, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb5,
- 0x0bb7, 0x0bb9,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0be7, 0x0bfa,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6a,
- 0x0f71, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fbe, 0x0fcc,
- 0x0fcf, 0x0fcf,
- 0x1000, 0x1021,
- 0x1023, 0x1027,
- 0x1029, 0x102a,
- 0x102c, 0x1032,
- 0x1036, 0x1039,
- 0x1040, 0x1059,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10f8,
- 0x10fb, 0x10fb,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1200, 0x1206,
- 0x1208, 0x1246,
- 0x1248, 0x1248,
- 0x124a, 0x124d,
- 0x1250, 0x1256,
- 0x1258, 0x1258,
- 0x125a, 0x125d,
- 0x1260, 0x1286,
- 0x1288, 0x1288,
- 0x128a, 0x128d,
- 0x1290, 0x12ae,
- 0x12b0, 0x12b0,
- 0x12b2, 0x12b5,
- 0x12b8, 0x12be,
- 0x12c0, 0x12c0,
- 0x12c2, 0x12c5,
- 0x12c8, 0x12ce,
- 0x12d0, 0x12d6,
- 0x12d8, 0x12ee,
- 0x12f0, 0x130e,
- 0x1310, 0x1310,
- 0x1312, 0x1315,
- 0x1318, 0x131e,
- 0x1320, 0x1346,
- 0x1348, 0x135a,
- 0x1361, 0x137c,
- 0x13a0, 0x13f4,
- 0x1401, 0x1676,
- 0x1681, 0x169c,
- 0x16a0, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180d,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18a9,
- 0x1900, 0x191c,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1940, 0x1940,
- 0x1944, 0x196d,
- 0x1970, 0x1974,
- 0x19e0, 0x19ff,
- 0x1d00, 0x1d6b,
- 0x1e00, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fc4,
- 0x1fc6, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fdd, 0x1fef,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffe,
- 0x200b, 0x2027,
- 0x202a, 0x202e,
- 0x2030, 0x2054,
- 0x2057, 0x2057,
- 0x2060, 0x2063,
- 0x206a, 0x2071,
- 0x2074, 0x208e,
- 0x20a0, 0x20b1,
- 0x20d0, 0x20ea,
- 0x2100, 0x213b,
- 0x213d, 0x214b,
- 0x2153, 0x2183,
- 0x2190, 0x23d0,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x2617,
- 0x2619, 0x267d,
- 0x2680, 0x2691,
- 0x26a0, 0x26a1,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x2756,
- 0x2758, 0x275e,
- 0x2761, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x27d0, 0x27eb,
- 0x27f0, 0x2b0d,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3001, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x3190, 0x31b7,
- 0x31f0, 0x321e,
- 0x3220, 0x3243,
- 0x3250, 0x327d,
- 0x327f, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fa5,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xac00, 0xd7a3,
- 0xe000, 0xfa2d,
- 0xfa30, 0xfa6a,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfd,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe23,
- 0xfe30, 0xfe52,
- 0xfe54, 0xfe66,
- 0xfe68, 0xfe6b,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xfeff, 0xfeff,
- 0xff01, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0xffe0, 0xffe6,
- 0xffe8, 0xffee,
- 0xfff9, 0xfffd,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10100, 0x10102,
- 0x10107, 0x10133,
- 0x10137, 0x1013f,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10380, 0x1039d,
- 0x1039f, 0x1039f,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x1083f,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d12a, 0x1d1dd,
- 0x1d300, 0x1d356,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a3,
- 0x1d6a8, 0x1d7c9,
- 0x1d7ce, 0x1d7ff,
- 0x20000, 0x2a6d6,
- 0x2f800, 0x2fa1d,
- 0xe0001, 0xe0001,
- 0xe0020, 0xe007f,
- 0xe0100, 0xe01ef,
- 0xf0000, 0xffffd,
- 0x100000, 0x10fffd
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-}; /* end of MBGraph */
-
-static OnigCodePoint SBLower[] = {
- 1,
- 0x0061, 0x007a
-};
-
-static OnigCodePoint MBLower[] = {
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 423,
-#else
- 5,
-#endif
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00ba, 0x00ba,
- 0x00df, 0x00f6,
- 0x00f8, 0x00ff
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- ,
- 0x0101, 0x0101,
- 0x0103, 0x0103,
- 0x0105, 0x0105,
- 0x0107, 0x0107,
- 0x0109, 0x0109,
- 0x010b, 0x010b,
- 0x010d, 0x010d,
- 0x010f, 0x010f,
- 0x0111, 0x0111,
- 0x0113, 0x0113,
- 0x0115, 0x0115,
- 0x0117, 0x0117,
- 0x0119, 0x0119,
- 0x011b, 0x011b,
- 0x011d, 0x011d,
- 0x011f, 0x011f,
- 0x0121, 0x0121,
- 0x0123, 0x0123,
- 0x0125, 0x0125,
- 0x0127, 0x0127,
- 0x0129, 0x0129,
- 0x012b, 0x012b,
- 0x012d, 0x012d,
- 0x012f, 0x012f,
- 0x0131, 0x0131,
- 0x0133, 0x0133,
- 0x0135, 0x0135,
- 0x0137, 0x0138,
- 0x013a, 0x013a,
- 0x013c, 0x013c,
- 0x013e, 0x013e,
- 0x0140, 0x0140,
- 0x0142, 0x0142,
- 0x0144, 0x0144,
- 0x0146, 0x0146,
- 0x0148, 0x0149,
- 0x014b, 0x014b,
- 0x014d, 0x014d,
- 0x014f, 0x014f,
- 0x0151, 0x0151,
- 0x0153, 0x0153,
- 0x0155, 0x0155,
- 0x0157, 0x0157,
- 0x0159, 0x0159,
- 0x015b, 0x015b,
- 0x015d, 0x015d,
- 0x015f, 0x015f,
- 0x0161, 0x0161,
- 0x0163, 0x0163,
- 0x0165, 0x0165,
- 0x0167, 0x0167,
- 0x0169, 0x0169,
- 0x016b, 0x016b,
- 0x016d, 0x016d,
- 0x016f, 0x016f,
- 0x0171, 0x0171,
- 0x0173, 0x0173,
- 0x0175, 0x0175,
- 0x0177, 0x0177,
- 0x017a, 0x017a,
- 0x017c, 0x017c,
- 0x017e, 0x0180,
- 0x0183, 0x0183,
- 0x0185, 0x0185,
- 0x0188, 0x0188,
- 0x018c, 0x018d,
- 0x0192, 0x0192,
- 0x0195, 0x0195,
- 0x0199, 0x019b,
- 0x019e, 0x019e,
- 0x01a1, 0x01a1,
- 0x01a3, 0x01a3,
- 0x01a5, 0x01a5,
- 0x01a8, 0x01a8,
- 0x01aa, 0x01ab,
- 0x01ad, 0x01ad,
- 0x01b0, 0x01b0,
- 0x01b4, 0x01b4,
- 0x01b6, 0x01b6,
- 0x01b9, 0x01ba,
- 0x01bd, 0x01bf,
- 0x01c6, 0x01c6,
- 0x01c9, 0x01c9,
- 0x01cc, 0x01cc,
- 0x01ce, 0x01ce,
- 0x01d0, 0x01d0,
- 0x01d2, 0x01d2,
- 0x01d4, 0x01d4,
- 0x01d6, 0x01d6,
- 0x01d8, 0x01d8,
- 0x01da, 0x01da,
- 0x01dc, 0x01dd,
- 0x01df, 0x01df,
- 0x01e1, 0x01e1,
- 0x01e3, 0x01e3,
- 0x01e5, 0x01e5,
- 0x01e7, 0x01e7,
- 0x01e9, 0x01e9,
- 0x01eb, 0x01eb,
- 0x01ed, 0x01ed,
- 0x01ef, 0x01f0,
- 0x01f3, 0x01f3,
- 0x01f5, 0x01f5,
- 0x01f9, 0x01f9,
- 0x01fb, 0x01fb,
- 0x01fd, 0x01fd,
- 0x01ff, 0x01ff,
- 0x0201, 0x0201,
- 0x0203, 0x0203,
- 0x0205, 0x0205,
- 0x0207, 0x0207,
- 0x0209, 0x0209,
- 0x020b, 0x020b,
- 0x020d, 0x020d,
- 0x020f, 0x020f,
- 0x0211, 0x0211,
- 0x0213, 0x0213,
- 0x0215, 0x0215,
- 0x0217, 0x0217,
- 0x0219, 0x0219,
- 0x021b, 0x021b,
- 0x021d, 0x021d,
- 0x021f, 0x021f,
- 0x0221, 0x0221,
- 0x0223, 0x0223,
- 0x0225, 0x0225,
- 0x0227, 0x0227,
- 0x0229, 0x0229,
- 0x022b, 0x022b,
- 0x022d, 0x022d,
- 0x022f, 0x022f,
- 0x0231, 0x0231,
- 0x0233, 0x0236,
- 0x0250, 0x02af,
- 0x0390, 0x0390,
- 0x03ac, 0x03ce,
- 0x03d0, 0x03d1,
- 0x03d5, 0x03d7,
- 0x03d9, 0x03d9,
- 0x03db, 0x03db,
- 0x03dd, 0x03dd,
- 0x03df, 0x03df,
- 0x03e1, 0x03e1,
- 0x03e3, 0x03e3,
- 0x03e5, 0x03e5,
- 0x03e7, 0x03e7,
- 0x03e9, 0x03e9,
- 0x03eb, 0x03eb,
- 0x03ed, 0x03ed,
- 0x03ef, 0x03f3,
- 0x03f5, 0x03f5,
- 0x03f8, 0x03f8,
- 0x03fb, 0x03fb,
- 0x0430, 0x045f,
- 0x0461, 0x0461,
- 0x0463, 0x0463,
- 0x0465, 0x0465,
- 0x0467, 0x0467,
- 0x0469, 0x0469,
- 0x046b, 0x046b,
- 0x046d, 0x046d,
- 0x046f, 0x046f,
- 0x0471, 0x0471,
- 0x0473, 0x0473,
- 0x0475, 0x0475,
- 0x0477, 0x0477,
- 0x0479, 0x0479,
- 0x047b, 0x047b,
- 0x047d, 0x047d,
- 0x047f, 0x047f,
- 0x0481, 0x0481,
- 0x048b, 0x048b,
- 0x048d, 0x048d,
- 0x048f, 0x048f,
- 0x0491, 0x0491,
- 0x0493, 0x0493,
- 0x0495, 0x0495,
- 0x0497, 0x0497,
- 0x0499, 0x0499,
- 0x049b, 0x049b,
- 0x049d, 0x049d,
- 0x049f, 0x049f,
- 0x04a1, 0x04a1,
- 0x04a3, 0x04a3,
- 0x04a5, 0x04a5,
- 0x04a7, 0x04a7,
- 0x04a9, 0x04a9,
- 0x04ab, 0x04ab,
- 0x04ad, 0x04ad,
- 0x04af, 0x04af,
- 0x04b1, 0x04b1,
- 0x04b3, 0x04b3,
- 0x04b5, 0x04b5,
- 0x04b7, 0x04b7,
- 0x04b9, 0x04b9,
- 0x04bb, 0x04bb,
- 0x04bd, 0x04bd,
- 0x04bf, 0x04bf,
- 0x04c2, 0x04c2,
- 0x04c4, 0x04c4,
- 0x04c6, 0x04c6,
- 0x04c8, 0x04c8,
- 0x04ca, 0x04ca,
- 0x04cc, 0x04cc,
- 0x04ce, 0x04ce,
- 0x04d1, 0x04d1,
- 0x04d3, 0x04d3,
- 0x04d5, 0x04d5,
- 0x04d7, 0x04d7,
- 0x04d9, 0x04d9,
- 0x04db, 0x04db,
- 0x04dd, 0x04dd,
- 0x04df, 0x04df,
- 0x04e1, 0x04e1,
- 0x04e3, 0x04e3,
- 0x04e5, 0x04e5,
- 0x04e7, 0x04e7,
- 0x04e9, 0x04e9,
- 0x04eb, 0x04eb,
- 0x04ed, 0x04ed,
- 0x04ef, 0x04ef,
- 0x04f1, 0x04f1,
- 0x04f3, 0x04f3,
- 0x04f5, 0x04f5,
- 0x04f9, 0x04f9,
- 0x0501, 0x0501,
- 0x0503, 0x0503,
- 0x0505, 0x0505,
- 0x0507, 0x0507,
- 0x0509, 0x0509,
- 0x050b, 0x050b,
- 0x050d, 0x050d,
- 0x050f, 0x050f,
- 0x0561, 0x0587,
- 0x1d00, 0x1d2b,
- 0x1d62, 0x1d6b,
- 0x1e01, 0x1e01,
- 0x1e03, 0x1e03,
- 0x1e05, 0x1e05,
- 0x1e07, 0x1e07,
- 0x1e09, 0x1e09,
- 0x1e0b, 0x1e0b,
- 0x1e0d, 0x1e0d,
- 0x1e0f, 0x1e0f,
- 0x1e11, 0x1e11,
- 0x1e13, 0x1e13,
- 0x1e15, 0x1e15,
- 0x1e17, 0x1e17,
- 0x1e19, 0x1e19,
- 0x1e1b, 0x1e1b,
- 0x1e1d, 0x1e1d,
- 0x1e1f, 0x1e1f,
- 0x1e21, 0x1e21,
- 0x1e23, 0x1e23,
- 0x1e25, 0x1e25,
- 0x1e27, 0x1e27,
- 0x1e29, 0x1e29,
- 0x1e2b, 0x1e2b,
- 0x1e2d, 0x1e2d,
- 0x1e2f, 0x1e2f,
- 0x1e31, 0x1e31,
- 0x1e33, 0x1e33,
- 0x1e35, 0x1e35,
- 0x1e37, 0x1e37,
- 0x1e39, 0x1e39,
- 0x1e3b, 0x1e3b,
- 0x1e3d, 0x1e3d,
- 0x1e3f, 0x1e3f,
- 0x1e41, 0x1e41,
- 0x1e43, 0x1e43,
- 0x1e45, 0x1e45,
- 0x1e47, 0x1e47,
- 0x1e49, 0x1e49,
- 0x1e4b, 0x1e4b,
- 0x1e4d, 0x1e4d,
- 0x1e4f, 0x1e4f,
- 0x1e51, 0x1e51,
- 0x1e53, 0x1e53,
- 0x1e55, 0x1e55,
- 0x1e57, 0x1e57,
- 0x1e59, 0x1e59,
- 0x1e5b, 0x1e5b,
- 0x1e5d, 0x1e5d,
- 0x1e5f, 0x1e5f,
- 0x1e61, 0x1e61,
- 0x1e63, 0x1e63,
- 0x1e65, 0x1e65,
- 0x1e67, 0x1e67,
- 0x1e69, 0x1e69,
- 0x1e6b, 0x1e6b,
- 0x1e6d, 0x1e6d,
- 0x1e6f, 0x1e6f,
- 0x1e71, 0x1e71,
- 0x1e73, 0x1e73,
- 0x1e75, 0x1e75,
- 0x1e77, 0x1e77,
- 0x1e79, 0x1e79,
- 0x1e7b, 0x1e7b,
- 0x1e7d, 0x1e7d,
- 0x1e7f, 0x1e7f,
- 0x1e81, 0x1e81,
- 0x1e83, 0x1e83,
- 0x1e85, 0x1e85,
- 0x1e87, 0x1e87,
- 0x1e89, 0x1e89,
- 0x1e8b, 0x1e8b,
- 0x1e8d, 0x1e8d,
- 0x1e8f, 0x1e8f,
- 0x1e91, 0x1e91,
- 0x1e93, 0x1e93,
- 0x1e95, 0x1e9b,
- 0x1ea1, 0x1ea1,
- 0x1ea3, 0x1ea3,
- 0x1ea5, 0x1ea5,
- 0x1ea7, 0x1ea7,
- 0x1ea9, 0x1ea9,
- 0x1eab, 0x1eab,
- 0x1ead, 0x1ead,
- 0x1eaf, 0x1eaf,
- 0x1eb1, 0x1eb1,
- 0x1eb3, 0x1eb3,
- 0x1eb5, 0x1eb5,
- 0x1eb7, 0x1eb7,
- 0x1eb9, 0x1eb9,
- 0x1ebb, 0x1ebb,
- 0x1ebd, 0x1ebd,
- 0x1ebf, 0x1ebf,
- 0x1ec1, 0x1ec1,
- 0x1ec3, 0x1ec3,
- 0x1ec5, 0x1ec5,
- 0x1ec7, 0x1ec7,
- 0x1ec9, 0x1ec9,
- 0x1ecb, 0x1ecb,
- 0x1ecd, 0x1ecd,
- 0x1ecf, 0x1ecf,
- 0x1ed1, 0x1ed1,
- 0x1ed3, 0x1ed3,
- 0x1ed5, 0x1ed5,
- 0x1ed7, 0x1ed7,
- 0x1ed9, 0x1ed9,
- 0x1edb, 0x1edb,
- 0x1edd, 0x1edd,
- 0x1edf, 0x1edf,
- 0x1ee1, 0x1ee1,
- 0x1ee3, 0x1ee3,
- 0x1ee5, 0x1ee5,
- 0x1ee7, 0x1ee7,
- 0x1ee9, 0x1ee9,
- 0x1eeb, 0x1eeb,
- 0x1eed, 0x1eed,
- 0x1eef, 0x1eef,
- 0x1ef1, 0x1ef1,
- 0x1ef3, 0x1ef3,
- 0x1ef5, 0x1ef5,
- 0x1ef7, 0x1ef7,
- 0x1ef9, 0x1ef9,
- 0x1f00, 0x1f07,
- 0x1f10, 0x1f15,
- 0x1f20, 0x1f27,
- 0x1f30, 0x1f37,
- 0x1f40, 0x1f45,
- 0x1f50, 0x1f57,
- 0x1f60, 0x1f67,
- 0x1f70, 0x1f7d,
- 0x1f80, 0x1f87,
- 0x1f90, 0x1f97,
- 0x1fa0, 0x1fa7,
- 0x1fb0, 0x1fb4,
- 0x1fb6, 0x1fb7,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fc7,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fd7,
- 0x1fe0, 0x1fe7,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ff7,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x210a, 0x210a,
- 0x210e, 0x210f,
- 0x2113, 0x2113,
- 0x212f, 0x212f,
- 0x2134, 0x2134,
- 0x2139, 0x2139,
- 0x213d, 0x213d,
- 0x2146, 0x2149,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xff41, 0xff5a,
- 0x10428, 0x1044f,
- 0x1d41a, 0x1d433,
- 0x1d44e, 0x1d454,
- 0x1d456, 0x1d467,
- 0x1d482, 0x1d49b,
- 0x1d4b6, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d4cf,
- 0x1d4ea, 0x1d503,
- 0x1d51e, 0x1d537,
- 0x1d552, 0x1d56b,
- 0x1d586, 0x1d59f,
- 0x1d5ba, 0x1d5d3,
- 0x1d5ee, 0x1d607,
- 0x1d622, 0x1d63b,
- 0x1d656, 0x1d66f,
- 0x1d68a, 0x1d6a3,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6e1,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d71b,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d755,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d78f,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7c9
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-}; /* end of MBLower */
-
-static OnigCodePoint SBPrint[] = {
- 2,
- 0x0009, 0x000d,
- 0x0020, 0x007e
-};
-
-static OnigCodePoint MBPrint[] = {
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 403,
-#else
- 2,
-#endif
- 0x0085, 0x0085,
- 0x00a0, 0x0236
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- ,
- 0x0250, 0x0357,
- 0x035d, 0x036f,
- 0x0374, 0x0375,
- 0x037a, 0x037a,
- 0x037e, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x03fb,
- 0x0400, 0x0486,
- 0x0488, 0x04ce,
- 0x04d0, 0x04f5,
- 0x04f8, 0x04f9,
- 0x0500, 0x050f,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x0591, 0x05a1,
- 0x05a3, 0x05b9,
- 0x05bb, 0x05c4,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x0603,
- 0x060c, 0x0615,
- 0x061b, 0x061b,
- 0x061f, 0x061f,
- 0x0621, 0x063a,
- 0x0640, 0x0658,
- 0x0660, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x074f,
- 0x0780, 0x07b1,
- 0x0901, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0970,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fa,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae3,
- 0x0ae6, 0x0aef,
- 0x0af1, 0x0af1,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b71,
- 0x0b82, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb5,
- 0x0bb7, 0x0bb9,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0be7, 0x0bfa,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6a,
- 0x0f71, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fbe, 0x0fcc,
- 0x0fcf, 0x0fcf,
- 0x1000, 0x1021,
- 0x1023, 0x1027,
- 0x1029, 0x102a,
- 0x102c, 0x1032,
- 0x1036, 0x1039,
- 0x1040, 0x1059,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10f8,
- 0x10fb, 0x10fb,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1200, 0x1206,
- 0x1208, 0x1246,
- 0x1248, 0x1248,
- 0x124a, 0x124d,
- 0x1250, 0x1256,
- 0x1258, 0x1258,
- 0x125a, 0x125d,
- 0x1260, 0x1286,
- 0x1288, 0x1288,
- 0x128a, 0x128d,
- 0x1290, 0x12ae,
- 0x12b0, 0x12b0,
- 0x12b2, 0x12b5,
- 0x12b8, 0x12be,
- 0x12c0, 0x12c0,
- 0x12c2, 0x12c5,
- 0x12c8, 0x12ce,
- 0x12d0, 0x12d6,
- 0x12d8, 0x12ee,
- 0x12f0, 0x130e,
- 0x1310, 0x1310,
- 0x1312, 0x1315,
- 0x1318, 0x131e,
- 0x1320, 0x1346,
- 0x1348, 0x135a,
- 0x1361, 0x137c,
- 0x13a0, 0x13f4,
- 0x1401, 0x1676,
- 0x1680, 0x169c,
- 0x16a0, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18a9,
- 0x1900, 0x191c,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1940, 0x1940,
- 0x1944, 0x196d,
- 0x1970, 0x1974,
- 0x19e0, 0x19ff,
- 0x1d00, 0x1d6b,
- 0x1e00, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fc4,
- 0x1fc6, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fdd, 0x1fef,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffe,
- 0x2000, 0x2054,
- 0x2057, 0x2057,
- 0x205f, 0x2063,
- 0x206a, 0x2071,
- 0x2074, 0x208e,
- 0x20a0, 0x20b1,
- 0x20d0, 0x20ea,
- 0x2100, 0x213b,
- 0x213d, 0x214b,
- 0x2153, 0x2183,
- 0x2190, 0x23d0,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x2617,
- 0x2619, 0x267d,
- 0x2680, 0x2691,
- 0x26a0, 0x26a1,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x2756,
- 0x2758, 0x275e,
- 0x2761, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x27d0, 0x27eb,
- 0x27f0, 0x2b0d,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x3190, 0x31b7,
- 0x31f0, 0x321e,
- 0x3220, 0x3243,
- 0x3250, 0x327d,
- 0x327f, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fa5,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xac00, 0xd7a3,
- 0xe000, 0xfa2d,
- 0xfa30, 0xfa6a,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfd,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe23,
- 0xfe30, 0xfe52,
- 0xfe54, 0xfe66,
- 0xfe68, 0xfe6b,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xfeff, 0xfeff,
- 0xff01, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0xffe0, 0xffe6,
- 0xffe8, 0xffee,
- 0xfff9, 0xfffd,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10100, 0x10102,
- 0x10107, 0x10133,
- 0x10137, 0x1013f,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10380, 0x1039d,
- 0x1039f, 0x1039f,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x1083f,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d12a, 0x1d1dd,
- 0x1d300, 0x1d356,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a3,
- 0x1d6a8, 0x1d7c9,
- 0x1d7ce, 0x1d7ff,
- 0x20000, 0x2a6d6,
- 0x2f800, 0x2fa1d,
- 0xe0001, 0xe0001,
- 0xe0020, 0xe007f,
- 0xe0100, 0xe01ef,
- 0xf0000, 0xffffd,
- 0x100000, 0x10fffd
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-}; /* end of MBPrint */
-
-static OnigCodePoint SBPunct[] = {
- 9,
- 0x0021, 0x0023,
- 0x0025, 0x002a,
- 0x002c, 0x002f,
- 0x003a, 0x003b,
- 0x003f, 0x0040,
- 0x005b, 0x005d,
- 0x005f, 0x005f,
- 0x007b, 0x007b,
- 0x007d, 0x007d
-}; /* end of SBPunct */
-
-static OnigCodePoint MBPunct[] = {
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 77,
-#else
- 5,
-#endif
- 0x00a1, 0x00a1,
- 0x00ab, 0x00ab,
- 0x00b7, 0x00b7,
- 0x00bb, 0x00bb,
- 0x00bf, 0x00bf
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- ,
- 0x037e, 0x037e,
- 0x0387, 0x0387,
- 0x055a, 0x055f,
- 0x0589, 0x058a,
- 0x05be, 0x05be,
- 0x05c0, 0x05c0,
- 0x05c3, 0x05c3,
- 0x05f3, 0x05f4,
- 0x060c, 0x060d,
- 0x061b, 0x061b,
- 0x061f, 0x061f,
- 0x066a, 0x066d,
- 0x06d4, 0x06d4,
- 0x0700, 0x070d,
- 0x0964, 0x0965,
- 0x0970, 0x0970,
- 0x0df4, 0x0df4,
- 0x0e4f, 0x0e4f,
- 0x0e5a, 0x0e5b,
- 0x0f04, 0x0f12,
- 0x0f3a, 0x0f3d,
- 0x0f85, 0x0f85,
- 0x104a, 0x104f,
- 0x10fb, 0x10fb,
- 0x1361, 0x1368,
- 0x166d, 0x166e,
- 0x169b, 0x169c,
- 0x16eb, 0x16ed,
- 0x1735, 0x1736,
- 0x17d4, 0x17d6,
- 0x17d8, 0x17da,
- 0x1800, 0x180a,
- 0x1944, 0x1945,
- 0x2010, 0x2027,
- 0x2030, 0x2043,
- 0x2045, 0x2051,
- 0x2053, 0x2054,
- 0x2057, 0x2057,
- 0x207d, 0x207e,
- 0x208d, 0x208e,
- 0x2329, 0x232a,
- 0x23b4, 0x23b6,
- 0x2768, 0x2775,
- 0x27e6, 0x27eb,
- 0x2983, 0x2998,
- 0x29d8, 0x29db,
- 0x29fc, 0x29fd,
- 0x3001, 0x3003,
- 0x3008, 0x3011,
- 0x3014, 0x301f,
- 0x3030, 0x3030,
- 0x303d, 0x303d,
- 0x30a0, 0x30a0,
- 0x30fb, 0x30fb,
- 0xfd3e, 0xfd3f,
- 0xfe30, 0xfe52,
- 0xfe54, 0xfe61,
- 0xfe63, 0xfe63,
- 0xfe68, 0xfe68,
- 0xfe6a, 0xfe6b,
- 0xff01, 0xff03,
- 0xff05, 0xff0a,
- 0xff0c, 0xff0f,
- 0xff1a, 0xff1b,
- 0xff1f, 0xff20,
- 0xff3b, 0xff3d,
- 0xff3f, 0xff3f,
- 0xff5b, 0xff5b,
- 0xff5d, 0xff5d,
- 0xff5f, 0xff65,
- 0x10100, 0x10101,
- 0x1039f, 0x1039f
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-}; /* end of MBPunct */
-
-static OnigCodePoint SBSpace[] = {
- 2,
- 0x0009, 0x000d,
- 0x0020, 0x0020
-};
-
-static OnigCodePoint MBSpace[] = {
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 9,
-#else
- 2,
-#endif
- 0x0085, 0x0085,
- 0x00a0, 0x00a0
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- ,
- 0x1680, 0x1680,
- 0x180e, 0x180e,
- 0x2000, 0x200a,
- 0x2028, 0x2029,
- 0x202f, 0x202f,
- 0x205f, 0x205f,
- 0x3000, 0x3000
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-}; /* end of MBSpace */
-
-static OnigCodePoint SBUpper[] = {
- 1,
- 0x0041, 0x005a
-};
-
-static OnigCodePoint MBUpper[] = {
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 420,
-#else
- 2,
-#endif
- 0x00c0, 0x00d6,
- 0x00d8, 0x00de
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- ,
- 0x0100, 0x0100,
- 0x0102, 0x0102,
- 0x0104, 0x0104,
- 0x0106, 0x0106,
- 0x0108, 0x0108,
- 0x010a, 0x010a,
- 0x010c, 0x010c,
- 0x010e, 0x010e,
- 0x0110, 0x0110,
- 0x0112, 0x0112,
- 0x0114, 0x0114,
- 0x0116, 0x0116,
- 0x0118, 0x0118,
- 0x011a, 0x011a,
- 0x011c, 0x011c,
- 0x011e, 0x011e,
- 0x0120, 0x0120,
- 0x0122, 0x0122,
- 0x0124, 0x0124,
- 0x0126, 0x0126,
- 0x0128, 0x0128,
- 0x012a, 0x012a,
- 0x012c, 0x012c,
- 0x012e, 0x012e,
- 0x0130, 0x0130,
- 0x0132, 0x0132,
- 0x0134, 0x0134,
- 0x0136, 0x0136,
- 0x0139, 0x0139,
- 0x013b, 0x013b,
- 0x013d, 0x013d,
- 0x013f, 0x013f,
- 0x0141, 0x0141,
- 0x0143, 0x0143,
- 0x0145, 0x0145,
- 0x0147, 0x0147,
- 0x014a, 0x014a,
- 0x014c, 0x014c,
- 0x014e, 0x014e,
- 0x0150, 0x0150,
- 0x0152, 0x0152,
- 0x0154, 0x0154,
- 0x0156, 0x0156,
- 0x0158, 0x0158,
- 0x015a, 0x015a,
- 0x015c, 0x015c,
- 0x015e, 0x015e,
- 0x0160, 0x0160,
- 0x0162, 0x0162,
- 0x0164, 0x0164,
- 0x0166, 0x0166,
- 0x0168, 0x0168,
- 0x016a, 0x016a,
- 0x016c, 0x016c,
- 0x016e, 0x016e,
- 0x0170, 0x0170,
- 0x0172, 0x0172,
- 0x0174, 0x0174,
- 0x0176, 0x0176,
- 0x0178, 0x0179,
- 0x017b, 0x017b,
- 0x017d, 0x017d,
- 0x0181, 0x0182,
- 0x0184, 0x0184,
- 0x0186, 0x0187,
- 0x0189, 0x018b,
- 0x018e, 0x0191,
- 0x0193, 0x0194,
- 0x0196, 0x0198,
- 0x019c, 0x019d,
- 0x019f, 0x01a0,
- 0x01a2, 0x01a2,
- 0x01a4, 0x01a4,
- 0x01a6, 0x01a7,
- 0x01a9, 0x01a9,
- 0x01ac, 0x01ac,
- 0x01ae, 0x01af,
- 0x01b1, 0x01b3,
- 0x01b5, 0x01b5,
- 0x01b7, 0x01b8,
- 0x01bc, 0x01bc,
- 0x01c4, 0x01c4,
- 0x01c7, 0x01c7,
- 0x01ca, 0x01ca,
- 0x01cd, 0x01cd,
- 0x01cf, 0x01cf,
- 0x01d1, 0x01d1,
- 0x01d3, 0x01d3,
- 0x01d5, 0x01d5,
- 0x01d7, 0x01d7,
- 0x01d9, 0x01d9,
- 0x01db, 0x01db,
- 0x01de, 0x01de,
- 0x01e0, 0x01e0,
- 0x01e2, 0x01e2,
- 0x01e4, 0x01e4,
- 0x01e6, 0x01e6,
- 0x01e8, 0x01e8,
- 0x01ea, 0x01ea,
- 0x01ec, 0x01ec,
- 0x01ee, 0x01ee,
- 0x01f1, 0x01f1,
- 0x01f4, 0x01f4,
- 0x01f6, 0x01f8,
- 0x01fa, 0x01fa,
- 0x01fc, 0x01fc,
- 0x01fe, 0x01fe,
- 0x0200, 0x0200,
- 0x0202, 0x0202,
- 0x0204, 0x0204,
- 0x0206, 0x0206,
- 0x0208, 0x0208,
- 0x020a, 0x020a,
- 0x020c, 0x020c,
- 0x020e, 0x020e,
- 0x0210, 0x0210,
- 0x0212, 0x0212,
- 0x0214, 0x0214,
- 0x0216, 0x0216,
- 0x0218, 0x0218,
- 0x021a, 0x021a,
- 0x021c, 0x021c,
- 0x021e, 0x021e,
- 0x0220, 0x0220,
- 0x0222, 0x0222,
- 0x0224, 0x0224,
- 0x0226, 0x0226,
- 0x0228, 0x0228,
- 0x022a, 0x022a,
- 0x022c, 0x022c,
- 0x022e, 0x022e,
- 0x0230, 0x0230,
- 0x0232, 0x0232,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x038f,
- 0x0391, 0x03a1,
- 0x03a3, 0x03ab,
- 0x03d2, 0x03d4,
- 0x03d8, 0x03d8,
- 0x03da, 0x03da,
- 0x03dc, 0x03dc,
- 0x03de, 0x03de,
- 0x03e0, 0x03e0,
- 0x03e2, 0x03e2,
- 0x03e4, 0x03e4,
- 0x03e6, 0x03e6,
- 0x03e8, 0x03e8,
- 0x03ea, 0x03ea,
- 0x03ec, 0x03ec,
- 0x03ee, 0x03ee,
- 0x03f4, 0x03f4,
- 0x03f7, 0x03f7,
- 0x03f9, 0x03fa,
- 0x0400, 0x042f,
- 0x0460, 0x0460,
- 0x0462, 0x0462,
- 0x0464, 0x0464,
- 0x0466, 0x0466,
- 0x0468, 0x0468,
- 0x046a, 0x046a,
- 0x046c, 0x046c,
- 0x046e, 0x046e,
- 0x0470, 0x0470,
- 0x0472, 0x0472,
- 0x0474, 0x0474,
- 0x0476, 0x0476,
- 0x0478, 0x0478,
- 0x047a, 0x047a,
- 0x047c, 0x047c,
- 0x047e, 0x047e,
- 0x0480, 0x0480,
- 0x048a, 0x048a,
- 0x048c, 0x048c,
- 0x048e, 0x048e,
- 0x0490, 0x0490,
- 0x0492, 0x0492,
- 0x0494, 0x0494,
- 0x0496, 0x0496,
- 0x0498, 0x0498,
- 0x049a, 0x049a,
- 0x049c, 0x049c,
- 0x049e, 0x049e,
- 0x04a0, 0x04a0,
- 0x04a2, 0x04a2,
- 0x04a4, 0x04a4,
- 0x04a6, 0x04a6,
- 0x04a8, 0x04a8,
- 0x04aa, 0x04aa,
- 0x04ac, 0x04ac,
- 0x04ae, 0x04ae,
- 0x04b0, 0x04b0,
- 0x04b2, 0x04b2,
- 0x04b4, 0x04b4,
- 0x04b6, 0x04b6,
- 0x04b8, 0x04b8,
- 0x04ba, 0x04ba,
- 0x04bc, 0x04bc,
- 0x04be, 0x04be,
- 0x04c0, 0x04c1,
- 0x04c3, 0x04c3,
- 0x04c5, 0x04c5,
- 0x04c7, 0x04c7,
- 0x04c9, 0x04c9,
- 0x04cb, 0x04cb,
- 0x04cd, 0x04cd,
- 0x04d0, 0x04d0,
- 0x04d2, 0x04d2,
- 0x04d4, 0x04d4,
- 0x04d6, 0x04d6,
- 0x04d8, 0x04d8,
- 0x04da, 0x04da,
- 0x04dc, 0x04dc,
- 0x04de, 0x04de,
- 0x04e0, 0x04e0,
- 0x04e2, 0x04e2,
- 0x04e4, 0x04e4,
- 0x04e6, 0x04e6,
- 0x04e8, 0x04e8,
- 0x04ea, 0x04ea,
- 0x04ec, 0x04ec,
- 0x04ee, 0x04ee,
- 0x04f0, 0x04f0,
- 0x04f2, 0x04f2,
- 0x04f4, 0x04f4,
- 0x04f8, 0x04f8,
- 0x0500, 0x0500,
- 0x0502, 0x0502,
- 0x0504, 0x0504,
- 0x0506, 0x0506,
- 0x0508, 0x0508,
- 0x050a, 0x050a,
- 0x050c, 0x050c,
- 0x050e, 0x050e,
- 0x0531, 0x0556,
- 0x10a0, 0x10c5,
- 0x1e00, 0x1e00,
- 0x1e02, 0x1e02,
- 0x1e04, 0x1e04,
- 0x1e06, 0x1e06,
- 0x1e08, 0x1e08,
- 0x1e0a, 0x1e0a,
- 0x1e0c, 0x1e0c,
- 0x1e0e, 0x1e0e,
- 0x1e10, 0x1e10,
- 0x1e12, 0x1e12,
- 0x1e14, 0x1e14,
- 0x1e16, 0x1e16,
- 0x1e18, 0x1e18,
- 0x1e1a, 0x1e1a,
- 0x1e1c, 0x1e1c,
- 0x1e1e, 0x1e1e,
- 0x1e20, 0x1e20,
- 0x1e22, 0x1e22,
- 0x1e24, 0x1e24,
- 0x1e26, 0x1e26,
- 0x1e28, 0x1e28,
- 0x1e2a, 0x1e2a,
- 0x1e2c, 0x1e2c,
- 0x1e2e, 0x1e2e,
- 0x1e30, 0x1e30,
- 0x1e32, 0x1e32,
- 0x1e34, 0x1e34,
- 0x1e36, 0x1e36,
- 0x1e38, 0x1e38,
- 0x1e3a, 0x1e3a,
- 0x1e3c, 0x1e3c,
- 0x1e3e, 0x1e3e,
- 0x1e40, 0x1e40,
- 0x1e42, 0x1e42,
- 0x1e44, 0x1e44,
- 0x1e46, 0x1e46,
- 0x1e48, 0x1e48,
- 0x1e4a, 0x1e4a,
- 0x1e4c, 0x1e4c,
- 0x1e4e, 0x1e4e,
- 0x1e50, 0x1e50,
- 0x1e52, 0x1e52,
- 0x1e54, 0x1e54,
- 0x1e56, 0x1e56,
- 0x1e58, 0x1e58,
- 0x1e5a, 0x1e5a,
- 0x1e5c, 0x1e5c,
- 0x1e5e, 0x1e5e,
- 0x1e60, 0x1e60,
- 0x1e62, 0x1e62,
- 0x1e64, 0x1e64,
- 0x1e66, 0x1e66,
- 0x1e68, 0x1e68,
- 0x1e6a, 0x1e6a,
- 0x1e6c, 0x1e6c,
- 0x1e6e, 0x1e6e,
- 0x1e70, 0x1e70,
- 0x1e72, 0x1e72,
- 0x1e74, 0x1e74,
- 0x1e76, 0x1e76,
- 0x1e78, 0x1e78,
- 0x1e7a, 0x1e7a,
- 0x1e7c, 0x1e7c,
- 0x1e7e, 0x1e7e,
- 0x1e80, 0x1e80,
- 0x1e82, 0x1e82,
- 0x1e84, 0x1e84,
- 0x1e86, 0x1e86,
- 0x1e88, 0x1e88,
- 0x1e8a, 0x1e8a,
- 0x1e8c, 0x1e8c,
- 0x1e8e, 0x1e8e,
- 0x1e90, 0x1e90,
- 0x1e92, 0x1e92,
- 0x1e94, 0x1e94,
- 0x1ea0, 0x1ea0,
- 0x1ea2, 0x1ea2,
- 0x1ea4, 0x1ea4,
- 0x1ea6, 0x1ea6,
- 0x1ea8, 0x1ea8,
- 0x1eaa, 0x1eaa,
- 0x1eac, 0x1eac,
- 0x1eae, 0x1eae,
- 0x1eb0, 0x1eb0,
- 0x1eb2, 0x1eb2,
- 0x1eb4, 0x1eb4,
- 0x1eb6, 0x1eb6,
- 0x1eb8, 0x1eb8,
- 0x1eba, 0x1eba,
- 0x1ebc, 0x1ebc,
- 0x1ebe, 0x1ebe,
- 0x1ec0, 0x1ec0,
- 0x1ec2, 0x1ec2,
- 0x1ec4, 0x1ec4,
- 0x1ec6, 0x1ec6,
- 0x1ec8, 0x1ec8,
- 0x1eca, 0x1eca,
- 0x1ecc, 0x1ecc,
- 0x1ece, 0x1ece,
- 0x1ed0, 0x1ed0,
- 0x1ed2, 0x1ed2,
- 0x1ed4, 0x1ed4,
- 0x1ed6, 0x1ed6,
- 0x1ed8, 0x1ed8,
- 0x1eda, 0x1eda,
- 0x1edc, 0x1edc,
- 0x1ede, 0x1ede,
- 0x1ee0, 0x1ee0,
- 0x1ee2, 0x1ee2,
- 0x1ee4, 0x1ee4,
- 0x1ee6, 0x1ee6,
- 0x1ee8, 0x1ee8,
- 0x1eea, 0x1eea,
- 0x1eec, 0x1eec,
- 0x1eee, 0x1eee,
- 0x1ef0, 0x1ef0,
- 0x1ef2, 0x1ef2,
- 0x1ef4, 0x1ef4,
- 0x1ef6, 0x1ef6,
- 0x1ef8, 0x1ef8,
- 0x1f08, 0x1f0f,
- 0x1f18, 0x1f1d,
- 0x1f28, 0x1f2f,
- 0x1f38, 0x1f3f,
- 0x1f48, 0x1f4d,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f5f,
- 0x1f68, 0x1f6f,
- 0x1fb8, 0x1fbb,
- 0x1fc8, 0x1fcb,
- 0x1fd8, 0x1fdb,
- 0x1fe8, 0x1fec,
- 0x1ff8, 0x1ffb,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210b, 0x210d,
- 0x2110, 0x2112,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x212d,
- 0x2130, 0x2131,
- 0x2133, 0x2133,
- 0x213e, 0x213f,
- 0x2145, 0x2145,
- 0xff21, 0xff3a,
- 0x10400, 0x10427,
- 0x1d400, 0x1d419,
- 0x1d434, 0x1d44d,
- 0x1d468, 0x1d481,
- 0x1d49c, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b5,
- 0x1d4d0, 0x1d4e9,
- 0x1d504, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d538, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d56c, 0x1d585,
- 0x1d5a0, 0x1d5b9,
- 0x1d5d4, 0x1d5ed,
- 0x1d608, 0x1d621,
- 0x1d63c, 0x1d655,
- 0x1d670, 0x1d689,
- 0x1d6a8, 0x1d6c0,
- 0x1d6e2, 0x1d6fa,
- 0x1d71c, 0x1d734,
- 0x1d756, 0x1d76e,
- 0x1d790, 0x1d7a8
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-}; /* end of MBUpper */
-
-static OnigCodePoint SBXDigit[] = {
- 3,
- 0x0030, 0x0039,
- 0x0041, 0x0046,
- 0x0061, 0x0066
-};
-
-static OnigCodePoint SBASCII[] = {
- 1,
- 0x0000, 0x007f
-};
-
-static OnigCodePoint SBWord[] = {
- 4,
- 0x0030, 0x0039,
- 0x0041, 0x005a,
- 0x005f, 0x005f,
- 0x0061, 0x007a
-};
-
-static OnigCodePoint MBWord[] = {
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- 432,
-#else
- 8,
-#endif
- 0x00aa, 0x00aa,
- 0x00b2, 0x00b3,
- 0x00b5, 0x00b5,
- 0x00b9, 0x00ba,
- 0x00bc, 0x00be,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
-#ifndef USE_UNICODE_FULL_RANGE_CTYPE
- 0x00f8, 0x7fffffff
-#else /* not USE_UNICODE_FULL_RANGE_CTYPE */
- 0x00f8, 0x0236,
- 0x0250, 0x02c1,
- 0x02c6, 0x02d1,
- 0x02e0, 0x02e4,
- 0x02ee, 0x02ee,
- 0x0300, 0x0357,
- 0x035d, 0x036f,
- 0x037a, 0x037a,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x03f5,
- 0x03f7, 0x03fb,
- 0x0400, 0x0481,
- 0x0483, 0x0486,
- 0x0488, 0x04ce,
- 0x04d0, 0x04f5,
- 0x04f8, 0x04f9,
- 0x0500, 0x050f,
- 0x0531, 0x0556,
- 0x0559, 0x0559,
- 0x0561, 0x0587,
- 0x0591, 0x05a1,
- 0x05a3, 0x05b9,
- 0x05bb, 0x05bd,
- 0x05bf, 0x05bf,
- 0x05c1, 0x05c2,
- 0x05c4, 0x05c4,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f2,
- 0x0610, 0x0615,
- 0x0621, 0x063a,
- 0x0640, 0x0658,
- 0x0660, 0x0669,
- 0x066e, 0x06d3,
- 0x06d5, 0x06dc,
- 0x06de, 0x06e8,
- 0x06ea, 0x06fc,
- 0x06ff, 0x06ff,
- 0x0710, 0x074a,
- 0x074d, 0x074f,
- 0x0780, 0x07b1,
- 0x0901, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0963,
- 0x0966, 0x096f,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09f1,
- 0x09f4, 0x09f9,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae3,
- 0x0ae6, 0x0aef,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b6f,
- 0x0b71, 0x0b71,
- 0x0b82, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb5,
- 0x0bb7, 0x0bb9,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0be7, 0x0bf2,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df3,
- 0x0e01, 0x0e3a,
- 0x0e40, 0x0e4e,
- 0x0e50, 0x0e59,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f00,
- 0x0f18, 0x0f19,
- 0x0f20, 0x0f33,
- 0x0f35, 0x0f35,
- 0x0f37, 0x0f37,
- 0x0f39, 0x0f39,
- 0x0f3e, 0x0f47,
- 0x0f49, 0x0f6a,
- 0x0f71, 0x0f84,
- 0x0f86, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fc6, 0x0fc6,
- 0x1000, 0x1021,
- 0x1023, 0x1027,
- 0x1029, 0x102a,
- 0x102c, 0x1032,
- 0x1036, 0x1039,
- 0x1040, 0x1049,
- 0x1050, 0x1059,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10f8,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1200, 0x1206,
- 0x1208, 0x1246,
- 0x1248, 0x1248,
- 0x124a, 0x124d,
- 0x1250, 0x1256,
- 0x1258, 0x1258,
- 0x125a, 0x125d,
- 0x1260, 0x1286,
- 0x1288, 0x1288,
- 0x128a, 0x128d,
- 0x1290, 0x12ae,
- 0x12b0, 0x12b0,
- 0x12b2, 0x12b5,
- 0x12b8, 0x12be,
- 0x12c0, 0x12c0,
- 0x12c2, 0x12c5,
- 0x12c8, 0x12ce,
- 0x12d0, 0x12d6,
- 0x12d8, 0x12ee,
- 0x12f0, 0x130e,
- 0x1310, 0x1310,
- 0x1312, 0x1315,
- 0x1318, 0x131e,
- 0x1320, 0x1346,
- 0x1348, 0x135a,
- 0x1369, 0x137c,
- 0x13a0, 0x13f4,
- 0x1401, 0x166c,
- 0x166f, 0x1676,
- 0x1681, 0x169a,
- 0x16a0, 0x16ea,
- 0x16ee, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1734,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17b3,
- 0x17b6, 0x17d3,
- 0x17d7, 0x17d7,
- 0x17dc, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x180b, 0x180d,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18a9,
- 0x1900, 0x191c,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1946, 0x196d,
- 0x1970, 0x1974,
- 0x1d00, 0x1d6b,
- 0x1e00, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x203f, 0x2040,
- 0x2054, 0x2054,
- 0x2070, 0x2071,
- 0x2074, 0x2079,
- 0x207f, 0x2089,
- 0x20d0, 0x20ea,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x212d,
- 0x212f, 0x2131,
- 0x2133, 0x2139,
- 0x213d, 0x213f,
- 0x2145, 0x2149,
- 0x2153, 0x2183,
- 0x2460, 0x249b,
- 0x24ea, 0x24ff,
- 0x2776, 0x2793,
- 0x3005, 0x3007,
- 0x3021, 0x302f,
- 0x3031, 0x3035,
- 0x3038, 0x303c,
- 0x3041, 0x3096,
- 0x3099, 0x309a,
- 0x309d, 0x309f,
- 0x30a1, 0x30ff,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x3192, 0x3195,
- 0x31a0, 0x31b7,
- 0x31f0, 0x31ff,
- 0x3220, 0x3229,
- 0x3251, 0x325f,
- 0x3280, 0x3289,
- 0x32b1, 0x32bf,
- 0x3400, 0x4db5,
- 0x4e00, 0x9fa5,
- 0xa000, 0xa48c,
- 0xac00, 0xd7a3,
- 0xf900, 0xfa2d,
- 0xfa30, 0xfa6a,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb28,
- 0xfb2a, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3d,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe23,
- 0xfe33, 0xfe34,
- 0xfe4d, 0xfe4f,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xff10, 0xff19,
- 0xff21, 0xff3a,
- 0xff3f, 0xff3f,
- 0xff41, 0xff5a,
- 0xff65, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10107, 0x10133,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10380, 0x1039d,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x1083f,
- 0x1d165, 0x1d169,
- 0x1d16d, 0x1d172,
- 0x1d17b, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a3,
- 0x1d6a8, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7c9,
- 0x1d7ce, 0x1d7ff,
- 0x20000, 0x2a6d6,
- 0x2f800, 0x2fa1d,
- 0xe0100, 0xe01ef
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-}; /* end of MBWord */
-
-
-static int
-utf8_get_ctype_code_range(int ctype,
- OnigCodePoint* sbr[], OnigCodePoint* mbr[])
-{
-#define CR_SET(sbl,mbl) do { \
- *sbr = sbl; \
- *mbr = mbl; \
-} while (0)
-
-#define CR_SB_SET(sbl) do { \
- *sbr = sbl; \
- *mbr = EmptyRange; \
-} while (0)
-
- switch (ctype) {
- case ONIGENC_CTYPE_ALPHA:
- CR_SET(SBAlpha, MBAlpha);
- break;
- case ONIGENC_CTYPE_BLANK:
- CR_SET(SBBlank, MBBlank);
- break;
- case ONIGENC_CTYPE_CNTRL:
- CR_SET(SBCntrl, MBCntrl);
- break;
- case ONIGENC_CTYPE_DIGIT:
- CR_SET(SBDigit, MBDigit);
- break;
- case ONIGENC_CTYPE_GRAPH:
- CR_SET(SBGraph, MBGraph);
- break;
- case ONIGENC_CTYPE_LOWER:
- CR_SET(SBLower, MBLower);
- break;
- case ONIGENC_CTYPE_PRINT:
- CR_SET(SBPrint, MBPrint);
- break;
- case ONIGENC_CTYPE_PUNCT:
- CR_SET(SBPunct, MBPunct);
- break;
- case ONIGENC_CTYPE_SPACE:
- CR_SET(SBSpace, MBSpace);
- break;
- case ONIGENC_CTYPE_UPPER:
- CR_SET(SBUpper, MBUpper);
- break;
- case ONIGENC_CTYPE_XDIGIT:
- CR_SB_SET(SBXDigit);
- break;
- case ONIGENC_CTYPE_WORD:
- CR_SET(SBWord, MBWord);
- break;
- case ONIGENC_CTYPE_ASCII:
- CR_SB_SET(SBASCII);
- break;
- case ONIGENC_CTYPE_ALNUM:
- CR_SET(SBAlnum, MBAlnum);
- break;
-
- default:
- return ONIGENCERR_TYPE_BUG;
- break;
- }
-
- return 0;
-}
-
-static int
-utf8_is_code_ctype(OnigCodePoint code, unsigned int ctype)
-{
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
- OnigCodePoint *range;
-#endif
-
- if (code < 256) {
- return ONIGENC_IS_UNICODE_ISO_8859_1_CTYPE(code, ctype);
- }
-
-#ifdef USE_UNICODE_FULL_RANGE_CTYPE
-
- switch (ctype) {
- case ONIGENC_CTYPE_ALPHA:
- range = MBAlpha;
- break;
- case ONIGENC_CTYPE_BLANK:
- range = MBBlank;
- break;
- case ONIGENC_CTYPE_CNTRL:
- range = MBCntrl;
- break;
- case ONIGENC_CTYPE_DIGIT:
- range = MBDigit;
- break;
- case ONIGENC_CTYPE_GRAPH:
- range = MBGraph;
- break;
- case ONIGENC_CTYPE_LOWER:
- range = MBLower;
- break;
- case ONIGENC_CTYPE_PRINT:
- range = MBPrint;
- break;
- case ONIGENC_CTYPE_PUNCT:
- range = MBPunct;
- break;
- case ONIGENC_CTYPE_SPACE:
- range = MBSpace;
- break;
- case ONIGENC_CTYPE_UPPER:
- range = MBUpper;
- break;
- case ONIGENC_CTYPE_XDIGIT:
- return FALSE;
- break;
- case ONIGENC_CTYPE_WORD:
- range = MBWord;
- break;
- case ONIGENC_CTYPE_ASCII:
- return FALSE;
- break;
- case ONIGENC_CTYPE_ALNUM:
- range = MBAlnum;
- break;
-
- default:
- return ONIGENCERR_TYPE_BUG;
- break;
- }
-
- return onig_is_in_code_range((UChar* )range, code);
-
-#else
-
- if ((ctype & ONIGENC_CTYPE_WORD) != 0) {
-#ifdef USE_INVALID_CODE_SCHEME
- if (code <= VALID_CODE_LIMIT)
-#endif
- return TRUE;
- }
-#endif /* USE_UNICODE_FULL_RANGE_CTYPE */
-
- return FALSE;
-}
-
-static UChar*
-utf8_left_adjust_char_head(const UChar* start, const UChar* s)
-{
- const UChar *p;
-
- if (s <= start) return (UChar* )s;
- p = s;
-
- while (!utf8_islead(*p) && p > start) p--;
- return (UChar* )p;
-}
-
-OnigEncodingType OnigEncodingUTF8 = {
- utf8_mbc_enc_len,
- "UTF-8", /* name */
- 6, /* max byte length */
- 1, /* min byte length */
- (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE |
- ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE |
- ONIGENC_AMBIGUOUS_MATCH_COMPOUND),
- {
- (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,
- utf8_mbc_to_code,
- utf8_code_to_mbclen,
- utf8_code_to_mbc,
- utf8_mbc_to_normalize,
- utf8_is_mbc_ambiguous,
- onigenc_iso_8859_1_get_all_pair_ambig_codes,
- onigenc_ess_tsett_get_all_comp_ambig_codes,
- utf8_is_code_ctype,
- utf8_get_ctype_code_range,
- utf8_left_adjust_char_head,
- onigenc_always_true_is_allowed_reverse_match
-};
-/**********************************************************************
-
- util.c -
-
- $Author: matz $
- $Date: 2004/09/21 03:08:31 $
- created at: Fri Mar 10 17:22:34 JST 1995
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-
-#include <ctype.h>
-#include <stdio.h>
-#include <errno.h>
-
-#ifdef _WIN32
-#include "missing/file.h"
-#endif
-
-#include "util.h"
-#ifndef HAVE_STRING_H
-char *strchr _((char*,char));
-#endif
-
-unsigned long
-scan_oct(start, len, retlen)
- const char *start;
- int len;
- int *retlen;
-{
- register const char *s = start;
- register unsigned long retval = 0;
-
- while (len-- && *s >= '0' && *s <= '7') {
- retval <<= 3;
- retval |= *s++ - '0';
- }
- *retlen = s - start;
- return retval;
-}
-
-unsigned long
-scan_hex(start, len, retlen)
- const char *start;
- int len;
- int *retlen;
-{
- static char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
- register const char *s = start;
- register unsigned long retval = 0;
- char *tmp;
-
- while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
- retval <<= 4;
- retval |= (tmp - hexdigit) & 15;
- s++;
- }
- *retlen = s - start;
- return retval;
-}
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if defined(HAVE_FCNTL_H)
-#include <fcntl.h>
-#endif
-
-#ifndef S_ISDIR
-# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
-#endif
-
-#if defined(MSDOS) || defined(__CYGWIN32__) || defined(_WIN32)
-/*
- * Copyright (c) 1993, Intergraph Corporation
- *
- * You may distribute under the terms of either the GNU General Public
- * License or the Artistic License, as specified in the perl README file.
- *
- * Various Unix compatibility functions and NT specific functions.
- *
- * Some of this code was derived from the MSDOS port(s) and the OS/2 port.
- *
- */
-
-
-/*
- * Suffix appending for in-place editing under MS-DOS and OS/2 (and now NT!).
- *
- * Here are the rules:
- *
- * Style 0: Append the suffix exactly as standard perl would do it.
- * If the filesystem groks it, use it. (HPFS will always
- * grok it. So will NTFS. FAT will rarely accept it.)
- *
- * Style 1: The suffix begins with a '.'. The extension is replaced.
- * If the name matches the original name, use the fallback method.
- *
- * Style 2: The suffix is a single character, not a '.'. Try to add the
- * suffix to the following places, using the first one that works.
- * [1] Append to extension.
- * [2] Append to filename,
- * [3] Replace end of extension,
- * [4] Replace end of filename.
- * If the name matches the original name, use the fallback method.
- *
- * Style 3: Any other case: Ignore the suffix completely and use the
- * fallback method.
- *
- * Fallback method: Change the extension to ".$$$". If that matches the
- * original name, then change the extension to ".~~~".
- *
- * If filename is more than 1000 characters long, we die a horrible
- * death. Sorry.
- *
- * The filename restriction is a cheat so that we can use buf[] to store
- * assorted temporary goo.
- *
- * Examples, assuming style 0 failed.
- *
- * suffix = ".bak" (style 1)
- * foo.bar => foo.bak
- * foo.bak => foo.$$$ (fallback)
- * foo.$$$ => foo.~~~ (fallback)
- * makefile => makefile.bak
- *
- * suffix = "~" (style 2)
- * foo.c => foo.c~
- * foo.c~ => foo.c~~
- * foo.c~~ => foo~.c~~
- * foo~.c~~ => foo~~.c~~
- * foo~~~~~.c~~ => foo~~~~~.$$$ (fallback)
- *
- * foo.pas => foo~.pas
- * makefile => makefile.~
- * longname.fil => longname.fi~
- * longname.fi~ => longnam~.fi~
- * longnam~.fi~ => longnam~.$$$
- *
- */
-
-
-static int valid_filename(char *s);
-
-static char suffix1[] = ".$$$";
-static char suffix2[] = ".~~~";
-
-#define ext (&buf[1000])
-
-#define strEQ(s1,s2) (strcmp(s1,s2) == 0)
-
-void
-ruby_add_suffix(str, suffix)
- VALUE str;
- char *suffix;
-{
- int baselen;
- int extlen = strlen(suffix);
- char *s, *t, *p;
- long slen;
- char buf[1024];
-
- if (RSTRING(str)->len > 1000)
- rb_fatal("Cannot do inplace edit on long filename (%ld characters)",
- RSTRING(str)->len);
-
-#if defined(DJGPP) || defined(__CYGWIN32__) || defined(_WIN32)
- /* Style 0 */
- slen = RSTRING(str)->len;
- rb_str_cat(str, suffix, extlen);
-#if defined(DJGPP)
- if (_USE_LFN) return;
-#else
- if (valid_filename(RSTRING(str)->ptr)) return;
-#endif
-
- /* Fooey, style 0 failed. Fix str before continuing. */
- RSTRING(str)->ptr[RSTRING(str)->len = slen] = '\0';
-#endif
-
- slen = extlen;
- t = buf; baselen = 0; s = RSTRING(str)->ptr;
- while ((*t = *s) && *s != '.') {
- baselen++;
- if (*s == '\\' || *s == '/') baselen = 0;
- s++; t++;
- }
- p = t;
-
- t = ext; extlen = 0;
- while (*t++ = *s++) extlen++;
- if (extlen == 0) { ext[0] = '.'; ext[1] = 0; extlen++; }
-
- if (*suffix == '.') { /* Style 1 */
- if (strEQ(ext, suffix)) goto fallback;
- strcpy(p, suffix);
- }
- else if (suffix[1] == '\0') { /* Style 2 */
- if (extlen < 4) {
- ext[extlen] = *suffix;
- ext[++extlen] = '\0';
- }
- else if (baselen < 8) {
- *p++ = *suffix;
- }
- else if (ext[3] != *suffix) {
- ext[3] = *suffix;
- }
- else if (buf[7] != *suffix) {
- buf[7] = *suffix;
- }
- else goto fallback;
- strcpy(p, ext);
- }
- else { /* Style 3: Panic */
-fallback:
- (void)memcpy(p, strEQ(ext, suffix1) ? suffix2 : suffix1, 5);
- }
- rb_str_resize(str, strlen(buf));
- memcpy(RSTRING(str)->ptr, buf, RSTRING(str)->len);
-}
-
-#if defined(__CYGWIN32__) || defined(_WIN32)
-static int
-valid_filename(char *s)
-{
- int fd;
-
- /*
- // if the file exists, then it's a valid filename!
- */
-
- if (_access(s, 0) == 0) {
- return 1;
- }
-
- /*
- // It doesn't exist, so see if we can open it.
- */
-
- if ((fd = _open(s, O_CREAT, 0666)) >= 0) {
- _close(fd);
- _unlink(s); /* don't leave it laying around */
- return 1;
- }
- return 0;
-}
-#endif
-#endif
-
-#if defined __DJGPP__
-
-#include <dpmi.h>
-
-static char dbcs_table[256];
-
-int
-make_dbcs_table()
-{
- __dpmi_regs r;
- struct {
- unsigned char start;
- unsigned char end;
- } vec;
- int offset;
-
- memset(&r, 0, sizeof(r));
- r.x.ax = 0x6300;
- __dpmi_int(0x21, &r);
- offset = r.x.ds * 16 + r.x.si;
-
- for (;;) {
- int i;
- dosmemget(offset, sizeof vec, &vec);
- if (!vec.start && !vec.end)
- break;
- for (i = vec.start; i <= vec.end; i++)
- dbcs_table[i] = 1;
- offset += 2;
- }
-}
-
-int
-mblen(const char *s, size_t n)
-{
- static int need_init = 1;
- if (need_init) {
- make_dbcs_table();
- need_init = 0;
- }
- if (s) {
- if (n == 0 || *s == 0)
- return 0;
- else if (!s[1])
- return 1;
- return dbcs_table[(unsigned char)*s] + 1;
- }
- else
- return 1;
-}
-
-struct PathList {
- struct PathList *next;
- char *path;
-};
-
-struct PathInfo {
- struct PathList *head;
- int count;
-};
-
-static void
-push_element(const char *path, VALUE vinfo)
-{
- struct PathList *p;
- struct PathInfo *info = (struct PathInfo *)vinfo;
-
- p = ALLOC(struct PathList);
- MEMZERO(p, struct PathList, 1);
- p->path = ruby_strdup(path);
- p->next = info->head;
- info->head = p;
- info->count++;
-}
-
-#include <dirent.h>
-int __opendir_flags = __OPENDIR_PRESERVE_CASE;
-
-char **
-__crt0_glob_function(char *path)
-{
- int len = strlen(path);
- int i;
- char **rv;
- char path_buffer[PATH_MAX];
- char *buf = path_buffer;
- char *p;
- struct PathInfo info;
- struct PathList *plist;
-
- if (PATH_MAX <= len)
- buf = ruby_xmalloc(len + 1);
-
- strncpy(buf, path, len);
- buf[len] = '\0';
-
- for (p = buf; *p; p += mblen(p, RUBY_MBCHAR_MAXSIZE))
- if (*p == '\\')
- *p = '/';
-
- info.count = 0;
- info.head = 0;
-
- rb_glob(buf, push_element, (VALUE)&info);
-
- if (buf != path_buffer)
- ruby_xfree(buf);
-
- if (info.count == 0)
- return 0;
-
- rv = ruby_xmalloc((info.count + 1) * sizeof (char *));
-
- plist = info.head;
- i = 0;
- while (plist) {
- struct PathList *cur;
- rv[i] = plist->path;
- cur = plist;
- plist = plist->next;
- ruby_xfree(cur);
- i++;
- }
- rv[i] = 0;
- return rv;
-}
-
-#endif
-
-/* mm.c */
-
-#define A ((int*)a)
-#define B ((int*)b)
-#define C ((int*)c)
-#define D ((int*)d)
-
-#define mmprepare(base, size) do {\
- if (((long)base & (0x3)) == 0)\
- if (size >= 16) mmkind = 1;\
- else mmkind = 0;\
- else mmkind = -1;\
- high = (size & (~0xf));\
- low = (size & 0x0c);\
-} while (0)\
-
-#define mmarg mmkind, size, high, low
-
-static void mmswap_(a, b, mmarg)
- register char *a, *b;
- int mmarg;
-{
- register int s;
- if (a == b) return;
- if (mmkind >= 0) {
- if (mmkind > 0) {
- register char *t = a + high;
- do {
- s = A[0]; A[0] = B[0]; B[0] = s;
- s = A[1]; A[1] = B[1]; B[1] = s;
- s = A[2]; A[2] = B[2]; B[2] = s;
- s = A[3]; A[3] = B[3]; B[3] = s; a += 16; b += 16;
- } while (a < t);
- }
- if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
- if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = s;
- if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = s;}}}
- }
- else {
- register char *t = a + size;
- do {s = *a; *a++ = *b; *b++ = s;} while (a < t);
- }
-}
-#define mmswap(a,b) mmswap_((a),(b),mmarg)
-
-static void mmrot3_(a, b, c, mmarg)
- register char *a, *b, *c;
- int mmarg;
-{
- register int s;
- if (mmkind >= 0) {
- if (mmkind > 0) {
- register char *t = a + high;
- do {
- s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
- s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
- s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;
- s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s; a += 16; b += 16; c += 16;
- } while (a < t);
- }
- if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
- if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
- if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}}}
- }
- else {
- register char *t = a + size;
- do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;} while (a < t);
- }
-}
-#define mmrot3(a,b,c) mmrot3_((a),(b),(c),mmarg)
-
-/* qs6.c */
-/*****************************************************/
-/* */
-/* qs6 (Quick sort function) */
-/* */
-/* by Tomoyuki Kawamura 1995.4.21 */
-/* kawamura@tokuyama.ac.jp */
-/*****************************************************/
-
-typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */
-#define PUSH(ll,rr) do { top->LL = (ll); top->RR = (rr); ++top; } while (0) /* Push L,l,R,r */
-#define POP(ll,rr) do { --top; ll = top->LL; rr = top->RR; } while (0) /* Pop L,l,R,r */
-
-#define med3(a,b,c) ((*cmp)(a,b,d)<0 ? \
- ((*cmp)(b,c,d)<0 ? b : ((*cmp)(a,c,d)<0 ? c : a)) : \
- ((*cmp)(b,c,d)>0 ? b : ((*cmp)(a,c,d)<0 ? a : c)))
-
-void ruby_qsort (base, nel, size, cmp, d)
- void* base;
- const int nel;
- const int size;
- int (*cmp)();
- void *d;
-{
- register char *l, *r, *m; /* l,r:left,right group m:median point */
- register int t, eq_l, eq_r; /* eq_l: all items in left group are equal to S */
- char *L = base; /* left end of curren region */
- char *R = (char*)base + size*(nel-1); /* right end of current region */
- int chklim = 63; /* threshold of ordering element check */
- stack_node stack[32], *top = stack; /* 32 is enough for 32bit CPU */
- int mmkind, high, low;
-
- if (nel <= 1) return; /* need not to sort */
- mmprepare(base, size);
- goto start;
-
- nxt:
- if (stack == top) return; /* return if stack is empty */
- POP(L,R);
-
- for (;;) {
- start:
- if (L + size == R) { /* 2 elements */
- if ((*cmp)(L,R,d) > 0) mmswap(L,R); goto nxt;
- }
-
- l = L; r = R;
- t = (r - l + size) / size; /* number of elements */
- m = l + size * (t >> 1); /* calculate median value */
-
- if (t >= 60) {
- register char *m1;
- register char *m3;
- if (t >= 200) {
- t = size*(t>>3); /* number of bytes in splitting 8 */
- {
- register char *p1 = l + t;
- register char *p2 = p1 + t;
- register char *p3 = p2 + t;
- m1 = med3(p1, p2, p3);
- p1 = m + t;
- p2 = p1 + t;
- p3 = p2 + t;
- m3 = med3(p1, p2, p3);
- }
- }
- else {
- t = size*(t>>2); /* number of bytes in splitting 4 */
- m1 = l + t;
- m3 = m + t;
- }
- m = med3(m1, m, m3);
- }
-
- if ((t = (*cmp)(l,m,d)) < 0) { /*3-5-?*/
- if ((t = (*cmp)(m,r,d)) < 0) { /*3-5-7*/
- if (chklim && nel >= chklim) { /* check if already ascending order */
- char *p;
- chklim = 0;
- for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) > 0) goto fail;
- goto nxt;
- }
- fail: goto loopA; /*3-5-7*/
- }
- if (t > 0) {
- if ((*cmp)(l,r,d) <= 0) {mmswap(m,r); goto loopA;} /*3-5-4*/
- mmrot3(r,m,l); goto loopA; /*3-5-2*/
- }
- goto loopB; /*3-5-5*/
- }
-
- if (t > 0) { /*7-5-?*/
- if ((t = (*cmp)(m,r,d)) > 0) { /*7-5-3*/
- if (chklim && nel >= chklim) { /* check if already ascending order */
- char *p;
- chklim = 0;
- for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) < 0) goto fail2;
- while (l<r) {mmswap(l,r); l+=size; r-=size;} /* reverse region */
- goto nxt;
- }
- fail2: mmswap(l,r); goto loopA; /*7-5-3*/
- }
- if (t < 0) {
- if ((*cmp)(l,r,d) <= 0) {mmswap(l,m); goto loopB;} /*7-5-8*/
- mmrot3(l,m,r); goto loopA; /*7-5-6*/
- }
- mmswap(l,r); goto loopA; /*7-5-5*/
- }
-
- if ((t = (*cmp)(m,r,d)) < 0) {goto loopA;} /*5-5-7*/
- if (t > 0) {mmswap(l,r); goto loopB;} /*5-5-3*/
-
- /* determining splitting type in case 5-5-5 */ /*5-5-5*/
- for (;;) {
- if ((l += size) == r) goto nxt; /*5-5-5*/
- if (l == m) continue;
- if ((t = (*cmp)(l,m,d)) > 0) {mmswap(l,r); l = L; goto loopA;}/*575-5*/
- if (t < 0) {mmswap(L,l); l = L; goto loopB;} /*535-5*/
- }
-
- loopA: eq_l = 1; eq_r = 1; /* splitting type A */ /* left <= median < right */
- for (;;) {
- for (;;) {
- if ((l += size) == r)
- {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
- if (l == m) continue;
- if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
- if (t < 0) eq_l = 0;
- }
- for (;;) {
- if (l == (r -= size))
- {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
- if (r == m) {m = l; break;}
- if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
- if (t == 0) break;
- }
- mmswap(l,r); /* swap left and right */
- }
-
- loopB: eq_l = 1; eq_r = 1; /* splitting type B */ /* left < median <= right */
- for (;;) {
- for (;;) {
- if (l == (r -= size))
- {r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
- if (r == m) continue;
- if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
- if (t > 0) eq_r = 0;
- }
- for (;;) {
- if ((l += size) == r)
- {r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
- if (l == m) {m = r; break;}
- if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
- if (t == 0) break;
- }
- mmswap(l,r); /* swap left and right */
- }
-
- fin:
- if (eq_l == 0) /* need to sort left side */
- if (eq_r == 0) /* need to sort right side */
- if (l-L < R-r) {PUSH(r,R); R = l;} /* sort left side first */
- else {PUSH(L,l); L = r;} /* sort right side first */
- else R = l; /* need to sort left side only */
- else if (eq_r == 0) L = r; /* need to sort right side only */
- else goto nxt; /* need not to sort both sides */
- }
-}
-
-char *
-ruby_strdup(str)
- const char *str;
-{
- char *tmp;
- int len = strlen(str) + 1;
-
- tmp = xmalloc(len);
- memcpy(tmp, str, len);
-
- return tmp;
-}
-
-char *
-ruby_getcwd()
-{
-#ifdef HAVE_GETCWD
- int size = 200;
- char *buf = xmalloc(size);
-
- while (!getcwd(buf, size)) {
- if (errno != ERANGE) {
- free(buf);
- rb_sys_fail("getcwd");
- }
- size *= 2;
- buf = xrealloc(buf, size);
- }
-#else
-# ifndef PATH_MAX
-# define PATH_MAX 8192
-# endif
- char *buf = xmalloc(PATH_MAX+1);
-
- if (!getwd(buf)) {
- free(buf);
- rb_sys_fail("getwd");
- }
-#endif
- return buf;
-}
-
-/* copyright notice for strtod implementation --
- *
- * Copyright (c) 1988-1993 The Regents of the University of California.
- * Copyright (c) 1994 Sun Microsystems, Inc.
- *
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- *
- */
-
-#define TRUE 1
-#define FALSE 0
-
-static int MDMINEXPT = -323;
-static int MDMAXEXPT = 309;
-static double powersOf10[] = { /* Table giving binary powers of 10. Entry */
- 10.0, /* is 10^2^i. Used to convert decimal */
- 100.0, /* exponents into floating-point numbers. */
- 1.0e4,
- 1.0e8,
- 1.0e16,
- 1.0e32,
- 1.0e64,
- 1.0e128,
- 1.0e256
-};
-
-/*
- *----------------------------------------------------------------------
- *
- * strtod --
- *
- * This procedure converts a floating-point number from an ASCII
- * decimal representation to internal double-precision format.
- *
- * Results:
- * The return value is the double-precision floating-point
- * representation of the characters in string. If endPtr isn't
- * NULL, then *endPtr is filled in with the address of the
- * next character after the last one that was part of the
- * floating-point number.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-double
-ruby_strtod(string, endPtr)
- const char *string; /* A decimal ASCII floating-point number,
- * optionally preceded by white space.
- * Must have form "-I.FE-X", where I is the
- * integer part of the mantissa, F is the
- * fractional part of the mantissa, and X
- * is the exponent. Either of the signs
- * may be "+", "-", or omitted. Either I
- * or F may be omitted, but both cannot be
- * ommitted at once. The decimal
- * point isn't necessary unless F is present.
- * The "E" may actually be an "e". E and X
- * may both be omitted (but not just one).
- */
- char **endPtr; /* If non-NULL, store terminating character's
- * address here. */
-{
- int sign, expSign = FALSE;
- double fraction, dblExp, *d;
- register const char *p;
- register int c;
- int exp = 0; /* Exponent read from "EX" field. */
- int fracExp = 0; /* Exponent that derives from the fractional
- * part. Under normal circumstatnces, it is
- * the negative of the number of digits in F.
- * However, if I is very long, the last digits
- * of I get dropped (otherwise a long I with a
- * large negative exponent could cause an
- * unnecessary overflow on I alone). In this
- * case, fracExp is incremented one for each
- * dropped digit. */
- int mantSize = 0; /* Number of digits in mantissa. */
- int hasPoint = FALSE; /* Decimal point exists. */
- int hasDigit = FALSE; /* I or F exists. */
- const char *pMant; /* Temporarily holds location of mantissa
- * in string. */
- const char *pExp; /* Temporarily holds location of exponent
- * in string. */
-
- /*
- * Strip off leading blanks and check for a sign.
- */
-
- errno = 0;
- p = string;
- while (ISSPACE(*p)) {
- p += 1;
- }
- if (*p == '-') {
- sign = TRUE;
- p += 1;
- }
- else {
- if (*p == '+') {
- p += 1;
- }
- sign = FALSE;
- }
-
- /*
- * Count the number of digits in the mantissa
- * and also locate the decimal point.
- */
-
- for ( ; c = *p; p += 1) {
- if (!ISDIGIT(c)) {
- if (c != '.' || hasPoint) {
- break;
- }
- hasPoint = TRUE;
- }
- else {
- if (hasPoint) { /* already in fractional part */
- fracExp -= 1;
- }
- if (mantSize) { /* already in mantissa */
- mantSize += 1;
- }
- else if (c != '0') { /* have entered mantissa */
- mantSize += 1;
- pMant = p;
- }
- hasDigit = TRUE;
- }
- }
-
- /*
- * Now suck up the digits in the mantissa. Use two integers to
- * collect 9 digits each (this is faster than using floating-point).
- * If the mantissa has more than 18 digits, ignore the extras, since
- * they can't affect the value anyway.
- */
-
- pExp = p;
- if (mantSize) {
- p = pMant;
- }
- if (mantSize > 18) {
- fracExp += (mantSize - 18);
- mantSize = 18;
- }
- if (!hasDigit) {
- fraction = 0.0;
- p = string;
- }
- else {
- int frac1, frac2;
- frac1 = 0;
- for ( ; mantSize > 9; mantSize -= 1) {
- c = *p;
- p += 1;
- if (c == '.') {
- c = *p;
- p += 1;
- }
- frac1 = 10*frac1 + (c - '0');
- }
- frac2 = 0;
- for (; mantSize > 0; mantSize -= 1) {
- c = *p;
- p += 1;
- if (c == '.') {
- c = *p;
- p += 1;
- }
- frac2 = 10*frac2 + (c - '0');
- }
-
- /*
- * Skim off the exponent.
- */
-
- p = pExp;
- if ((*p == 'E') || (*p == 'e')) {
- p += 1;
- if (*p == '-') {
- expSign = TRUE;
- p += 1;
- }
- else {
- if (*p == '+') {
- p += 1;
- }
- expSign = FALSE;
- }
- while (ISDIGIT(*p)) {
- exp = exp * 10 + (*p - '0');
- p += 1;
- }
- }
- if (expSign) {
- exp = fracExp - exp;
- }
- else {
- exp = fracExp + exp;
- }
-
- /*
- * Generate a floating-point number that represents the exponent.
- * Do this by processing the exponent one bit at a time to combine
- * many powers of 2 of 10. Then combine the exponent with the
- * fraction.
- */
-
- if (exp >= MDMAXEXPT - 18) {
- exp = MDMAXEXPT;
- errno = ERANGE;
- }
- else if (exp < MDMINEXPT + 18) {
- exp = MDMINEXPT;
- errno = ERANGE;
- }
- fracExp = exp;
- exp += 9;
- if (exp < 0) {
- expSign = TRUE;
- exp = -exp;
- }
- else {
- expSign = FALSE;
- }
- dblExp = 1.0;
- for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
- if (exp & 01) {
- dblExp *= *d;
- }
- }
- if (expSign) {
- fraction = frac1 / dblExp;
- }
- else {
- fraction = frac1 * dblExp;
- }
- exp = fracExp;
- if (exp < 0) {
- expSign = TRUE;
- exp = -exp;
- }
- else {
- expSign = FALSE;
- }
- dblExp = 1.0;
- for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
- if (exp & 01) {
- dblExp *= *d;
- }
- }
- if (expSign) {
- fraction += frac2 / dblExp;
- }
- else {
- fraction += frac2 * dblExp;
- }
- }
-
- if (endPtr != NULL) {
- *endPtr = (char *) p;
- }
-
- if (sign) {
- return -fraction;
- }
- return fraction;
-}
-/**********************************************************************
-
- variable.c -
-
- $Author: matz $
- $Date: 2005/03/04 06:47:41 $
- created at: Tue Apr 19 23:55:15 JST 1994
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
-#include "ruby.h"
-#include "env.h"
-#include "node.h"
-#include "st.h"
-#include "util.h"
-
-static st_table *rb_global_tbl;
-st_table *rb_class_tbl;
-static ID autoload, classpath, tmp_classpath;
-
-void
-Init_var_tables()
-{
- rb_global_tbl = st_init_numtable();
- rb_class_tbl = st_init_numtable();
- autoload = rb_intern("__autoload__");
- classpath = rb_intern("__classpath__");
- tmp_classpath = rb_intern("__tmp_classpath__");
-}
-
-struct fc_result {
- ID name;
- VALUE klass;
- VALUE path;
- VALUE track;
- struct fc_result *prev;
-};
-
-static VALUE
-fc_path(fc, name)
- struct fc_result *fc;
- ID name;
-{
- VALUE path, tmp;
-
- path = rb_str_new2(rb_id2name(name));
- while (fc) {
- if (fc->track == rb_cObject) break;
- if (ROBJECT(fc->track)->iv_tbl &&
- st_lookup(ROBJECT(fc->track)->iv_tbl, classpath, &tmp)) {
- tmp = rb_str_dup(tmp);
- rb_str_cat2(tmp, "::");
- rb_str_append(tmp, path);
-
- return tmp;
- }
- tmp = rb_str_new2(rb_id2name(fc->name));
- rb_str_cat2(tmp, "::");
- rb_str_append(tmp, path);
- path = tmp;
- fc = fc->prev;
- }
- return path;
-}
-
-static int
-fc_i(key, value, res)
- ID key;
- VALUE value;
- struct fc_result *res;
-{
- if (!rb_is_const_id(key)) return ST_CONTINUE;
-
- if (value == res->klass) {
- res->path = fc_path(res, key);
- return ST_STOP;
- }
- switch (TYPE(value)) {
- case T_MODULE:
- case T_CLASS:
- if (!RCLASS(value)->iv_tbl) return ST_CONTINUE;
- else {
- struct fc_result arg;
- struct fc_result *list;
-
- list = res;
- while (list) {
- if (list->track == value) return ST_CONTINUE;
- list = list->prev;
- }
-
- arg.name = key;
- arg.path = 0;
- arg.klass = res->klass;
- arg.track = value;
- arg.prev = res;
- st_foreach(RCLASS(value)->iv_tbl, fc_i, (st_data_t)&arg);
- if (arg.path) {
- res->path = arg.path;
- return ST_STOP;
- }
- }
- break;
-
- default:
- break;
- }
- return ST_CONTINUE;
-}
-
-static VALUE
-find_class_path(klass)
- VALUE klass;
-{
- struct fc_result arg;
-
- arg.name = 0;
- arg.path = 0;
- arg.klass = klass;
- arg.track = rb_cObject;
- arg.prev = 0;
- if (RCLASS(rb_cObject)->iv_tbl) {
- st_foreach_safe(RCLASS(rb_cObject)->iv_tbl, fc_i, (st_data_t)&arg);
- }
- if (arg.path == 0) {
- st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg);
- }
- if (arg.path) {
- if (!ROBJECT(klass)->iv_tbl) {
- ROBJECT(klass)->iv_tbl = st_init_numtable();
- }
- st_insert(ROBJECT(klass)->iv_tbl, classpath, arg.path);
- st_delete(RCLASS(klass)->iv_tbl, &tmp_classpath, 0);
- return arg.path;
- }
- return Qnil;
-}
-
-static VALUE
-classname(klass)
- VALUE klass;
-{
- VALUE path = Qnil;
-
- if (!klass) klass = rb_cObject;
- if (ROBJECT(klass)->iv_tbl) {
- if (!st_lookup(ROBJECT(klass)->iv_tbl, classpath, &path)) {
- ID classid = rb_intern("__classid__");
-
- if (!st_lookup(ROBJECT(klass)->iv_tbl, classid, &path)) {
- return find_class_path(klass);
- }
- path = rb_str_new2(rb_id2name(SYM2ID(path)));
- st_insert(ROBJECT(klass)->iv_tbl, classpath, path);
- st_delete(RCLASS(klass)->iv_tbl, (st_data_t*)&classid, 0);
- }
- if (TYPE(path) != T_STRING) {
- rb_bug("class path is not set properly");
- }
- return path;
- }
- return find_class_path(klass);
-}
-
-/*
- * call-seq:
- * mod.name => string
- *
- * Returns the name of the module <i>mod</i>.
- */
-
-VALUE
-rb_mod_name(mod)
- VALUE mod;
-{
- VALUE path = classname(mod);
-
- if (!NIL_P(path)) return rb_str_dup(path);
- return rb_str_new(0,0);
-}
-
-VALUE
-rb_class_path(klass)
- VALUE klass;
-{
- VALUE path = classname(klass);
-
- if (!NIL_P(path)) return path;
- if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl,
- tmp_classpath, &path)) {
- return path;
- }
- else {
- char *s = "Class";
-
- if (TYPE(klass) == T_MODULE) {
- if (rb_obj_class(klass) == rb_cModule) {
- s = "Module";
- }
- else {
- s = rb_class2name(RBASIC(klass)->klass);
- }
- }
- path = rb_str_new(0, 2 + strlen(s) + 3 + 2 * SIZEOF_LONG + 1);
- sprintf(RSTRING(path)->ptr, "#<%s:0x%lx>", s, klass);
- RSTRING(path)->len = strlen(RSTRING(path)->ptr);
- rb_ivar_set(klass, tmp_classpath, path);
-
- return path;
- }
-}
-
-void
-rb_set_class_path(klass, under, name)
- VALUE klass, under;
- const char *name;
-{
- VALUE str;
-
- if (under == rb_cObject) {
- str = rb_str_new2(name);
- }
- else {
- str = rb_str_dup(rb_class_path(under));
- rb_str_cat2(str, "::");
- rb_str_cat2(str, name);
- }
- rb_ivar_set(klass, classpath, str);
-}
-
-VALUE
-rb_path2class(path)
- const char *path;
-{
- const char *pbeg, *p;
- ID id;
- VALUE c = rb_cObject;
-
- if (path[0] == '#') {
- rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path);
- }
- pbeg = p = path;
- while (*p) {
- VALUE str;
-
- while (*p && *p != ':') p++;
- str = rb_str_new(pbeg, p-pbeg);
- id = rb_intern(RSTRING(str)->ptr);
- if (p[0] == ':') {
- if (p[1] != ':') goto undefined_class;
- p += 2;
- pbeg = p;
- }
- if (!rb_const_defined(c, id)) {
- undefined_class:
- rb_raise(rb_eArgError, "undefined class/module %.*s", p-path, path);
- }
- c = rb_const_get_at(c, id);
- switch (TYPE(c)) {
- case T_MODULE:
- case T_CLASS:
- break;
- default:
- rb_raise(rb_eTypeError, "%s does not refer class/module", path);
- }
- }
-
- return c;
-}
-
-void
-rb_name_class(klass, id)
- VALUE klass;
- ID id;
-{
- rb_iv_set(klass, "__classid__", ID2SYM(id));
-}
-
-VALUE
-rb_class_name(klass)
- VALUE klass;
-{
- return rb_class_path(rb_class_real(klass));
-}
-
-char *
-rb_class2name(klass)
- VALUE klass;
-{
- return RSTRING(rb_class_name(klass))->ptr;
-}
-
-char *
-rb_obj_classname(obj)
- VALUE obj;
-{
- return rb_class2name(CLASS_OF(obj));
-}
-
-struct trace_var {
- int removed;
- void (*func)();
- VALUE data;
- struct trace_var *next;
-};
-
-struct global_variable {
- int counter;
- void *data;
- VALUE (*getter)();
- void (*setter)();
- void (*marker)();
- int block_trace;
- struct trace_var *trace;
-};
-
-struct global_entry {
- struct global_variable *var;
- ID id;
-};
-
-static VALUE undef_getter();
-static void undef_setter();
-static void undef_marker();
-
-static VALUE val_getter();
-static void val_setter();
-static void val_marker();
-
-static VALUE var_getter();
-static void var_setter();
-static void var_marker();
-
-struct global_entry*
-rb_global_entry(id)
- ID id;
-{
- struct global_entry *entry;
-
- if (!st_lookup(rb_global_tbl, id, (st_data_t *)&entry)) {
- struct global_variable *var;
- entry = ALLOC(struct global_entry);
- var = ALLOC(struct global_variable);
- entry->id = id;
- entry->var = var;
- var->counter = 1;
- var->data = 0;
- var->getter = undef_getter;
- var->setter = undef_setter;
- var->marker = undef_marker;
-
- var->block_trace = 0;
- var->trace = 0;
- st_add_direct(rb_global_tbl, id, (st_data_t)entry);
- }
- return entry;
-}
-
-static VALUE
-undef_getter(id)
- ID id;
-{
- rb_warning("global variable `%s' not initialized", rb_id2name(id));
-
- return Qnil;
-}
-
-static void
-undef_setter(val, id, data, var)
- VALUE val;
- ID id;
- void *data;
- struct global_variable *var;
-{
- var->getter = val_getter;
- var->setter = val_setter;
- var->marker = val_marker;
-
- var->data = (void*)val;
-}
-
-static void
-undef_marker()
-{
-}
-
-static VALUE
-val_getter(id, val)
- ID id;
- VALUE val;
-{
- return val;
-}
-
-static void
-val_setter(val, id, data, var)
- VALUE val;
- ID id;
- void *data;
- struct global_variable *var;
-{
- var->data = (void*)val;
-}
-
-static void
-val_marker(data)
- VALUE data;
-{
- if (data) rb_gc_mark_maybe(data);
-}
-
-static VALUE
-var_getter(id, var)
- ID id;
- VALUE *var;
-{
- if (!var) return Qnil;
- return *var;
-}
-
-static void
-var_setter(val, id, var)
- VALUE val;
- ID id;
- VALUE *var;
-{
- *var = val;
-}
-
-static void
-var_marker(var)
- VALUE *var;
-{
- if (var) rb_gc_mark_maybe(*var);
-}
-
-static void
-readonly_setter(val, id, var)
- VALUE val;
- ID id;
- void *var;
-{
- rb_name_error(id, "%s is a read-only variable", rb_id2name(id));
-}
-
-static int
-mark_global_entry(key, entry)
- ID key;
- struct global_entry *entry;
-{
- struct trace_var *trace;
- struct global_variable *var = entry->var;
-
- (*var->marker)(var->data);
- trace = var->trace;
- while (trace) {
- if (trace->data) rb_gc_mark_maybe(trace->data);
- trace = trace->next;
- }
- return ST_CONTINUE;
-}
-
-void
-rb_gc_mark_global_tbl()
-{
- st_foreach_safe(rb_global_tbl, mark_global_entry, 0);
-}
-
-static ID
-global_id(name)
- const char *name;
-{
- ID id;
-
- if (name[0] == '$') id = rb_intern(name);
- else {
- char *buf = ALLOCA_N(char, strlen(name)+2);
- buf[0] = '$';
- strcpy(buf+1, name);
- id = rb_intern(buf);
- }
- return id;
-}
-
-void
-rb_define_hooked_variable(name, var, getter, setter)
- const char *name;
- VALUE *var;
- VALUE (*getter)();
- void (*setter)();
-{
- struct global_variable *gvar;
- ID id = global_id(name);
-
- gvar = rb_global_entry(id)->var;
- gvar->data = (void*)var;
- gvar->getter = getter?getter:var_getter;
- gvar->setter = setter?setter:var_setter;
- gvar->marker = var_marker;
-}
-
-void
-rb_define_variable(name, var)
- const char *name;
- VALUE *var;
-{
- rb_define_hooked_variable(name, var, 0, 0);
-}
-
-void
-rb_define_readonly_variable(name, var)
- const char *name;
- VALUE *var;
-{
- rb_define_hooked_variable(name, var, 0, readonly_setter);
-}
-
-void
-rb_define_virtual_variable(name, getter, setter)
- const char *name;
- VALUE (*getter)();
- void (*setter)();
-{
- if (!getter) getter = val_getter;
- if (!setter) setter = readonly_setter;
- rb_define_hooked_variable(name, 0, getter, setter);
-}
-
-static void
-rb_trace_eval(cmd, val)
- VALUE cmd, val;
-{
- rb_eval_cmd(cmd, rb_ary_new3(1, val), 0);
-}
-
-/*
- * call-seq:
- * trace_var(symbol, cmd ) => nil
- * trace_var(symbol) {|val| block } => nil
- *
- * Controls tracing of assignments to global variables. The parameter
- * +symbol_ identifies the variable (as either a string name or a
- * symbol identifier). _cmd_ (which may be a string or a
- * +Proc+ object) or block is executed whenever the variable
- * is assigned. The block or +Proc+ object receives the
- * variable's new value as a parameter. Also see
- * <code>Kernel::untrace_var</code>.
- *
- * trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
- * $_ = "hello"
- * $_ = ' there'
- *
- * <em>produces:</em>
- *
- * $_ is now 'hello'
- * $_ is now ' there'
- */
-
-VALUE
-rb_f_trace_var(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE var, cmd;
- struct global_entry *entry;
- struct trace_var *trace;
-
- rb_secure(4);
- if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
- cmd = rb_block_proc();
- }
- if (NIL_P(cmd)) {
- return rb_f_untrace_var(argc, argv);
- }
- entry = rb_global_entry(rb_to_id(var));
- if (OBJ_TAINTED(cmd)) {
- rb_raise(rb_eSecurityError, "Insecure: tainted variable trace");
- }
- trace = ALLOC(struct trace_var);
- trace->next = entry->var->trace;
- trace->func = rb_trace_eval;
- trace->data = cmd;
- trace->removed = 0;
- entry->var->trace = trace;
-
- return Qnil;
-}
-
-static void
-remove_trace(var)
- struct global_variable *var;
-{
- struct trace_var *trace = var->trace;
- struct trace_var t;
- struct trace_var *next;
-
- t.next = trace;
- trace = &t;
- while (trace->next) {
- next = trace->next;
- if (next->removed) {
- trace->next = next->next;
- free(next);
- }
- else {
- trace = next;
- }
- }
- var->trace = t.next;
-}
-
-/*
- * call-seq:
- * untrace_var(symbol [, cmd] ) => array or nil
- *
- * Removes tracing for the specified command on the given global
- * variable and returns +nil+. If no command is specified,
- * removes all tracing for that variable and returns an array
- * containing the commands actually removed.
- */
-
-VALUE
-rb_f_untrace_var(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE var, cmd;
- ID id;
- struct global_entry *entry;
- struct trace_var *trace;
-
- rb_scan_args(argc, argv, "11", &var, &cmd);
- id = rb_to_id(var);
- if (!st_lookup(rb_global_tbl, id, (st_data_t *)&entry)) {
- rb_name_error(id, "undefined global variable %s", rb_id2name(id));
- }
-
- trace = entry->var->trace;
- if (NIL_P(cmd)) {
- VALUE ary = rb_ary_new();
-
- while (trace) {
- struct trace_var *next = trace->next;
- rb_ary_push(ary, (VALUE)trace->data);
- trace->removed = 1;
- trace = next;
- }
-
- if (!entry->var->block_trace) remove_trace(entry->var);
- return ary;
- }
- else {
- while (trace) {
- if (trace->data == cmd) {
- trace->removed = 1;
- if (!entry->var->block_trace) remove_trace(entry->var);
- return rb_ary_new3(1, cmd);
- }
- trace = trace->next;
- }
- }
- return Qnil;
-}
-
-VALUE
-rb_gvar_get(entry)
- struct global_entry *entry;
-{
- struct global_variable *var = entry->var;
- return (*var->getter)(entry->id, var->data, var);
-}
-
-struct trace_data {
- struct trace_var *trace;
- VALUE val;
-};
-
-static VALUE
-trace_ev(data)
- struct trace_data *data;
-{
- struct trace_var *trace = data->trace;
-
- while (trace) {
- (*trace->func)(trace->data, data->val);
- trace = trace->next;
- }
- return Qnil; /* not reached */
-}
-
-static VALUE
-trace_en(var)
- struct global_variable *var;
-{
- var->block_trace = 0;
- remove_trace(var);
- return Qnil; /* not reached */
-}
-
-VALUE
-rb_gvar_set(entry, val)
- struct global_entry *entry;
- VALUE val;
-{
- struct trace_data trace;
- struct global_variable *var = entry->var;
-
- if (rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't change global variable value");
- (*var->setter)(val, entry->id, var->data, var);
-
- if (var->trace && !var->block_trace) {
- var->block_trace = 1;
- trace.trace = var->trace;
- trace.val = val;
- rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var);
- }
- return val;
-}
-
-VALUE
-rb_gv_set(name, val)
- const char *name;
- VALUE val;
-{
- struct global_entry *entry;
-
- entry = rb_global_entry(global_id(name));
- return rb_gvar_set(entry, val);
-}
-
-VALUE
-rb_gv_get(name)
- const char *name;
-{
- struct global_entry *entry;
-
- entry = rb_global_entry(global_id(name));
- return rb_gvar_get(entry);
-}
-
-VALUE
-rb_gvar_defined(entry)
- struct global_entry *entry;
-{
- if (entry->var->getter == undef_getter) return Qfalse;
- return Qtrue;
-}
-
-static int
-gvar_i(key, entry, ary)
- ID key;
- struct global_entry *entry;
- VALUE ary;
-{
- rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * global_variables => array
- *
- * Returns an array of the names of global variables.
- *
- * global_variables.grep /std/ #=> ["$stderr", "$stdout", "$stdin"]
- */
-
-VALUE
-rb_f_global_variables()
-{
- VALUE ary = rb_ary_new();
- char buf[4];
- char *s = "&`'+123456789";
-
- st_foreach_safe(rb_global_tbl, gvar_i, ary);
- if (!NIL_P(rb_backref_get())) {
- while (*s) {
- sprintf(buf, "$%c", *s++);
- rb_ary_push(ary, rb_str_new2(buf));
- }
- }
- return ary;
-}
-
-void
-rb_alias_variable(name1, name2)
- ID name1;
- ID name2;
-{
- struct global_entry *entry1, *entry2;
-
- if (rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't alias global variable");
-
- entry2 = rb_global_entry(name2);
- if (!st_lookup(rb_global_tbl, name1, (st_data_t *)&entry1)) {
- entry1 = ALLOC(struct global_entry);
- entry1->id = name1;
- st_add_direct(rb_global_tbl, name1, (st_data_t)entry1);
- }
- else if (entry1->var != entry2->var) {
- struct global_variable *var = entry1->var;
- if (var->block_trace) {
- rb_raise(rb_eRuntimeError, "can't alias in tracer");
- }
- var->counter--;
- if (var->counter == 0) {
- struct trace_var *trace = var->trace;
- while (trace) {
- struct trace_var *next = trace->next;
- free(trace);
- trace = next;
- }
- free(var);
- }
- }
- else {
- return;
- }
- entry2->var->counter++;
- entry1->var = entry2->var;
-}
-
-static int special_generic_ivar = 0;
-static st_table *generic_iv_tbl;
-
-st_table*
-rb_generic_ivar_table(obj)
- VALUE obj;
-{
- st_table *tbl;
-
- if (!FL_TEST(obj, FL_EXIVAR)) return 0;
- if (!generic_iv_tbl) return 0;
- if (!st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) return 0;
- return tbl;
-}
-
-static VALUE
-generic_ivar_get(obj, id)
- VALUE obj;
- ID id;
-{
- st_table *tbl;
- VALUE val;
-
- if (generic_iv_tbl) {
- if (st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) {
- if (st_lookup(tbl, id, &val)) {
- return val;
- }
- }
- }
-
- rb_warning("instance variable %s not initialized", rb_id2name(id));
- return Qnil;
-}
-
-static void
-generic_ivar_set(obj, id, val)
- VALUE obj;
- ID id;
- VALUE val;
-{
- st_table *tbl;
-
- if (rb_special_const_p(obj)) {
- special_generic_ivar = 1;
- }
- if (!generic_iv_tbl) {
- generic_iv_tbl = st_init_numtable();
- }
-
- if (!st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) {
- FL_SET(obj, FL_EXIVAR);
- tbl = st_init_numtable();
- st_add_direct(generic_iv_tbl, obj, (st_data_t)tbl);
- st_add_direct(tbl, id, val);
- return;
- }
- st_insert(tbl, id, val);
-}
-
-static VALUE
-generic_ivar_defined(obj, id)
- VALUE obj;
- ID id;
-{
- st_table *tbl;
- VALUE val;
-
- if (!generic_iv_tbl) return Qfalse;
- if (!st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) return Qfalse;
- if (st_lookup(tbl, id, &val)) {
- return Qtrue;
- }
- return Qfalse;
-}
-
-static int
-generic_ivar_remove(obj, id, valp)
- VALUE obj;
- ID id;
- VALUE *valp;
-{
- st_table *tbl;
- int status;
-
- if (!generic_iv_tbl) return 0;
- if (!st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) return 0;
- status = st_delete(tbl, &id, valp);
- if (tbl->num_entries == 0) {
- st_delete(generic_iv_tbl, &obj, (st_data_t *)&tbl);
- st_free_table(tbl);
- }
- return status;
-}
-
-void
-rb_mark_generic_ivar(obj)
- VALUE obj;
-{
- st_table *tbl;
-
- if (!generic_iv_tbl) return;
- if (st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) {
- rb_mark_tbl(tbl);
- }
-}
-
-static int
-givar_mark_i(key, value)
- ID key;
- VALUE value;
-{
- rb_gc_mark(value);
- return ST_CONTINUE;
-}
-
-static int
-givar_i(obj, tbl)
- VALUE obj;
- st_table *tbl;
-{
- if (rb_special_const_p(obj)) {
- st_foreach_safe(tbl, givar_mark_i, 0);
- }
- return ST_CONTINUE;
-}
-
-void
-rb_mark_generic_ivar_tbl()
-{
- if (!generic_iv_tbl) return;
- if (special_generic_ivar == 0) return;
- st_foreach_safe(generic_iv_tbl, givar_i, 0);
-}
-
-void
-rb_free_generic_ivar(obj)
- VALUE obj;
-{
- st_table *tbl;
-
- if (!generic_iv_tbl) return;
- if (st_delete(generic_iv_tbl, &obj, (st_data_t *)&tbl))
- st_free_table(tbl);
-}
-
-void
-rb_copy_generic_ivar(clone, obj)
- VALUE clone, obj;
-{
- st_table *tbl;
-
- if (!generic_iv_tbl) return;
- if (!FL_TEST(obj, FL_EXIVAR)) return;
- if (st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) {
- st_table *old;
-
- if (st_lookup(generic_iv_tbl, clone, (st_data_t *)&old)) {
- st_free_table(old);
- st_insert(generic_iv_tbl, clone, (st_data_t)st_copy(tbl));
- }
- else {
- st_add_direct(generic_iv_tbl, clone, (st_data_t)st_copy(tbl));
- FL_SET(clone, FL_EXIVAR);
- }
- }
-}
-
-static VALUE
-ivar_get(obj, id, warn)
- VALUE obj;
- ID id;
- int warn;
-{
- VALUE val;
-
- switch (TYPE(obj)) {
- case T_OBJECT:
- case T_CLASS:
- case T_MODULE:
- if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, &val))
- return val;
- break;
- default:
- if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
- return generic_ivar_get(obj, id);
- break;
- }
- if (warn && ruby_verbose) {
- rb_warning("instance variable %s not initialized", rb_id2name(id));
- }
-
- return Qnil;
-}
-
-VALUE
-rb_ivar_get(obj, id)
- VALUE obj;
- ID id;
-{
- return ivar_get(obj, id, Qtrue);
-}
-
-VALUE
-rb_attr_get(obj, id)
- VALUE obj;
- ID id;
-{
- return ivar_get(obj, id, Qfalse);
-}
-
-VALUE
-rb_ivar_set(obj, id, val)
- VALUE obj;
- ID id;
- VALUE val;
-{
- if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
- if (OBJ_FROZEN(obj)) rb_error_frozen("object");
- switch (TYPE(obj)) {
- case T_OBJECT:
- case T_CLASS:
- case T_MODULE:
- if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = st_init_numtable();
- st_insert(ROBJECT(obj)->iv_tbl, id, val);
- break;
- default:
- generic_ivar_set(obj, id, val);
- break;
- }
- return val;
-}
-
-VALUE
-rb_ivar_defined(obj, id)
- VALUE obj;
- ID id;
-{
- switch (TYPE(obj)) {
- case T_OBJECT:
- case T_CLASS:
- case T_MODULE:
- if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, 0))
- return Qtrue;
- break;
- default:
- if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
- return generic_ivar_defined(obj, id);
- break;
- }
- return Qfalse;
-}
-
-static int
-ivar_i(key, entry, ary)
- ID key;
- struct global_entry *entry;
- VALUE ary;
-{
- if (rb_is_instance_id(key)) {
- rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
- }
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * obj.instance_variables => array
- *
- * Returns an array of instance variable names for the receiver. Note
- * that simply defining an accessor does not create the corresponding
- * instance variable.
- *
- * class Fred
- * attr_accessor :a1
- * def initialize
- * @iv = 3
- * end
- * end
- * Fred.new.instance_variables #=> ["@iv"]
- */
-
-VALUE
-rb_obj_instance_variables(obj)
- VALUE obj;
-{
- VALUE ary;
-
- ary = rb_ary_new();
- switch (TYPE(obj)) {
- case T_OBJECT:
- case T_CLASS:
- case T_MODULE:
- if (ROBJECT(obj)->iv_tbl) {
- st_foreach_safe(ROBJECT(obj)->iv_tbl, ivar_i, ary);
- }
- break;
- default:
- if (!generic_iv_tbl) break;
- if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
- st_table *tbl;
-
- if (st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) {
- st_foreach_safe(tbl, ivar_i, ary);
- }
- }
- break;
- }
- return ary;
-}
-
-/*
- * call-seq:
- * obj.remove_instance_variable(symbol) => obj
- *
- * Removes the named instance variable from <i>obj</i>, returning that
- * variable's value.
- *
- * class Dummy
- * attr_reader :var
- * def initialize
- * @var = 99
- * end
- * def remove
- * remove_instance_variable(:@var)
- * end
- * end
- * d = Dummy.new
- * d.var #=> 99
- * d.remove #=> 99
- * d.var #=> nil
- */
-
-VALUE
-rb_obj_remove_instance_variable(obj, name)
- VALUE obj, name;
-{
- VALUE val = Qnil;
- ID id = rb_to_id(name);
-
- if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
- if (OBJ_FROZEN(obj)) rb_error_frozen("object");
- if (!rb_is_instance_id(id)) {
- rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
- }
-
- switch (TYPE(obj)) {
- case T_OBJECT:
- case T_CLASS:
- case T_MODULE:
- if (ROBJECT(obj)->iv_tbl && st_delete(ROBJECT(obj)->iv_tbl, (st_data_t*)&id, &val)) {
- return val;
- }
- break;
- default:
- if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
- if (generic_ivar_remove(obj, id, &val)) {
- return val;
- }
- }
- break;
- }
- rb_name_error(id, "instance variable %s not defined", rb_id2name(id));
- return Qnil; /* not reached */
-}
-
-NORETURN(static void uninitialized_constant _((VALUE, ID)));
-static void
-uninitialized_constant(klass, id)
- VALUE klass;
- ID id;
-{
- if (klass && klass != rb_cObject)
- rb_name_error(id, "uninitialized constant %s::%s",
- rb_class2name(klass),
- rb_id2name(id));
- else {
- rb_name_error(id, "uninitialized constant %s", rb_id2name(id));
- }
-}
-
-static VALUE
-const_missing(klass, id)
- VALUE klass;
- ID id;
-{
- return rb_funcall(klass, rb_intern("const_missing"), 1, ID2SYM(id));
-}
-
-
-/*
- * call-seq:
- * mod.const_missing(sym) => obj
- *
- * Invoked when a reference is made to an undefined constant in
- * <i>mod</i>. It is passed a symbol for the undefined constant, and
- * returns a value to be used for that constant. The
- * following code is a (very bad) example: if reference is made to
- * an undefined constant, it attempts to load a file whose name is
- * the lowercase version of the constant (thus class <code>Fred</code> is
- * assumed to be in file <code>fred.rb</code>). If found, it returns the
- * value of the loaded class. It therefore implements a perverse
- * kind of autoload facility.
- *
- * def Object.const_missing(name)
- * @looked_for ||= {}
- * str_name = name.to_s
- * raise "Class not found: #{name}" if @looked_for[str_name]
- * @looked_for[str_name] = 1
- * file = str_name.downcase
- * require file
- * klass = const_get(name)
- * return klass if klass
- * raise "Class not found: #{name}"
- * end
- *
- */
-
-VALUE
-rb_mod_const_missing(klass, name)
- VALUE klass, name;
-{
- ruby_frame = ruby_frame->prev; /* pop frame for "const_missing" */
- uninitialized_constant(klass, rb_to_id(name));
- return Qnil; /* not reached */
-}
-
-static struct st_table *
-check_autoload_table(av)
- VALUE av;
-{
- Check_Type(av, T_DATA);
- if (RDATA(av)->dmark != (RUBY_DATA_FUNC)rb_mark_tbl ||
- RDATA(av)->dfree != (RUBY_DATA_FUNC)st_free_table) {
- rb_raise(rb_eTypeError, "wrong autoload table: %s", RSTRING(rb_inspect(av))->ptr);
- }
- return (struct st_table *)DATA_PTR(av);
-}
-
-void
-rb_autoload(mod, id, file)
- VALUE mod;
- ID id;
- const char *file;
-{
- VALUE av, fn;
- struct st_table *tbl;
-
- if (!rb_is_const_id(id)) {
- rb_raise(rb_eNameError, "autoload must be constant name", rb_id2name(id));
- }
- if (!file || !*file) {
- rb_raise(rb_eArgError, "empty file name");
- }
-
- if ((tbl = RCLASS(mod)->iv_tbl) && st_lookup(tbl, id, &av) && av != Qundef)
- return;
-
- rb_const_set(mod, id, Qundef);
- tbl = RCLASS(mod)->iv_tbl;
- if (st_lookup(tbl, autoload, &av)) {
- tbl = check_autoload_table(av);
- }
- else {
- av = Data_Wrap_Struct(0, rb_mark_tbl, st_free_table, 0);
- st_add_direct(tbl, autoload, av);
- DATA_PTR(av) = tbl = st_init_numtable();
- }
- fn = rb_str_new2(file);
- FL_UNSET(fn, FL_TAINT);
- OBJ_FREEZE(fn);
- st_insert(tbl, id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, ruby_safe_level, 0));
-}
-
-static NODE*
-autoload_delete(mod, id)
- VALUE mod;
- ID id;
-{
- VALUE val;
- st_data_t load = 0;
-
- st_delete(RCLASS(mod)->iv_tbl, (st_data_t*)&id, 0);
- if (st_lookup(RCLASS(mod)->iv_tbl, autoload, &val)) {
- struct st_table *tbl = check_autoload_table(val);
-
- st_delete(tbl, (st_data_t*)&id, &load);
-
- if (tbl->num_entries == 0) {
- DATA_PTR(val) = 0;
- st_free_table(tbl);
- id = autoload;
- if (st_delete(RCLASS(mod)->iv_tbl, (st_data_t*)&id, &val)) {
- rb_gc_force_recycle(val);
- }
- }
- }
-
- return (NODE *)load;
-}
-
-void
-rb_autoload_load(klass, id)
- VALUE klass;
- ID id;
-{
- VALUE file;
- NODE *load = autoload_delete(klass, id);
-
- if (!load || !(file = load->nd_lit) || rb_provided(RSTRING(file)->ptr)) {
- const_missing(klass, id);
- }
- rb_require_safe(file, load->nd_nth);
-}
-
-static VALUE
-autoload_file(mod, id)
- VALUE mod;
- ID id;
-{
- VALUE val, file;
- struct st_table *tbl;
- st_data_t load;
-
- if (!st_lookup(RCLASS(mod)->iv_tbl, autoload, &val) ||
- !(tbl = check_autoload_table(val)) || !st_lookup(tbl, id, &load)) {
- return Qnil;
- }
- file = ((NODE *)load)->nd_lit;
- Check_Type(file, T_STRING);
- if (!RSTRING(file)->ptr) {
- rb_raise(rb_eArgError, "empty file name");
- }
- if (!rb_provided(RSTRING(file)->ptr)) {
- return file;
- }
-
- /* already loaded but not defined */
- st_delete(tbl, (st_data_t*)&id, 0);
- if (!tbl->num_entries) {
- DATA_PTR(val) = 0;
- st_free_table(tbl);
- id = autoload;
- if (st_delete(RCLASS(mod)->iv_tbl, (st_data_t*)&id, &val)) {
- rb_gc_force_recycle(val);
- }
- }
- return Qnil;
-}
-
-VALUE
-rb_autoload_p(mod, id)
- VALUE mod;
- ID id;
-{
- struct st_table *tbl = RCLASS(mod)->iv_tbl;
- VALUE val;
-
- if (!tbl || !st_lookup(tbl, id, &val) || val != Qundef) {
- return Qnil;
- }
- return autoload_file(mod, id);
-}
-
-static VALUE
-rb_const_get_0(klass, id, exclude, recurse)
- VALUE klass;
- ID id;
- int exclude, recurse;
-{
- VALUE value, tmp;
- int mod_retry = 0;
-
- tmp = klass;
- retry:
- while (tmp) {
- while (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) {
- if (value == Qundef) {
- rb_autoload_load(tmp, id);
- continue;
- }
- if (exclude && tmp == rb_cObject && klass != rb_cObject) {
- rb_warn("toplevel constant %s referenced by %s::%s",
- rb_id2name(id), rb_class2name(klass), rb_id2name(id));
- }
- return value;
- }
- if (!recurse && klass != rb_cObject) break;
- tmp = RCLASS(tmp)->super;
- }
- if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
- mod_retry = 1;
- tmp = rb_cObject;
- goto retry;
- }
-
- return const_missing(klass, id);
-}
-
-VALUE
-rb_const_get_from(klass, id)
- VALUE klass;
- ID id;
-{
- return rb_const_get_0(klass, id, Qtrue, Qtrue);
-}
-
-VALUE
-rb_const_get(klass, id)
- VALUE klass;
- ID id;
-{
- return rb_const_get_0(klass, id, Qfalse, Qtrue);
-}
-
-VALUE
-rb_const_get_at(klass, id)
- VALUE klass;
- ID id;
-{
- return rb_const_get_0(klass, id, Qtrue, Qfalse);
-}
-
-/*
- * call-seq:
- * remove_const(sym) => obj
- *
- * Removes the definition of the given constant, returning that
- * constant's value. Predefined classes and singleton objects (such as
- * <i>true</i>) cannot be removed.
- */
-
-VALUE
-rb_mod_remove_const(mod, name)
- VALUE mod, name;
-{
- ID id = rb_to_id(name);
- VALUE val;
-
- if (!rb_is_const_id(id)) {
- rb_name_error(id, "`%s' is not allowed as a constant name", rb_id2name(id));
- }
- if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
- if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
-
- if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, (st_data_t*)&id, &val)) {
- if (val == Qundef) {
- autoload_delete(mod, id);
- val = Qnil;
- }
- return val;
- }
- if (rb_const_defined_at(mod, id)) {
- rb_name_error(id, "cannot remove %s::%s",
- rb_class2name(mod), rb_id2name(id));
- }
- rb_name_error(id, "constant %s::%s not defined",
- rb_class2name(mod), rb_id2name(id));
- return Qnil; /* not reached */
-}
-
-static int
-sv_i(key, value, tbl)
- ID key;
- VALUE value;
- st_table *tbl;
-{
- if (rb_is_const_id(key)) {
- if (!st_lookup(tbl, key, 0)) {
- st_insert(tbl, key, key);
- }
- }
- return ST_CONTINUE;
-}
-
-void*
-rb_mod_const_at(mod, data)
- VALUE mod;
- void *data;
-{
- st_table *tbl = data;
- if (!tbl) {
- tbl = st_init_numtable();
- }
- if (RCLASS(mod)->iv_tbl) {
- st_foreach_safe(RCLASS(mod)->iv_tbl, sv_i, (st_data_t)tbl);
- }
- return tbl;
-}
-
-void*
-rb_mod_const_of(mod, data)
- VALUE mod;
- void *data;
-{
- VALUE tmp = mod;
- for (;;) {
- data = rb_mod_const_at(tmp, data);
- tmp = RCLASS(tmp)->super;
- if (!tmp) break;
- if (tmp == rb_cObject && mod != rb_cObject) break;
- }
- return data;
-}
-
-static int
-list_i(key, value, ary)
- ID key, value;
- VALUE ary;
-{
- rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
- return ST_CONTINUE;
-}
-
-VALUE
-rb_const_list(data)
- void *data;
-{
- st_table *tbl = data;
- VALUE ary;
-
- if (!tbl) return rb_ary_new2(0);
- ary = rb_ary_new2(tbl->num_entries);
- st_foreach_safe(tbl, list_i, ary);
- st_free_table(tbl);
-
- return ary;
-}
-
-/*
- * call-seq:
- * mod.constants => array
- *
- * Returns an array of the names of the constants accessible in
- * <i>mod</i>. This includes the names of constants in any included
- * modules (example at start of section).
- */
-
-VALUE
-rb_mod_constants(mod)
- VALUE mod;
-{
- return rb_const_list(rb_mod_const_of(mod, 0));
-}
-
-static int
-rb_const_defined_0(klass, id, exclude, recurse)
- VALUE klass;
- ID id;
- int exclude, recurse;
-{
- VALUE value, tmp;
- int mod_retry = 0;
-
- tmp = klass;
- retry:
- while (tmp) {
- if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl, id, &value)) {
- if (value == Qundef && NIL_P(autoload_file(klass, id)))
- return Qfalse;
- return Qtrue;
- }
- if (!recurse && klass != rb_cObject) break;
- tmp = RCLASS(tmp)->super;
- }
- if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
- mod_retry = 1;
- tmp = rb_cObject;
- goto retry;
- }
- return Qfalse;
-}
-
-int
-rb_const_defined_from(klass, id)
- VALUE klass;
- ID id;
-{
- return rb_const_defined_0(klass, id, Qtrue, Qtrue);
-}
-
-int
-rb_const_defined(klass, id)
- VALUE klass;
- ID id;
-{
- return rb_const_defined_0(klass, id, Qfalse, Qtrue);
-}
-
-int
-rb_const_defined_at(klass, id)
- VALUE klass;
- ID id;
-{
- return rb_const_defined_0(klass, id, Qtrue, Qfalse);
-}
-
-static void
-mod_av_set(klass, id, val, isconst)
- VALUE klass;
- ID id;
- VALUE val;
- int isconst;
-{
- char *dest = isconst ? "constant" : "class variable";
-
- if (!OBJ_TAINTED(klass) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest);
- if (OBJ_FROZEN(klass)) {
- if (BUILTIN_TYPE(klass) == T_MODULE) {
- rb_error_frozen("module");
- }
- else {
- rb_error_frozen("class");
- }
- }
- if (!RCLASS(klass)->iv_tbl) {
- RCLASS(klass)->iv_tbl = st_init_numtable();
- }
- else if (isconst) {
- VALUE value = Qfalse;
-
- if (st_lookup(RCLASS(klass)->iv_tbl, id, &value)) {
- if (value == Qundef)
- autoload_delete(klass, id);
- else
- rb_warn("already initialized %s %s", dest, rb_id2name(id));
- }
- }
-
- st_insert(RCLASS(klass)->iv_tbl, id, val);
-}
-
-void
-rb_const_set(klass, id, val)
- VALUE klass;
- ID id;
- VALUE val;
-{
- mod_av_set(klass, id, val, Qtrue);
-}
-
-void
-rb_define_const(klass, name, val)
- VALUE klass;
- const char *name;
- VALUE val;
-{
- ID id = rb_intern(name);
-
- if (!rb_is_const_id(id)) {
- rb_warn("rb_define_const: invalide name `%s' for constant", name);
- }
- if (klass == rb_cObject) {
- rb_secure(4);
- }
- rb_const_set(klass, id, val);
-}
-
-void
-rb_define_global_const(name, val)
- const char *name;
- VALUE val;
-{
- rb_define_const(rb_cObject, name, val);
-}
-
-void
-rb_cvar_set(klass, id, val, warn)
- VALUE klass;
- ID id;
- VALUE val;
- int warn;
-{
- mod_av_set(klass, id, val, Qfalse);
-}
-
-VALUE
-rb_cvar_get(klass, id)
- VALUE klass;
- ID id;
-{
- VALUE value;
-
- if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl,id,&value)) {
- return value;
- }
-
- rb_name_error(id,"uninitialized class variable %s in %s",
- rb_id2name(id), rb_class2name(klass));
- return Qnil; /* not reached */
-}
-
-VALUE
-rb_cvar_defined(klass, id)
- VALUE klass;
- ID id;
-{
- if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl,id,0)) {
- return Qtrue;
- }
- return Qfalse;
-}
-
-void
-rb_cv_set(klass, name, val)
- VALUE klass;
- const char *name;
- VALUE val;
-{
- ID id = rb_intern(name);
- if (!rb_is_class_id(id)) {
- rb_name_error(id, "wrong class variable name %s", name);
- }
- rb_cvar_set(klass, id, val, Qfalse);
-}
-
-VALUE
-rb_cv_get(klass, name)
- VALUE klass;
- const char *name;
-{
- ID id = rb_intern(name);
- if (!rb_is_class_id(id)) {
- rb_name_error(id, "wrong class variable name %s", name);
- }
- return rb_cvar_get(klass, id);
-}
-
-void
-rb_define_class_variable(klass, name, val)
- VALUE klass;
- const char *name;
- VALUE val;
-{
- ID id = rb_intern(name);
-
- if (!rb_is_class_id(id)) {
- rb_name_error(id, "wrong class variable name %s", name);
- }
- rb_cvar_set(klass, id, val, Qtrue);
-}
-
-static int
-cv_i(key, value, ary)
- ID key;
- VALUE value;
- VALUE ary;
-{
- if (rb_is_class_id(key)) {
- VALUE kval = rb_str_new2(rb_id2name(key));
- if (!rb_ary_includes(ary, kval)) {
- rb_ary_push(ary, kval);
- }
- }
- return ST_CONTINUE;
-}
-
-/*
- * call-seq:
- * mod.class_variables => array
- *
- * Returns an array of the names of class variables in <i>mod</i>.
- *
- * class One
- * @@var1 = 1
- * end
- * class Two < One
- * @@var2 = 2
- * end
- * One.class_variables #=> ["@@var1"]
- * Two.class_variables #=> ["@@var2"]
- */
-
-VALUE
-rb_mod_class_variables(obj)
- VALUE obj;
-{
- VALUE ary = rb_ary_new();
-
- if (RCLASS(obj)->iv_tbl) {
- st_foreach_safe(RCLASS(obj)->iv_tbl, cv_i, ary);
- }
- return ary;
-}
-
-/*
- * call-seq:
- * remove_class_variable(sym) => obj
- *
- * Removes the definition of the <i>sym</i>, returning that
- * constant's value.
- *
- * class Dummy
- * @@var = 99
- * puts @@var
- * remove_class_variable(:@@var)
- * puts(defined? @@var)
- * end
- *
- * <em>produces:</em>
- *
- * 99
- * nil
- */
-
-VALUE
-rb_mod_remove_cvar(mod, name)
- VALUE mod, name;
-{
- ID id = rb_to_id(name);
- VALUE val;
-
- if (!rb_is_class_id(id)) {
- rb_name_error(id, "wrong class variable name %s", rb_id2name(id));
- }
- if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
- if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
-
- if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, (st_data_t*)&id, &val)) {
- return val;
- }
- if (rb_cvar_defined(mod, id)) {
- rb_name_error(id, "cannot remove %s for %s",
- rb_id2name(id), rb_class2name(mod));
- }
- rb_name_error(id, "class variable %s not defined for %s",
- rb_id2name(id), rb_class2name(mod));
- return Qnil; /* not reached */
-}
-
-VALUE
-rb_iv_get(obj, name)
- VALUE obj;
- const char *name;
-{
- ID id = rb_intern(name);
-
- return rb_ivar_get(obj, id);
-}
-
-VALUE
-rb_iv_set(obj, name, val)
- VALUE obj;
- const char *name;
- VALUE val;
-{
- ID id = rb_intern(name);
-
- return rb_ivar_set(obj, id, val);
-}
-/**********************************************************************
-
- version.c -
-
- $Author: nobu $
- $Date: 2004/03/25 12:01:40 $
- created at: Thu Sep 30 20:08:01 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include "version.h"
-#include <stdio.h>
-
-const char ruby_version[] = RUBY_VERSION;
-const char ruby_release_date[] = RUBY_RELEASE_DATE;
-const char ruby_platform[] = RUBY_PLATFORM;
-
-void
-Init_version()
-{
- VALUE v = rb_obj_freeze(rb_str_new2(ruby_version));
- VALUE d = rb_obj_freeze(rb_str_new2(ruby_release_date));
- VALUE p = rb_obj_freeze(rb_str_new2(ruby_platform));
-
- rb_define_global_const("RUBY_VERSION", v);
- rb_define_global_const("RUBY_RELEASE_DATE", d);
- rb_define_global_const("RUBY_PLATFORM", p);
-}
-
-void
-ruby_show_version()
-{
- printf("ruby %s (%s) [%s]\n", RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM);
-}
-
-void
-ruby_show_copyright()
-{
- printf("ruby - Copyright (C) 1993-%d Yukihiro Matsumoto\n", RUBY_RELEASE_YEAR);
- exit(0);
-}
diff --git a/bench/example.cpp b/bench/example.cpp
deleted file mode 100644
index ba9cf72..0000000
--- a/bench/example.cpp
+++ /dev/null
@@ -1,13544 +0,0 @@
-/***************************************************************************
- ansigenerator.cpp - description
- -------------------
- begin : Jul 5 2004
- copyright : (C) 2004 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 "ansigenerator.h"
-
-using namespace std;
-
-namespace highlight {
-
-
-string AnsiGenerator::getOpenTag(const string&font,
- const string&fgCol, const string&bgCol) {
- ostringstream s;
- s << "\033["<<font;
- if (!fgCol.empty())
- s<<";"<<fgCol;
- if (!bgCol.empty())
- s<<";"<<bgCol;
- s << "m";
- return s.str();
-}
-
-
-AnsiGenerator::AnsiGenerator(const string &colourTheme)
- : CodeGenerator(colourTheme) {
- styleTagOpen.push_back("");
- styleTagOpen.push_back(getOpenTag("00", "31")); //str
- styleTagOpen.push_back(getOpenTag("00", "34"));//number
- styleTagOpen.push_back(getOpenTag("00", "34"));//sl comment
- styleTagOpen.push_back(getOpenTag("00", "34"));//ml comment
- styleTagOpen.push_back(getOpenTag("00", "35"));//escapeChar
- styleTagOpen.push_back(getOpenTag("00", "35"));//directive
- styleTagOpen.push_back(getOpenTag("01", "31"));//directive string
- styleTagOpen.push_back(getOpenTag("00", "30"));//linenum
- styleTagOpen.push_back(getOpenTag("01", "00"));//symbol
-
- styleTagClose.push_back("");
- for (int i=1;i<NUMBER_BUILTIN_STYLES; i++) {
- styleTagClose.push_back("\033[m");
- }
- newLineTag = "\n";
- spacer = " ";
-}
-
-AnsiGenerator::AnsiGenerator() {}
-AnsiGenerator::~AnsiGenerator() {}
-
-string AnsiGenerator::getHeader(const string & title) {
- return string();
-}
-
-void AnsiGenerator::printBody() {
- processRootState();
-}
-
-string AnsiGenerator::getFooter() {
- return string();
-}
-
-string AnsiGenerator::maskCharacter(unsigned char c) {
- string m;
- m+=c;
- return m;
-}
-
-string AnsiGenerator::getMatchingOpenTag(unsigned int styleID) {
- return (styleID)?getOpenTag("01", "32", ""):getOpenTag("00", "33");
-}
-
-string AnsiGenerator::getMatchingCloseTag(unsigned int styleID) {
- return "\033[m";
-}
-
-}
-/***************************************************************************
- ansicode.h - description
- -------------------
- begin : Jul 5 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 ANSIGENERATOR_H
-#define ANSIGENERATOR_H
-
-#include <iostream>
-#include <fstream>
-#include <string>
-#include <sstream>
-
-#include "codegenerator.h"
-#include "charcodes.h"
-#include "version.h"
-
-namespace highlight {
-
-/**
- \brief This class generates ANSI escape sequences.
-
- 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 AnsiGenerator : public highlight::CodeGenerator
- {
- public:
-
- /** Constructor
- \param colourTheme Name of Colour theme to use
- */
- AnsiGenerator( const string &colourTheme);
- AnsiGenerator();
- ~AnsiGenerator();
-
- /** 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 );
-
-
- /** gibt ANSI-"Tags" zurueck (Farbindex+bold+kursiv)*/
- string getOpenTag(const string&font,
- const string&fgCol, const string&bgCol="");
-
-
-
- string getMatchingOpenTag(unsigned int styleID);
- string getMatchingCloseTag(unsigned int styleID);
- };
-
-}
-#endif
-/*
- * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
- *
- * ASBeautifier.cpp
- * by Tal Davidson (davidsont@bigfoot.com)
- * This file is a part of "Artistic Style" - an indentater and reformatter
- * of C, C, C# and Java source files.
- *
- * The "Artistic Style" project, including all files needed to compile it,
- * is free software; you can redistribute it and/or use it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program.
- *
- * Patches:
- * 18 March 1999 - Brian Rampel -
- * Fixed inverse insertion of spaces vs. tabs when in -t mode.
- * 08 may 2004
- * applied ASBeautifier.cpp.BITFIELD.patch.bz2
- */
-
-#include "compiler_defines.h"
-#include "ASBeautifier.h"
-
-#include <vector>
-#include <string>
-#include <cctype>
-#include <algorithm>
-#include <iostream>
-
-
-#define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); }
-#define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container) ; }
-
-#ifdef USES_NAMESPACE
-using namespace std;
-#endif
-
-
-
-
-#ifdef USES_NAMESPACE
-namespace astyle
- {
-#endif
-
- bool ASBeautifier::calledInitStatic = false;
-
- vector<const string*> ASBeautifier::headers;
- vector<const string*> ASBeautifier::nonParenHeaders;
- vector<const string*> ASBeautifier::preBlockStatements;
- vector<const string*> ASBeautifier::assignmentOperators;
- vector<const string*> ASBeautifier::nonAssignmentOperators;
-
- /*
- * initialize the static vars
- */
- void ASBeautifier::initStatic()
- {
- if (calledInitStatic)
- return;
-
- calledInitStatic = true;
-
- headers.push_back(&AS_IF);
- headers.push_back(&AS_ELSE);
- headers.push_back(&AS_FOR);
- headers.push_back(&AS_WHILE);
- headers.push_back(&AS_DO);
- headers.push_back(&AS_TRY);
- headers.push_back(&AS_CATCH);
- headers.push_back(&AS_FINALLY);
- headers.push_back(&AS_SYNCHRONIZED);
- headers.push_back(&AS_SWITCH);
- headers.push_back(&AS_CASE);
- headers.push_back(&AS_DEFAULT);
- headers.push_back(&AS_FOREACH);
- headers.push_back(&AS_LOCK);
- headers.push_back(&AS_UNSAFE);
- headers.push_back(&AS_FIXED);
- headers.push_back(&AS_GET);
- headers.push_back(&AS_SET);
- headers.push_back(&AS_ADD);
- headers.push_back(&AS_REMOVE);
- //headers.push_back(&AS_PUBLIC);
- //headers.push_back(&AS_PRIVATE);
- //headers.push_back(&AS_PROTECTED);
-
- //headers.push_back(&AS_OPERATOR);
- headers.push_back(&AS_TEMPLATE);
- headers.push_back(&AS_CONST);
- /**/
- headers.push_back(&AS_STATIC);
- headers.push_back(&AS_EXTERN);
-
- nonParenHeaders.push_back(&AS_ELSE);
- nonParenHeaders.push_back(&AS_DO);
- nonParenHeaders.push_back(&AS_TRY);
- nonParenHeaders.push_back(&AS_FINALLY);
- nonParenHeaders.push_back(&AS_STATIC);
- nonParenHeaders.push_back(&AS_CONST);
- nonParenHeaders.push_back(&AS_EXTERN);
- nonParenHeaders.push_back(&AS_CASE);
- nonParenHeaders.push_back(&AS_DEFAULT);
- nonParenHeaders.push_back(&AS_UNSAFE);
- nonParenHeaders.push_back(&AS_GET);
- nonParenHeaders.push_back(&AS_SET);
- nonParenHeaders.push_back(&AS_ADD);
- nonParenHeaders.push_back(&AS_REMOVE);
-
-
-
- nonParenHeaders.push_back(&AS_PUBLIC);
- nonParenHeaders.push_back(&AS_PRIVATE);
- nonParenHeaders.push_back(&AS_PROTECTED);
- nonParenHeaders.push_back(&AS_TEMPLATE);
- nonParenHeaders.push_back(&AS_CONST);
- /// nonParenHeaders.push_back(&AS_ASM);
-
- preBlockStatements.push_back(&AS_CLASS);
- preBlockStatements.push_back(&AS_STRUCT);
- preBlockStatements.push_back(&AS_UNION);
- preBlockStatements.push_back(&AS_INTERFACE);
- preBlockStatements.push_back(&AS_NAMESPACE);
- preBlockStatements.push_back(&AS_THROWS);
- preBlockStatements.push_back(&AS_EXTERN);
-
- assignmentOperators.push_back(&AS_ASSIGN);
- assignmentOperators.push_back(&AS_PLUS_ASSIGN);
- assignmentOperators.push_back(&AS_MINUS_ASSIGN);
- assignmentOperators.push_back(&AS_MULT_ASSIGN);
- assignmentOperators.push_back(&AS_DIV_ASSIGN);
- assignmentOperators.push_back(&AS_MOD_ASSIGN);
- assignmentOperators.push_back(&AS_OR_ASSIGN);
- assignmentOperators.push_back(&AS_AND_ASSIGN);
- assignmentOperators.push_back(&AS_XOR_ASSIGN);
- assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN);
- assignmentOperators.push_back(&AS_GR_GR_ASSIGN);
- assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN);
- assignmentOperators.push_back(&AS_LS_LS_ASSIGN);
-
- assignmentOperators.push_back(&AS_RETURN);
-
- nonAssignmentOperators.push_back(&AS_EQUAL);
- nonAssignmentOperators.push_back(&AS_PLUS_PLUS);
- nonAssignmentOperators.push_back(&AS_MINUS_MINUS);
- nonAssignmentOperators.push_back(&AS_NOT_EQUAL);
- nonAssignmentOperators.push_back(&AS_GR_EQUAL);
- nonAssignmentOperators.push_back(&AS_GR_GR_GR);
- nonAssignmentOperators.push_back(&AS_GR_GR);
- nonAssignmentOperators.push_back(&AS_LS_EQUAL);
- nonAssignmentOperators.push_back(&AS_LS_LS_LS);
- nonAssignmentOperators.push_back(&AS_LS_LS);
- nonAssignmentOperators.push_back(&AS_ARROW);
- nonAssignmentOperators.push_back(&AS_AND);
- nonAssignmentOperators.push_back(&AS_OR);
- }
-
- /**
- * ASBeautifier's constructor
- */
- ASBeautifier::ASBeautifier()
- {
- initStatic();
-
- waitingBeautifierStack = NULL;
- activeBeautifierStack = NULL;
- waitingBeautifierStackLengthStack = NULL;
- activeBeautifierStackLengthStack = NULL;
-
- headerStack = NULL;
- tempStacks = NULL;
- blockParenDepthStack = NULL;
- blockStatementStack = NULL;
- parenStatementStack = NULL;
- bracketBlockStateStack = NULL;
- inStatementIndentStack = NULL;
- inStatementIndentStackSizeStack = NULL;
- parenIndentStack = NULL;
- sourceIterator = NULL;
-
- isMinimalConditinalIndentSet = false;
- shouldForceTabIndentation = false;
-
- setSpaceIndentation(4);
- setMaxInStatementIndentLength(40);
- setClassIndent(false);
- setSwitchIndent(false);
- setCaseIndent(false);
- setBlockIndent(false);
- setBracketIndent(false);
- setNamespaceIndent(false);
- setLabelIndent(false);
- setEmptyLineFill(false);
- setCStyle();
- setPreprocessorIndent(false);
- }
-
- ASBeautifier::ASBeautifier(const ASBeautifier &other)
- {
- waitingBeautifierStack = NULL;
- activeBeautifierStack = NULL;
- waitingBeautifierStackLengthStack = NULL;
- activeBeautifierStackLengthStack = NULL;
-
- headerStack = new vector<const string*>;
- *headerStack = *other.headerStack;
-
- tempStacks = new vector< vector<const string*>* >;
- vector< vector<const string*>* >::iterator iter;
- for (iter = other.tempStacks->begin();
- iter != other.tempStacks->end();
- ++iter)
- {
- vector<const string*> *newVec = new vector<const string*>;
- *newVec = **iter;
- tempStacks->push_back(newVec);
- }
- blockParenDepthStack = new vector<int>;
- *blockParenDepthStack = *other.blockParenDepthStack;
-
- blockStatementStack = new vector<bool>;
- *blockStatementStack = *other.blockStatementStack;
-
- parenStatementStack = new vector<bool>;
- *parenStatementStack = *other.parenStatementStack;
-
- bracketBlockStateStack = new vector<bool>;
- *bracketBlockStateStack = *other.bracketBlockStateStack;
-
- inStatementIndentStack = new vector<int>;
- *inStatementIndentStack = *other.inStatementIndentStack;
-
- inStatementIndentStackSizeStack = new vector<int>;
- *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack;
-
- parenIndentStack = new vector<int>;
- *parenIndentStack = *other.parenIndentStack;
-
- sourceIterator = other.sourceIterator;
-
- indentString = other.indentString;
- currentHeader = other.currentHeader;
- previousLastLineHeader = other.previousLastLineHeader;
- immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp;
- isInQuote = other.isInQuote;
- isInComment = other.isInComment;
- isInCase = other.isInCase;
- isInQuestion = other.isInQuestion;
- isInStatement =other. isInStatement;
- isInHeader = other.isInHeader;
- isCStyle = other.isCStyle;
- isInOperator = other.isInOperator;
- isInTemplate = other.isInTemplate;
- isInConst = other.isInConst;
- classIndent = other.classIndent;
- isInClassHeader = other.isInClassHeader;
- isInClassHeaderTab = other.isInClassHeaderTab;
- switchIndent = other.switchIndent;
- caseIndent = other.caseIndent;
- namespaceIndent = other.namespaceIndent;
- bracketIndent = other.bracketIndent;
- blockIndent = other.blockIndent;
- labelIndent = other.labelIndent;
- preprocessorIndent = other.preprocessorIndent;
- parenDepth = other.parenDepth;
- indentLength = other.indentLength;
- blockTabCount = other.blockTabCount;
- leadingWhiteSpaces = other.leadingWhiteSpaces;
- maxInStatementIndent = other.maxInStatementIndent;
- templateDepth = other.templateDepth;
- quoteChar = other.quoteChar;
- prevNonSpaceCh = other.prevNonSpaceCh;
- currentNonSpaceCh = other.currentNonSpaceCh;
- currentNonLegalCh = other.currentNonLegalCh;
- prevNonLegalCh = other.prevNonLegalCh;
- isInConditional = other.isInConditional;
- minConditionalIndent = other.minConditionalIndent;
- prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount;
- prevFinalLineTabCount = other.prevFinalLineTabCount;
- emptyLineFill = other.emptyLineFill;
- probationHeader = other.probationHeader;
- isInDefine = other.isInDefine;
- isInDefineDefinition = other.isInDefineDefinition;
- backslashEndsPrevLine = other.backslashEndsPrevLine;
- defineTabCount = other.defineTabCount;
- }
-
- /**
- * ASBeautifier's destructor
- */
- ASBeautifier::~ASBeautifier()
- {
- DELETE_CONTAINER( headerStack );
- DELETE_CONTAINER( tempStacks );
- DELETE_CONTAINER( blockParenDepthStack );
- DELETE_CONTAINER( blockStatementStack );
- DELETE_CONTAINER( parenStatementStack );
- DELETE_CONTAINER( bracketBlockStateStack );
- DELETE_CONTAINER( inStatementIndentStack );
- DELETE_CONTAINER( inStatementIndentStackSizeStack );
- DELETE_CONTAINER( parenIndentStack );
-
- // DELETE_CONTAINER( sourceIterator );
- }
-
- /**
- * initialize the ASBeautifier.
- *
- * init() should be called every time a ABeautifier object is to start
- * beautifying a NEW source file.
- * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object
- * that will be used to iterate through the source code. This object will be
- * deleted during the ASBeautifier's destruction, and thus should not be
- * deleted elsewhere.
- *
- * @param iter a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
- */
- void ASBeautifier::init(ASSourceIterator *iter)
-
- {
- sourceIterator = iter;
- init();
- }
-
- /**
- * initialize the ASBeautifier.
- */
- void ASBeautifier::init()
- {
- INIT_CONTAINER( waitingBeautifierStack, new vector<ASBeautifier*> );
- INIT_CONTAINER( activeBeautifierStack, new vector<ASBeautifier*> );
-
- INIT_CONTAINER( waitingBeautifierStackLengthStack, new vector<int> );
- INIT_CONTAINER( activeBeautifierStackLengthStack, new vector<int> );
-
- INIT_CONTAINER( headerStack, new vector<const string*> );
- INIT_CONTAINER( tempStacks, new vector< vector<const string*>* > );
- tempStacks->push_back(new vector<const string*>);
-
- INIT_CONTAINER( blockParenDepthStack, new vector<int> );
- INIT_CONTAINER( blockStatementStack, new vector<bool> );
- INIT_CONTAINER( parenStatementStack, new vector<bool> );
-
- INIT_CONTAINER( bracketBlockStateStack, new vector<bool> );
- bracketBlockStateStack->push_back(true);
-
- INIT_CONTAINER( inStatementIndentStack, new vector<int> );
- INIT_CONTAINER( inStatementIndentStackSizeStack, new vector<int> );
- inStatementIndentStackSizeStack->push_back(0);
- INIT_CONTAINER( parenIndentStack, new vector<int> );
-
- immediatelyPreviousAssignmentOp = NULL;
- previousLastLineHeader = NULL;
-
- isInQuote = false;
- isInComment = false;
- isInStatement = false;
- isInCase = false;
- isInQuestion = false;
- isInClassHeader = false;
- isInClassHeaderTab = false;
- isInHeader = false;
- isInOperator = false;
- isInTemplate = false;
- isInConst = false;
- isInConditional = false;
- templateDepth = 0;
- parenDepth=0;
- blockTabCount = 0;
- leadingWhiteSpaces = 0;
- prevNonSpaceCh = '{';
- currentNonSpaceCh = '{';
- prevNonLegalCh = '{';
- currentNonLegalCh = '{';
- prevFinalLineSpaceTabCount = 0;
- prevFinalLineTabCount = 0;
- probationHeader = NULL;
- backslashEndsPrevLine = false;
- isInDefine = false;
- isInDefineDefinition = false;
- defineTabCount = 0;
- }
-
- /**
- * set indentation style to ANSI C/C++.
- */
- void ASBeautifier::setCStyle()
- {
- isCStyle = true;
- }
-
- /**
- * set indentation style to Java / K&R.
- */
- void ASBeautifier::setJavaStyle()
- {
- isCStyle = false;
- }
-
- /**
- * indent using one tab per indentation
- */
- void ASBeautifier::setTabIndentation(int length, bool forceTabs)
- {
- indentString = "\t";
- indentLength = length;
- shouldForceTabIndentation = forceTabs;
-
- if (!isMinimalConditinalIndentSet)
- minConditionalIndent = indentLength * 2;
- }
-
- /**
-
- * indent using a number of spaces per indentation.
- *
- * @param length number of spaces per indent.
- */
- void ASBeautifier::setSpaceIndentation(int length)
- {
- indentString=string(length, ' ');
- indentLength = length;
-
- if (!isMinimalConditinalIndentSet)
- minConditionalIndent = indentLength * 2;
- }
-
- /**
- * set the maximum indentation between two lines in a multi-line statement.
- *
- * @param max maximum indentation length.
- */
- void ASBeautifier::setMaxInStatementIndentLength(int max)
- {
- maxInStatementIndent = max;
- }
-
- /**
- * set the minimum indentation between two lines in a multi-line condition.
- *
- * @param min minimal indentation length.
- */
- void ASBeautifier::setMinConditionalIndentLength(int min)
- {
- minConditionalIndent = min;
- isMinimalConditinalIndentSet = true;
- }
-
- /**
- * set the state of the bracket indentation option. If true, brackets will
- * be indented one additional indent.
- *
- * @param state state of option.
- */
- void ASBeautifier::setBracketIndent(bool state)
- {
- bracketIndent = state;
- }
-
- /**
- * set the state of the block indentation option. If true, entire blocks
- * will be indented one additional indent, similar to the GNU indent style.
- *
- * @param state state of option.
- */
- void ASBeautifier::setBlockIndent(bool state)
- {
- if (state)
- setBracketIndent(false); // so that we don't have both bracket and block indent
- blockIndent = state;
- }
-
- /**
- * set the state of the class indentation option. If true, C++ class
- * definitions will be indented one additional indent.
- *
- * @param state state of option.
- */
- void ASBeautifier::setClassIndent(bool state)
- {
- classIndent = state;
- }
-
- /**
- * set the state of the switch indentation option. If true, blocks of 'switch'
- * statements will be indented one additional indent.
- *
- * @param state state of option.
- */
- void ASBeautifier::setSwitchIndent(bool state)
- {
- switchIndent = state;
- }
-
- /**
- * set the state of the case indentation option. If true, lines of 'case'
- * statements will be indented one additional indent.
- *
- * @param state state of option.
- */
- void ASBeautifier::setCaseIndent(bool state)
- {
- caseIndent = state;
- }
- /**
- * set the state of the namespace indentation option.
- * If true, blocks of 'namespace' statements will be indented one
- * additional indent. Otherwise, NO indentation will be added.
- *
- * @param state state of option.
- */
- void ASBeautifier::setNamespaceIndent(bool state)
- {
- namespaceIndent = state;
- }
-
- /**
- * set the state of the label indentation option.
- * If true, labels will be indented one indent LESS than the
- * current indentation level.
- * If false, labels will be flushed to the left with NO
- * indent at all.
- *
- * @param state state of option.
- */
- void ASBeautifier::setLabelIndent(bool state)
- {
- labelIndent = state;
- }
-
- /**
- * set the state of the preprocessor indentation option.
- * If true, multiline #define statements will be indented.
- *
- * @param state state of option.
- */
- void ASBeautifier::setPreprocessorIndent(bool state)
- {
- preprocessorIndent = state;
- }
-
- /**
- * set the state of the empty line fill option.
- * If true, empty lines will be filled with the whitespace.
- * of their previous lines.
- * If false, these lines will remain empty.
- *
- * @param state state of option.
- */
- void ASBeautifier::setEmptyLineFill(bool state)
- {
- emptyLineFill = state;
- }
-
- /**
- * check if there are any indented lines ready to be read by nextLine()
- *
- * @return are there any indented lines ready?
- */
- bool ASBeautifier::hasMoreLines() const
- {
- return sourceIterator->hasMoreLines();
- }
-
- /**
- * get the next indented line.
- *
- * @return indented line.
- */
- string ASBeautifier::nextLine()
- {
- return beautify(sourceIterator->nextLine());
- }
-
- /**
- * beautify a line of source code.
- * every line of source code in a source code file should be sent
- * one after the other to the beautify method.
- *
- * @return the indented line.
- * @param originalLine the original unindented line.
- */
- string ASBeautifier::beautify(const string &originalLine)
- {
- string line;
- bool isInLineComment = false;
- bool lineStartsInComment = false;
- bool isInClass = false;
- bool isInSwitch = false;
- bool isImmediatelyAfterConst = false;
- bool isSpecialChar = false;
-
- char ch = ' ';
- char prevCh;
- string outBuffer; // the newly idented line is bufferd here
- int tabCount = 0;
- const string *lastLineHeader = NULL;
- bool closingBracketReached = false;
- int spaceTabCount = 0;
- char tempCh;
- unsigned int headerStackSize = headerStack->size();
- //bool isLineInStatement = isInStatement;
- bool shouldIndentBrackettedLine = true;
- int lineOpeningBlocksNum = 0;
- int lineClosingBlocksNum = 0;
- bool previousLineProbation = (probationHeader != NULL);
- unsigned int i;
-
- currentHeader = NULL;
-
- lineStartsInComment = isInComment;
-
- // handle and remove white spaces around the line:
- // If not in comment, first find out size of white space before line,
- // so that possible comments starting in the line continue in
- // relation to the preliminary white-space.
- if (!isInComment)
- {
- leadingWhiteSpaces = 0;
- while (leadingWhiteSpaces<originalLine.length() && originalLine[leadingWhiteSpaces] <= 0x20)
- leadingWhiteSpaces++;
-
- line = trim(originalLine);
- }
- else
- {
- unsigned int trimSize;
- for (trimSize=0;
- trimSize < originalLine.length() && trimSize<leadingWhiteSpaces && originalLine[trimSize] <= 0x20 ;
- trimSize++)
- ;
- line = originalLine.substr(trimSize);
- }
-
-
- if (line.length() == 0)
- {
- if (emptyLineFill)
- return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount);
- else
- return line;
- }
-
- // handle preprocessor commands
-
- if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine))
- {
- if (line[0] == '#')
- {
- string preproc = trim(string(line.c_str() + 1));
-
-
- // When finding a multi-lined #define statement, the original beautifier
- // 1. sets its isInDefineDefinition flag
- // 2. clones a new beautifier that will be used for the actual indentation
- // of the #define. This clone is put into the activeBeautifierStack in order
- // to be called for the actual indentation.
- // The original beautifier will have isInDefineDefinition = true, isInDefine = false
- // The cloned beautifier will have isInDefineDefinition = true, isInDefine = true
- if (preprocessorIndent && preproc.COMPARE(0, 6, string("define")) == 0 && line[line.length() - 1] == '\\')
- {
- if (!isInDefineDefinition)
- {
- ASBeautifier *defineBeautifier;
-
- // this is the original beautifier
- isInDefineDefinition = true;
-
- // push a new beautifier into the active stack
- // this breautifier will be used for the indentation of this define
- defineBeautifier = new ASBeautifier(*this);
- //defineBeautifier->init();
- //defineBeautifier->isInDefineDefinition = true;
- //defineBeautifier->beautify("");
- activeBeautifierStack->push_back(defineBeautifier);
- }
- else
- {
- // the is the cloned beautifier that is in charge of indenting the #define.
- isInDefine = true;
- }
- }
- else if (preproc.COMPARE(0, 2, string("if")) == 0)
- {
- // push a new beautifier into the stack
- waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size());
- activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size());
- waitingBeautifierStack->push_back(new ASBeautifier(*this));
- }
- else if (preproc.COMPARE(0, 4/*2*/, string("else")) == 0)
- {
- if (!waitingBeautifierStack->empty())
- {
- // MOVE current waiting beautifier to active stack.
- activeBeautifierStack->push_back(waitingBeautifierStack->back());
- waitingBeautifierStack->pop_back();
- }
- }
- else if (preproc.COMPARE(0, 4, string("elif")) == 0)
- {
- if (!waitingBeautifierStack->empty())
- {
- // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original.
- activeBeautifierStack->push_back( new ASBeautifier( *(waitingBeautifierStack->back()) ) );
- }
- }
- else if (preproc.COMPARE(0, 5, string("endif")) == 0)
- {
- unsigned int stackLength;
- ASBeautifier *beautifier;
-
- if (!waitingBeautifierStackLengthStack->empty())
- {
- stackLength = waitingBeautifierStackLengthStack->back();
- waitingBeautifierStackLengthStack->pop_back();
- while (waitingBeautifierStack->size() > stackLength)
- {
- beautifier = waitingBeautifierStack->back();
- waitingBeautifierStack->pop_back();
- delete beautifier;
- }
- }
-
- if (!activeBeautifierStackLengthStack->empty())
- {
- stackLength = activeBeautifierStackLengthStack->back();
- activeBeautifierStackLengthStack->pop_back();
- while (activeBeautifierStack->size() > stackLength)
- {
- beautifier = activeBeautifierStack->back();
- activeBeautifierStack->pop_back();
- delete beautifier;
- }
- }
-
-
- }
- }
-
- // check if the last char is a backslash
- if(line.length() > 0)
- backslashEndsPrevLine = (line[line.length() - 1] == '\\');
- else
- backslashEndsPrevLine = false;
-
- // check if this line ends a multi-line #define
- // if so, use the #define's cloned beautifier for the line's indentation
- // and then remove it from the active beautifier stack and delete it.
- if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine)
- {
- string beautifiedLine;
- ASBeautifier *defineBeautifier;
-
- isInDefineDefinition = false;
- defineBeautifier = activeBeautifierStack->back();
- activeBeautifierStack->pop_back();
-
- beautifiedLine = defineBeautifier->beautify(line);
- delete defineBeautifier;
- return beautifiedLine;
- }
-
- // unless this is a multi-line #define, return this precompiler line as is.
- if (!isInDefine && !isInDefineDefinition)
- return originalLine;
- }
-
- // if there exists any worker beautifier in the activeBeautifierStack,
- // then use it instead of me to indent the current line.
- if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty())
- {
- return activeBeautifierStack->back()->beautify(line);
- }
-
- // calculate preliminary indentation based on data from past lines
- if (!inStatementIndentStack->empty())
- spaceTabCount = inStatementIndentStack->back();
-
-
- for (i=0; i<headerStackSize; i++)
- {
- isInClass = false;
-
- if (blockIndent || (!(i>0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET
- && (*headerStack)[i] == &AS_OPEN_BRACKET)))
- ++tabCount;
-
- if (isCStyle && !namespaceIndent && i >= 1
- && (*headerStack)[i-1] == &AS_NAMESPACE
- && (*headerStack)[i] == &AS_OPEN_BRACKET)
- --tabCount;
-
- if (isCStyle && i >= 1
- && (*headerStack)[i-1] == &AS_CLASS
- && (*headerStack)[i] == &AS_OPEN_BRACKET )
- {
- if (classIndent)
- ++tabCount;
- isInClass = true;
- }
-
- // is the switchIndent option is on, indent switch statements an additional indent.
- else if (switchIndent && i > 1 &&
- (*headerStack)[i-1] == &AS_SWITCH &&
- (*headerStack)[i] == &AS_OPEN_BRACKET
- )
- {
- ++tabCount;
- isInSwitch = true;
- }
-
- }
-
- if (!lineStartsInComment
- && isCStyle
- && isInClass
- && classIndent
- && headerStackSize >= 2
- &&(*headerStack)[headerStackSize-2] == &AS_CLASS
- && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
- && line[0] == '}')
- --tabCount;
-
- else if (!lineStartsInComment
- && isInSwitch
- && switchIndent
- && headerStackSize >= 2
- && (*headerStack)[headerStackSize-2] == &AS_SWITCH
- && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
- && line[0] == '}')
- --tabCount;
-
- if (isInClassHeader)
- {
- isInClassHeaderTab = true;
- tabCount += 2;
- }
-
- if (isInConditional)
- {
- --tabCount;
- }
-
-
- // parse characters in the current line.
-
- for (i=0; i<line.length(); i++)
- {
- tempCh = line[i];
-
- prevCh = ch;
- ch = tempCh;
-
- outBuffer.append(1, ch);
-
- if (isWhiteSpace(ch))
- continue;
-
-
- // handle special characters (i.e. backslash+character such as \n, \t, ...)
- if (isSpecialChar)
- {
- isSpecialChar = false;
- continue;
- }
- if (!(isInComment || isInLineComment) && line.COMPARE(i, 2, string("\\\\")) == 0)
- {
- outBuffer.append(1, '\\');
- i++;
- continue;
- }
- if (!(isInComment || isInLineComment) && ch=='\\')
- {
- isSpecialChar = true;
- continue;
- }
-
- // handle quotes (such as 'x' and "Hello Dolly")
- if (!(isInComment || isInLineComment) && (ch=='"' || ch=='\''))
- if (!isInQuote)
- {
- quoteChar = ch;
- isInQuote = true;
- }
- else if (quoteChar == ch)
- {
- isInQuote = false;
- isInStatement = true;
- continue;
- }
- if (isInQuote)
- continue;
-
- // handle comments
-
- if ( !(isInComment || isInLineComment) && line.COMPARE(i, 2, AS_OPEN_LINE_COMMENT) == 0 )
- {
- isInLineComment = true;
- outBuffer.append(1, '/');
- i++;
- continue;
- }
- else if ( !(isInComment || isInLineComment) && line.COMPARE(i, 2, AS_OPEN_COMMENT) == 0 )
- {
- isInComment = true;
- outBuffer.append(1, '*');
- i++;
- continue;
- }
- else if ( (isInComment || isInLineComment) && line.COMPARE(i, 2, AS_CLOSE_COMMENT) == 0 )
- {
- isInComment = false;
- outBuffer.append(1, '/');
- i++;
- continue;
- }
-
- if (isInComment||isInLineComment)
- continue;
-
- // if we have reached this far then we are NOT in a comment or string of special character...
-
- if (probationHeader != NULL)
- {
- if ( ((probationHeader == &AS_STATIC || probationHeader == &AS_CONST) && ch == '{')
- || (probationHeader == &AS_SYNCHRONIZED && ch == '('))
- {
- // insert the probation header as a new header
- isInHeader = true;
- headerStack->push_back(probationHeader);
-
- // handle the specific probation header
- isInConditional = (probationHeader == &AS_SYNCHRONIZED);
- if (probationHeader == &AS_CONST)
- isImmediatelyAfterConst = true;
- // isInConst = true;
- /* TODO:
- * There is actually no more need for the global isInConst variable.
- * The only reason for checking const is to see if there is a const
- * immediately before an open-bracket.
- * Since CONST is now put into probation and is checked during itspost-char,
- * isImmediatelyAfterConst can be set by its own...
- */
-
- isInStatement = false;
- // if the probation comes from the previous line, then indent by 1 tab count.
- if (previousLineProbation && ch == '{')
- tabCount++;
- previousLineProbation = false;
- }
-
- // dismiss the probation header
- probationHeader = NULL;
- }
-
- prevNonSpaceCh = currentNonSpaceCh;
- currentNonSpaceCh = ch;
- if (!isLegalNameChar(ch) && ch != ',' && ch != ';' )
- {
- prevNonLegalCh = currentNonLegalCh;
- currentNonLegalCh = ch;
- }
-
- //if (isInConst)
- //{
- // isInConst = false;
- // isImmediatelyAfterConst = true;
- //}
-
- if (isInHeader)
- {
- isInHeader = false;
- currentHeader = headerStack->back();
- }
- else
- currentHeader = NULL;
-
- if (isCStyle && isInTemplate
- && (ch == '<' || ch == '>')
- && findHeader(line, i, nonAssignmentOperators) == NULL) //;
- {
- if (ch == '<')
- {
- ++templateDepth;
- }
- else if (ch == '>')
- {
- if (--templateDepth <= 0)
- {
- if (isInTemplate)
- ch = ';';
- else
- ch = 't';
- isInTemplate = false;
- templateDepth = 0;
- }
-
- }
- }
-
- // handle parenthesies
- if (ch == '(' || ch == '[' || ch == ')' || ch == ']')
- {
- if (ch == '(' || ch == '[')
- {
- if (parenDepth == 0)
- {
- parenStatementStack->push_back(isInStatement);
- isInStatement = true;
- }
- parenDepth++;
-
- inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
-
- if (currentHeader != NULL)
- registerInStatementIndent(line, i, spaceTabCount, minConditionalIndent/*indentLength*2*/, true);
- else
- registerInStatementIndent(line, i, spaceTabCount, 0, true);
- }
- else if (ch == ')' || ch == ']')
- {
- parenDepth--;
- if (parenDepth == 0)
- {
- isInStatement = parenStatementStack->back();
- parenStatementStack->pop_back();
- ch = ' ';
-
- isInConditional = false;
- }
-
- if (!inStatementIndentStackSizeStack->empty())
- {
- unsigned int previousIndentStackSize = inStatementIndentStackSizeStack->back();
- inStatementIndentStackSizeStack->pop_back();
- while (previousIndentStackSize < inStatementIndentStack->size())
- inStatementIndentStack->pop_back();
-
- if (!parenIndentStack->empty())
- {
- int poppedIndent = parenIndentStack->back();
- parenIndentStack->pop_back();
-
- if (i == 0)
- spaceTabCount = poppedIndent;
- }
- }
- }
-
- continue;
- }
-
-
- if (ch == '{')
- {
- bool isBlockOpener = false;
-
- // first, check if '{' is a block-opener or an static-array opener
- isBlockOpener = ( (prevNonSpaceCh == '{' && bracketBlockStateStack->back())
- || prevNonSpaceCh == '}'
- || prevNonSpaceCh == ')'
- || prevNonSpaceCh == ';'
- || isInClassHeader
- || isBlockOpener
- || isImmediatelyAfterConst
- || (isInDefine &&
- (prevNonSpaceCh == '('
- || prevNonSpaceCh == '_'
- || isalnum(prevNonSpaceCh))) );
-
- isInClassHeader = false;
- if (!isBlockOpener && currentHeader != NULL)
- {
- for (unsigned int n=0; n < nonParenHeaders.size(); n++)
- if (currentHeader == nonParenHeaders[n])
- {
- isBlockOpener = true;
- break;
- }
- }
- bracketBlockStateStack->push_back(isBlockOpener);
- if (!isBlockOpener)
- {
- inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
- registerInStatementIndent(line, i, spaceTabCount, 0, true);
- parenDepth++;
- if (i == 0)
- shouldIndentBrackettedLine = false;
-
- continue;
- }
-
- // this bracket is a block opener...
-
- ++lineOpeningBlocksNum;
-
- if (isInClassHeader)
- isInClassHeader = false;
- if (isInClassHeaderTab)
- {
- isInClassHeaderTab = false;
- tabCount -= 2;
- }
-
- blockParenDepthStack->push_back(parenDepth);
- blockStatementStack->push_back(isInStatement);
-
- inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
-
- blockTabCount += isInStatement? 1 : 0;
- parenDepth = 0;
- isInStatement = false;
-
- tempStacks->push_back(new vector<const string*>);
- headerStack->push_back(&AS_OPEN_BRACKET);
- lastLineHeader = &AS_OPEN_BRACKET; // <------
-
- continue;
- }
-
- //check if a header has been reached
- if (prevCh == ' ')
- {
- bool isIndentableHeader = true;
- const string *newHeader = findHeader(line, i, headers);
- if (newHeader != NULL)
- {
- // if we reached here, then this is a header...
- isInHeader = true;
-
- vector<const string*> *lastTempStack;
- if (tempStacks->empty())
- lastTempStack = NULL;
- else
- lastTempStack = tempStacks->back();
-
- // if a new block is opened, push a new stack into tempStacks to hold the
- // future list of headers in the new block.
-
- // take care of the special case: 'else if (...)'
- if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE)
- {
- //spaceTabCount += indentLength; // to counter the opposite addition that occurs when the 'if' is registered below...
- headerStack->pop_back();
- }
-
- // take care of 'else'
- else if (newHeader == &AS_ELSE)
- {
- if (lastTempStack != NULL)
- {
- int indexOfIf = indexOf(*lastTempStack, &AS_IF); // <---
- if (indexOfIf != -1)
- {
- // recreate the header list in headerStack up to the previous 'if'
- // from the temporary snapshot stored in lastTempStack.
- int restackSize = lastTempStack->size() - indexOfIf - 1;
- for (int r=0; r<restackSize; r++)
- {
- headerStack->push_back(lastTempStack->back());
- lastTempStack->pop_back();
- }
- if (!closingBracketReached)
- tabCount += restackSize;
- }
- /*
- * If the above if is not true, i.e. no 'if' before the 'else',
- * then nothing beautiful will come out of this...
- * I should think about inserting an Exception here to notify the caller of this...
- */
- }
- }
-
- // check if 'while' closes a previous 'do'
- else if (newHeader == &AS_WHILE)
- {
- if (lastTempStack != NULL)
- {
- int indexOfDo = indexOf(*lastTempStack, &AS_DO); // <---
- if (indexOfDo != -1)
- {
- // recreate the header list in headerStack up to the previous 'do'
- // from the temporary snapshot stored in lastTempStack.
- int restackSize = lastTempStack->size() - indexOfDo - 1;
- for (int r=0; r<restackSize; r++)
- {
- headerStack->push_back(lastTempStack->back());
- lastTempStack->pop_back();
- }
- if (!closingBracketReached)
- tabCount += restackSize;
- }
- }
- }
- // check if 'catch' closes a previous 'try' or 'catch'
- else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY)
- {
- if (lastTempStack != NULL)
- {
- int indexOfTry = indexOf(*lastTempStack, &AS_TRY);
- if (indexOfTry == -1)
- indexOfTry = indexOf(*lastTempStack, &AS_CATCH);
- if (indexOfTry != -1)
- {
- // recreate the header list in headerStack up to the previous 'try'
- // from the temporary snapshot stored in lastTempStack.
- int restackSize = lastTempStack->size() - indexOfTry - 1;
- for (int r=0; r<restackSize; r++)
- {
- headerStack->push_back(lastTempStack->back());
- lastTempStack->pop_back();
- }
-
- if (!closingBracketReached)
- tabCount += restackSize;
- }
- }
- }
- else if (newHeader == &AS_CASE)
- {
- isInCase = true;
- if (!caseIndent)
- --tabCount;
- }
- else if(newHeader == &AS_DEFAULT)
- {
- isInCase = true;
- if (!caseIndent)
- --tabCount;
- }
- else if (newHeader == &AS_PUBLIC || newHeader == &AS_PROTECTED || newHeader == &AS_PRIVATE)
- {
- if (isCStyle && !isInClassHeader)
- --tabCount;
- isIndentableHeader = false;
- }
- //else if ((newHeader == &STATIC || newHeader == &SYNCHRONIZED) &&
- // !headerStack->empty() &&
- // (headerStack->back() == &STATIC || headerStack->back() == &SYNCHRONIZED))
- //{
- // isIndentableHeader = false;
- //}
- else if (newHeader == &AS_STATIC
- || newHeader == &AS_SYNCHRONIZED
- || (newHeader == &AS_CONST && isCStyle))
- {
- if (!headerStack->empty() &&
- (headerStack->back() == &AS_STATIC
- || headerStack->back() == &AS_SYNCHRONIZED
- || headerStack->back() == &AS_CONST))
- {
- isIndentableHeader = false;
- }
- else
- {
- isIndentableHeader = false;
- probationHeader = newHeader;
- }
- }
- else if (newHeader == &AS_CONST)
- {
- // this will be entered only if NOT in C style
- // since otherwise the CONST would be found to be a probstion header...
-
- //if (isCStyle)
- // isInConst = true;
- isIndentableHeader = false;
- }
- /*
- else if (newHeader == &OPERATOR)
- {
- if (isCStyle)
- isInOperator = true;
- isIndentableHeader = false;
- }
- */
- else if (newHeader == &AS_TEMPLATE)
- {
- if (isCStyle)
- isInTemplate = true;
- isIndentableHeader = false;
- }
-
-
- if (isIndentableHeader)
- {
- // 3.2.99
- //spaceTabCount-=indentLength;
- headerStack->push_back(newHeader);
- isInStatement = false;
- if (indexOf(nonParenHeaders, newHeader) == -1)
- {
- isInConditional = true;
- }
- lastLineHeader = newHeader;
- }
- else
- isInHeader = false;
-
- //lastLineHeader = newHeader;
-
- outBuffer.append(newHeader->substr(1));
- i += newHeader->length() - 1;
-
- continue;
- }
- }
-
- if (isCStyle && !isalpha(prevCh)
- && line.COMPARE(i, 8, AS_OPERATOR) == 0 && !isalnum(line[i+8]))
- {
- isInOperator = true;
- outBuffer.append(AS_OPERATOR.substr(1));
- i += 7;
- continue;
- }
-
- if (ch == '?')
- isInQuestion = true;
-
-
- // special handling of 'case' statements
- if (ch == ':')
- {
- if (line.length() > i+1 && line[i+1] == ':') // look for ::
- {
- ++i;
- outBuffer.append(1, ':');
- ch = ' ';
- continue;
- }
-
- else if (isCStyle && isInClass && prevNonSpaceCh != ')')
- {
- // BEGIN Content of ASBeautifier.cpp.BITFIELD.patch:
-
- unsigned int chIndex;
- char nextCh = 0;
- for (chIndex = i+1; chIndex < line.length(); chIndex++)
- if (!isWhiteSpace(line[chIndex]))
- break;
- if (chIndex< line.length())
- nextCh = line[chIndex];
- int nWord =0;
- for (chIndex = 0; chIndex < i; chIndex++)
- {
- if (!isWhiteSpace(line[chIndex]))
- {
- nWord ++;
- while (!isWhiteSpace(line[++chIndex]));
- }
- }
- if ((nextCh >= '0' && nextCh <= '9') || (nWord >1))
- continue;
- // END Content of ASBeautifier.cpp.BITFIELD.patch:
-
- --tabCount;
- // found a 'private:' or 'public:' inside a class definition
- // so do nothing special
- }
-
- else if (isCStyle && isInClassHeader)
- {
-
- // found a 'class A : public B' definition
- // so do nothing special
- }
-
- else if (isInQuestion)
- {
- isInQuestion = false;
- }
- else if (isCStyle && prevNonSpaceCh == ')')
- {
- isInClassHeader = true;
- if (i==0)
- tabCount += 2;
- }
- else
- {
- currentNonSpaceCh = ';'; // so that brackets after the ':' will appear as block-openers
- if (isInCase)
- {
- isInCase = false;
- ch = ';'; // from here on, treat char as ';'
- }
- // BEGIN content of ASBeautifier.cpp.BITFIELD.patch.bz2
- else // bitfield or labels
- {
- unsigned int chIndex;
- char nextCh = 0;
- for (chIndex = i+1; (isCStyle && chIndex < line.length()); chIndex++)
- if (!isWhiteSpace(line[chIndex]))
- break;
- if (chIndex< line.length())
- nextCh = line[chIndex];
-
- int nWord =0;
- for (chIndex = 0; chIndex < i; chIndex++)
- {
- if (!isWhiteSpace(line[chIndex]))
- {
- nWord ++;
- while (!isWhiteSpace(line[++chIndex]));
- }
- }
- if (isCStyle && (nextCh >= '0' && nextCh <= '9') || (nWord >1))
- {
- continue;
- }
- // END content of ASASBeautifier.cpp.BITFIELD.patch.bz2
-
- else // is in a label (e.g. 'label1:')
- {
- if (labelIndent)
- --tabCount; // unindent label by one indent
- else
- tabCount = 0; // completely flush indent to left
- }
-
- // BEGIN content of ASASBeautifier.cpp.BITFIELD.patch.bz2
- }
- // END content of ASASBeautifier.cpp.BITFIELD.patch.bz2
-
- }
- }
-
- if ((ch == ';' || (parenDepth>0 && ch == ',')) && !inStatementIndentStackSizeStack->empty())
- while ((unsigned int)inStatementIndentStackSizeStack->back() + (parenDepth>0 ? 1 : 0) < inStatementIndentStack->size())
- inStatementIndentStack->pop_back();
-
-
- // handle ends of statements
- if ( (ch == ';' && parenDepth == 0) || ch == '}'/* || (ch == ',' && parenDepth == 0)*/)
- {
- if (ch == '}')
- {
- // first check if this '}' closes a previous block, or a static array...
- if (!bracketBlockStateStack->empty())
- {
- bool bracketBlockState = bracketBlockStateStack->back();
- bracketBlockStateStack->pop_back();
- if (!bracketBlockState)
- {
- if (!inStatementIndentStackSizeStack->empty())
- {
- // this bracket is a static array
-
- unsigned int previousIndentStackSize = inStatementIndentStackSizeStack->back();
- inStatementIndentStackSizeStack->pop_back();
- while (previousIndentStackSize < inStatementIndentStack->size())
- inStatementIndentStack->pop_back();
- parenDepth--;
- if (i == 0)
- shouldIndentBrackettedLine = false;
-
- if (!parenIndentStack->empty())
- {
- int poppedIndent = parenIndentStack->back();
- parenIndentStack->pop_back();
- if (i == 0)
- spaceTabCount = poppedIndent;
- }
- }
- continue;
- }
- }
-
- // this bracket is block closer...
-
- ++lineClosingBlocksNum;
-
- if(!inStatementIndentStackSizeStack->empty())
- inStatementIndentStackSizeStack->pop_back();
-
- if (!blockParenDepthStack->empty())
- {
- parenDepth = blockParenDepthStack->back();
- blockParenDepthStack->pop_back();
- isInStatement = blockStatementStack->back();
- blockStatementStack->pop_back();
-
- if (isInStatement)
- blockTabCount--;
- }
-
- closingBracketReached = true;
- int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET); // <---
- if (headerPlace != -1)
- {
- const string *popped = headerStack->back();
- while (popped != &AS_OPEN_BRACKET)
- {
- headerStack->pop_back();
- popped = headerStack->back();
- }
- headerStack->pop_back();
-
- if (!tempStacks->empty())
- {
- vector<const string*> *temp = tempStacks->back();
- tempStacks->pop_back();
- delete temp;
- }
- }
-
-
- ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified...
- }
-
- /*
- * Create a temporary snapshot of the current block's header-list in the
- * uppermost inner stack in tempStacks, and clear the headerStack up to
- * the begining of the block.
- * Thus, the next future statement will think it comes one indent past
- * the block's '{' unless it specifically checks for a companion-header
- * (such as a previous 'if' for an 'else' header) within the tempStacks,
- * and recreates the temporary snapshot by manipulating the tempStacks.
- */
- if (!tempStacks->back()->empty())
- while (!tempStacks->back()->empty())
- tempStacks->back()->pop_back();
- while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACKET)
- {
- tempStacks->back()->push_back(headerStack->back());
- headerStack->pop_back();
- }
-
- if (parenDepth == 0 && ch == ';')
- isInStatement=false;
-
- isInClassHeader = false;
-
- continue;
- }
-
-
- // check for preBlockStatements ONLY if not within parenthesies
- // (otherwise 'struct XXX' statements would be wrongly interpreted...)
- if (prevCh == ' ' && !isInTemplate && parenDepth == 0)
- {
- const string *newHeader = findHeader(line, i, preBlockStatements);
- if (newHeader != NULL)
- {
- isInClassHeader = true;
- outBuffer.append(newHeader->substr(1));
- i += newHeader->length() - 1;
- //if (isCStyle)
- headerStack->push_back(newHeader);
- }
- }
-
- // Handle operators
- //
-
- //// // PRECHECK if a '==' or '--' or '++' operator was reached.
- //// // If not, then register an indent IF an assignment operator was reached.
- //// // The precheck is important, so that statements such as 'i--==2' are not recognized
- //// // to have assignment operators (here, '-=') in them . . .
-
- const string *foundAssignmentOp = NULL;
- const string *foundNonAssignmentOp = NULL;
-
- immediatelyPreviousAssignmentOp = NULL;
-
- // Check if an operator has been reached.
- foundAssignmentOp = findHeader(line, i, assignmentOperators, false);
- foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false);
-
- // Since findHeader's boundry checking was not used above, it is possible
- // that both an assignment op and a non-assignment op where found,
- // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the
- // found operator.
- if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL)
- if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
- foundAssignmentOp = NULL;
- else
- foundNonAssignmentOp = NULL;
-
- if (foundNonAssignmentOp != NULL)
- {
- if (foundNonAssignmentOp->length() > 1)
- {
- outBuffer.append(foundNonAssignmentOp->substr(1));
- i += foundNonAssignmentOp->length() - 1;
- }
- }
-
- else if (foundAssignmentOp != NULL)
-
- {
- if (foundAssignmentOp->length() > 1)
- {
- outBuffer.append(foundAssignmentOp->substr(1));
- i += foundAssignmentOp->length() - 1;
- }
-
- if (!isInOperator && !isInTemplate)
- {
- registerInStatementIndent(line, i, spaceTabCount, 0, false);
- immediatelyPreviousAssignmentOp = foundAssignmentOp;
- isInStatement = true;
- }
- }
-
- /*
- immediatelyPreviousAssignmentOp = NULL;
- bool isNonAssingmentOperator = false;
- for (int n = 0; n < nonAssignmentOperators.size(); n++)
- if (line.COMPARE(i, nonAssignmentOperators[n]->length(), *(nonAssignmentOperators[n])) == 0)
- {
- if (nonAssignmentOperators[n]->length() > 1)
- {
- outBuffer.append(nonAssignmentOperators[n]->substr(1));
- i += nonAssignmentOperators[n]->length() - 1;
- }
- isNonAssingmentOperator = true;
- break;
- }
- if (!isNonAssingmentOperator)
- {
- for (int a = 0; a < assignmentOperators.size(); a++)
- if (line.COMPARE(i, assignmentOperators[a]->length(), *(assignmentOperators[a])) == 0)
- {
- if (assignmentOperators[a]->length() > 1)
- {
- outBuffer.append(assignmentOperators[a]->substr(1));
- i += assignmentOperators[a]->length() - 1;
- }
-
- if (!isInOperator && !isInTemplate)
- {
- registerInStatementIndent(line, i, spaceTabCount, 0, false);
- immediatelyPreviousAssignmentOp = assignmentOperators[a];
- isInStatement = true;
- }
- break;
- }
- }
- */
-
- if (isInOperator)
- isInOperator = false;
- }
-
- // handle special cases of unindentation:
-
- /*
- * if '{' doesn't follow an immediately previous '{' in the headerStack
- * (but rather another header such as "for" or "if", then unindent it
- * by one indentation relative to its block.
- */
- // cerr << endl << lineOpeningBlocksNum << " " << lineClosingBlocksNum << " " << previousLastLineHeader << endl;
-
- // indent #define lines with one less tab
- //if (isInDefine)
- // tabCount -= defineTabCount-1;
-
-
- if (!lineStartsInComment
- && !blockIndent
- && outBuffer.length()>0
- && outBuffer[0]=='{'
- && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum)
- && !(headerStack->size() > 1 && (*headerStack)[headerStack->size()-2] == &AS_OPEN_BRACKET)
- && shouldIndentBrackettedLine)
- --tabCount;
-
- else if (!lineStartsInComment
- && outBuffer.length()>0
- && outBuffer[0]=='}'
- && shouldIndentBrackettedLine )
- --tabCount;
-
- // correctly indent one-line-blocks...
- else if (!lineStartsInComment
- && outBuffer.length()>0
- && lineOpeningBlocksNum > 0
- && lineOpeningBlocksNum == lineClosingBlocksNum
- && previousLastLineHeader != NULL
- && previousLastLineHeader != &AS_OPEN_BRACKET)
- tabCount -= 1; //lineOpeningBlocksNum - (blockIndent ? 1 : 0);
-
- if (tabCount < 0)
- tabCount = 0;
-
- // take care of extra bracket indentatation option...
- if (bracketIndent && outBuffer.length()>0 && shouldIndentBrackettedLine)
- if (outBuffer[0]=='{' || outBuffer[0]=='}')
- tabCount++;
-
-
- if (isInDefine)
- {
- if (outBuffer[0] == '#')
- {
- string preproc = trim(string(outBuffer.c_str() + 1));
- if (preproc.COMPARE(0, 6, string("define")) == 0)
- {
- if (!inStatementIndentStack->empty()
- && inStatementIndentStack->back() > 0)
- {
- defineTabCount = tabCount;
- }
- else
- {
- defineTabCount = tabCount - 1;
- tabCount--;
- }
- }
- }
-
- tabCount -= defineTabCount;
- }
-
- if (tabCount < 0)
- tabCount = 0;
-
-
- // finally, insert indentations into begining of line
-
- prevFinalLineSpaceTabCount = spaceTabCount;
- prevFinalLineTabCount = tabCount;
-
- if (shouldForceTabIndentation)
- {
- tabCount += spaceTabCount / indentLength;
- spaceTabCount = spaceTabCount % indentLength;
- }
-
- outBuffer = preLineWS(spaceTabCount,tabCount) + outBuffer;
-
- if (lastLineHeader != NULL)
- previousLastLineHeader = lastLineHeader;
-
- return outBuffer;
- }
-
-
- string ASBeautifier::preLineWS(int spaceTabCount, int tabCount)
- {
- string ws;
-
- for (int i=0; i<tabCount; i++)
- ws += indentString;
-
- while ((spaceTabCount--) > 0)
- ws += string(" ");
-
- return ws;
-
- }
-
- /**
- * register an in-statement indent.
- */
- void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount,
- int minIndent, bool updateParenStack)
- {
- int inStatementIndent;
- int remainingCharNum = line.length() - i;
- int nextNonWSChar = 1;
-
- nextNonWSChar = getNextProgramCharDistance(line, i);
-
- // if indent is around the last char in the line, indent instead 2 spaces from the previous indent
- if (nextNonWSChar == remainingCharNum)
- {
- int previousIndent = spaceTabCount;
- if (!inStatementIndentStack->empty())
- previousIndent = inStatementIndentStack->back();
-
- inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent );
- if (updateParenStack)
- parenIndentStack->push_back( previousIndent );
- return;
- }
-
- if (updateParenStack)
- parenIndentStack->push_back(i+spaceTabCount);
-
- inStatementIndent = i + nextNonWSChar + spaceTabCount;
-
- if (i + nextNonWSChar < minIndent)
- inStatementIndent = minIndent + spaceTabCount;
-
- if (i + nextNonWSChar > maxInStatementIndent)
- inStatementIndent = indentLength*2 + spaceTabCount;
-
-
-
- if (!inStatementIndentStack->empty() &&
- inStatementIndent < inStatementIndentStack->back())
- inStatementIndent = inStatementIndentStack->back();
-
- inStatementIndentStack->push_back(inStatementIndent);
- }
-
- /**
- * get distance to the next non-white sspace, non-comment character in the line.
- * if no such character exists, return the length remaining to the end of the line.
- */
- int ASBeautifier::getNextProgramCharDistance(const string &line, int i)
- {
- bool inComment = false;
- int remainingCharNum = line.length() - i;
- int charDistance = 1;
- int ch;
-
- for (charDistance = 1; charDistance < remainingCharNum; charDistance++)
- {
- ch = line[i + charDistance];
- if (inComment)
- {
- if (line.COMPARE(i + charDistance, 2, AS_CLOSE_COMMENT) == 0)
- {
- charDistance++;
- inComment = false;
- }
- continue;
- }
- else if (isWhiteSpace(ch))
- continue;
- else if (ch == '/')
- {
- if (line.COMPARE(i + charDistance, 2, AS_OPEN_LINE_COMMENT) == 0)
- return remainingCharNum;
- else if (line.COMPARE(i + charDistance, 2, AS_OPEN_COMMENT) == 0)
- {
- charDistance++;
- inComment = true;
- }
- }
- else
- return charDistance;
- }
-
- return charDistance;
- }
-
-
- /**
- * check if a specific character can be used in a legal variable/method/class name
- *
- * @return legality of the char.
- * @param ch the character to be checked.
- */
- bool ASBeautifier::isLegalNameChar(char ch) const
- {
- return (isalnum(ch) //(ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9') ||
- || ch=='.' || ch=='_' || (!isCStyle && ch=='$') || (isCStyle && ch=='~'));
- }
-
-
- /**
- * check if a specific line position contains a header, out of several possible headers.
- *
- * @return a pointer to the found header. if no header was found then return NULL.
- */
- const string *ASBeautifier::findHeader(const string &line, int i, const vector<const string*> &possibleHeaders, bool checkBoundry)
- {
- int maxHeaders = possibleHeaders.size();
- const string *header = NULL;
- int p;
-
- for (p=0; p < maxHeaders; p++)
- {
- header = possibleHeaders[p];
-
- if (line.COMPARE(i, header->length(), *header) == 0)
- {
- // check that this is a header and not a part of a longer word
- // (e.g. not at its begining, not at its middle...)
-
- int lineLength = line.length();
- int headerEnd = i + header->length();
- char startCh = (*header)[0]; // first char of header
- char endCh = 0; // char just after header
- char prevCh = 0; // char just before header
-
- if (headerEnd < lineLength)
- {
- endCh = line[headerEnd];
- }
- if (i > 0)
- {
- prevCh = line[i-1];
- }
-
- if (!checkBoundry)
- {
- return header;
- }
- else if (prevCh != 0
- && isLegalNameChar(startCh)
- && isLegalNameChar(prevCh))
- {
- return NULL;
- }
- else if (headerEnd >= lineLength
- || !isLegalNameChar(startCh)
- || !isLegalNameChar(endCh))
- {
- return header;
- }
- else
- {
- return NULL;
- }
- }
- }
-
- return NULL;
- }
-
-
- /**
- * check if a specific character can be used in a legal variable/method/class name
- *
- * @return legality of the char.
- * @param ch the character to be checked.
- */
- bool ASBeautifier::isWhiteSpace(char ch) const
- {
- return (ch == ' ' || ch == '\t');
- }
-
- /**
- * find the index number of a string element in a container of strings
- *
- * @return the index number of element in the ocntainer. -1 if element not found.
- * @param container a vector of strings.
- * @param element the element to find .
- */
- int ASBeautifier::indexOf(vector<const string*> &container, const string *element)
- {
- vector<const string*>::const_iterator where;
-
- where= find(container.begin(), container.end(), element);
- if (where == container.end())
- return -1;
- else
- return where - container.begin();
- }
-
- /**
- * trim removes the white space surrounding a line.
- *
- * @return the trimmed line.
- * @param str the line to trim.
- */
- string ASBeautifier::trim(const string &str)
- {
-
- int start = 0;
- int end = str.length() - 1;
-
- while (start < end && isWhiteSpace(str[start]))
- start++;
-
- while (start <= end && isWhiteSpace(str[end]))
- end--;
-
- string returnStr(str, start, end+1-start);
- return returnStr;
- }
-
-#ifdef USES_NAMESPACE
-}
-#endif
-/*
- * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
- *
- * compiler_defines.h (1 January 1999)
- * by Tal Davidson (davidsont@bigfoot.com)
- * This file is a part of "Artistic Style" - an indentater and reformatter
- * of C, C++, C# and Java source files.
- *
- * The "Artistic Style" project, including all files needed to compile it,
- * is free software; you can redistribute it and/or use it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program.
- */
-
-
-#ifndef ASBEAUTIFIER_H
-#define ASBEAUTIFIER_H
-
-#include "ASResource.h"
-#include "compiler_defines.h"
-#include "ASSourceIterator.h"
-
-#include <string>
-#include <vector>
-
-
-using namespace std;
-
-namespace astyle
- {
-
- enum BracketMode { NONE_MODE, ATTACH_MODE, BREAK_MODE, BDAC_MODE };
- enum BracketType { NULL_TYPE = 0,
- DEFINITION_TYPE = 1,
- COMMAND_TYPE = 2,
- ARRAY_TYPE = 4,
- SINGLE_LINE_TYPE = 8};
-
-
- class ASBeautifier : protected ASResource
- {
- public:
- ASBeautifier();
- virtual ~ASBeautifier();
- virtual void init(ASSourceIterator* iter); // pointer to dynamically created iterator.
- virtual void init();
- virtual bool hasMoreLines() const;
- virtual string nextLine();
- virtual string beautify(const string &line);
- void setTabIndentation(int length = 4, bool forceTabs = false);
- void setSpaceIndentation(int length = 4);
- void setMaxInStatementIndentLength(int max);
- void setMinConditionalIndentLength(int min);
- void setClassIndent(bool state);
- void setSwitchIndent(bool state);
- void setCaseIndent(bool state);
- void setBracketIndent(bool state);
- void setBlockIndent(bool state);
- void setNamespaceIndent(bool state);
- void setLabelIndent(bool state);
- void setCStyle();
- void setJavaStyle();
- void setEmptyLineFill(bool state);
- void setPreprocessorIndent(bool state);
-
-
- protected:
- int getNextProgramCharDistance(const string &line, int i);
- bool isLegalNameChar(char ch) const;
- bool isWhiteSpace(char ch) const;
- const string *findHeader(const string &line, int i,
- const vector<const string*> &possibleHeaders,
- bool checkBoundry = true);
- string trim(const string &str);
- int indexOf(vector<const string*> &container, const string *element);
-
- private:
- ASBeautifier(const ASBeautifier &copy);
- void operator=(ASBeautifier&); // not to be implemented
-
- void initStatic();
- void registerInStatementIndent(const string &line, int i, int spaceTabCount,
- int minIndent, bool updateParenStack);
- string preLineWS(int spaceTabCount, int tabCount);
-
- static vector<const string*> headers;
- static vector<const string*> nonParenHeaders;
- static vector<const string*> preprocessorHeaders;
- static vector<const string*> preBlockStatements;
- static vector<const string*> assignmentOperators;
- static vector<const string*> nonAssignmentOperators;
-
- static bool calledInitStatic;
-
- ASSourceIterator *sourceIterator;
- vector<ASBeautifier*> *waitingBeautifierStack;
- vector<ASBeautifier*> *activeBeautifierStack;
- vector<int> *waitingBeautifierStackLengthStack;
- vector<int> *activeBeautifierStackLengthStack;
- vector<const string*> *headerStack;
- vector< vector<const string*>* > *tempStacks;
- vector<int> *blockParenDepthStack;
- vector<bool> *blockStatementStack;
- vector<bool> *parenStatementStack;
- vector<int> *inStatementIndentStack;
- vector<int> *inStatementIndentStackSizeStack;
- vector<int> *parenIndentStack;
- vector<bool> *bracketBlockStateStack;
- string indentString;
- const string *currentHeader;
- const string *previousLastLineHeader;
- const string *immediatelyPreviousAssignmentOp;
- const string *probationHeader;
- bool isInQuote;
- bool isInComment;
- bool isInCase;
- bool isInQuestion;
- bool isInStatement;
- bool isInHeader;
- bool isCStyle;
- bool isInOperator;
- bool isInTemplate;
- bool isInConst;
- bool isInDefine;
- bool isInDefineDefinition;
- bool classIndent;
- bool isInClassHeader;
- bool isInClassHeaderTab;
- bool switchIndent;
- bool caseIndent;
- bool namespaceIndent;
- bool bracketIndent;
- bool blockIndent;
- bool labelIndent;
- bool preprocessorIndent;
- bool isInConditional;
- bool isMinimalConditinalIndentSet;
- bool shouldForceTabIndentation;
- int minConditionalIndent;
- int parenDepth;
- int indentLength;
- int blockTabCount;
- unsigned int leadingWhiteSpaces;
- int maxInStatementIndent;
- int templateDepth;
- char quoteChar;
- char prevNonSpaceCh;
- char currentNonSpaceCh;
- char currentNonLegalCh;
- char prevNonLegalCh;
- int prevFinalLineSpaceTabCount;
- int prevFinalLineTabCount;
- bool emptyLineFill;
- bool backslashEndsPrevLine;
- int defineTabCount;
- };
-}
-
-#endif
-/*
- * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
- *
- * ASFormatter.cpp
- * by Tal Davidson (davidsont@bigfoot.com)
- * This file is a part of "Artistic Style" - an indentater and reformatter
- * of C, C++, C# and Java source files.
- *
- * The "Artistic Style" project, including all files needed to compile it,
- * is free software; you can redistribute it and/or use it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program.
- *
- *
- * Patches:
- * 26 November 1998 - Richard Bullington -
- * A correction of line-breaking in headers following '}',
-
- * was created using a variation of a patch by Richard Bullington.
- * 08 May 2004
- * applied ASFormatter450670.patch.bz2, ASFormatter.cpp.patch.bz2,
- * patch1_ssvb_patch.tar.gz
- */
-
-#include "compiler_defines.h"
-#include "ASFormatter.h"
-
-
-#include <string>
-#include <cctype>
-#include <vector>
-#include <algorithm>
-#include <iostream>
-
-
-#define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); }
-#define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container) ; }
-#define IS_A(a,b) ( ((a) & (b)) == (b))
-#ifdef USES_NAMESPACE
-using namespace std;
-
-namespace astyle
- {
-#endif
-
-
- bool ASFormatter::calledInitStatic = false;
- vector<const string*> ASFormatter::headers;
- vector<const string*> ASFormatter::nonParenHeaders;
- vector<const string*> ASFormatter::preprocessorHeaders;
- vector<const string*> ASFormatter::preDefinitionHeaders;
- vector<const string*> ASFormatter::preCommandHeaders;
- vector<const string*> ASFormatter::operators;
- vector<const string*> ASFormatter::assignmentOperators;
-
-
- /**
- * Constructor of ASFormatter
- */
- ASFormatter::ASFormatter()
- {
- staticInit();
-
- preBracketHeaderStack = NULL;
- bracketTypeStack = NULL;
- parenStack = NULL;
-
- sourceIterator = NULL;
- bracketFormatMode = NONE_MODE;
- shouldPadOperators = false;
- shouldPadParenthesies = false;
- shouldBreakOneLineBlocks = true;
- shouldBreakOneLineStatements = true;
- shouldConvertTabs = false;
- shouldBreakBlocks = false;
- shouldBreakClosingHeaderBlocks = false;
- shouldBreakClosingHeaderBrackets = false;
- shouldBreakElseIfs = false;
- }
-
- /**
- * Destructor of ASFormatter
- */
- ASFormatter::~ASFormatter()
- {
- DELETE_CONTAINER( preBracketHeaderStack );
- }
-
- /**
- * initialization of static data of ASFormatter.
- */
- void ASFormatter::staticInit()
- {
- if (calledInitStatic)
- return;
-
- calledInitStatic = true;
-
- headers.push_back(&AS_IF);
- headers.push_back(&AS_ELSE);
- headers.push_back(&AS_DO);
- headers.push_back(&AS_WHILE);
- headers.push_back(&AS_FOR);
- headers.push_back(&AS_SYNCHRONIZED);
- headers.push_back(&AS_TRY);
- headers.push_back(&AS_CATCH);
- headers.push_back(&AS_FINALLY);
- headers.push_back(&AS_SWITCH);
- headers.push_back(&AS_TEMPLATE);
- headers.push_back(&AS_FOREACH);
- headers.push_back(&AS_LOCK);
- headers.push_back(&AS_UNSAFE);
- headers.push_back(&AS_FIXED);
- headers.push_back(&AS_GET);
- headers.push_back(&AS_SET);
- headers.push_back(&AS_ADD);
- headers.push_back(&AS_REMOVE);
-
- nonParenHeaders.push_back(&AS_ELSE);
- nonParenHeaders.push_back(&AS_DO);
- nonParenHeaders.push_back(&AS_TRY);
- nonParenHeaders.push_back(&AS_FINALLY);
- nonParenHeaders.push_back(&AS_UNSAFE);
- nonParenHeaders.push_back(&AS_GET);
- nonParenHeaders.push_back(&AS_SET);
- nonParenHeaders.push_back(&AS_ADD);
- nonParenHeaders.push_back(&AS_REMOVE);
-
- // nonParenHeaders.push_back(&AS_TEMPLATE);
-
- preDefinitionHeaders.push_back(&AS_CLASS);
- preDefinitionHeaders.push_back(&AS_INTERFACE);
- preDefinitionHeaders.push_back(&AS_NAMESPACE);
- preDefinitionHeaders.push_back(&AS_STRUCT);
-
- preCommandHeaders.push_back(&AS_EXTERN);
- preCommandHeaders.push_back(&AS_THROWS);
- preCommandHeaders.push_back(&AS_CONST);
-
- preprocessorHeaders.push_back(&AS_BAR_DEFINE);
- //// DEVEL: removed the folowing lines
- ////preprocessorHeaders.push_back(&AS_BAR_INCLUDE);
- ////preprocessorHeaders.push_back(&AS_BAR_IF); // #if or #ifdef
- ////preprocessorHeaders.push_back(&AS_BAR_EL); // #else or #elif
- ////preprocessorHeaders.push_back(&AS_BAR_ENDIF);
-
- operators.push_back(&AS_PLUS_ASSIGN);
- operators.push_back(&AS_MINUS_ASSIGN);
- operators.push_back(&AS_MULT_ASSIGN);
- operators.push_back(&AS_DIV_ASSIGN);
- operators.push_back(&AS_MOD_ASSIGN);
- operators.push_back(&AS_OR_ASSIGN);
- operators.push_back(&AS_AND_ASSIGN);
- operators.push_back(&AS_XOR_ASSIGN);
- operators.push_back(&AS_EQUAL);
- operators.push_back(&AS_PLUS_PLUS);
- operators.push_back(&AS_MINUS_MINUS);
- operators.push_back(&AS_NOT_EQUAL);
- operators.push_back(&AS_GR_EQUAL);
- operators.push_back(&AS_GR_GR_GR_ASSIGN);
- operators.push_back(&AS_GR_GR_ASSIGN);
- operators.push_back(&AS_GR_GR_GR);
- operators.push_back(&AS_GR_GR);
- operators.push_back(&AS_LS_EQUAL);
- operators.push_back(&AS_LS_LS_LS_ASSIGN);
- operators.push_back(&AS_LS_LS_ASSIGN);
- operators.push_back(&AS_LS_LS_LS);
- operators.push_back(&AS_LS_LS);
- operators.push_back(&AS_ARROW);
- operators.push_back(&AS_AND);
- operators.push_back(&AS_OR);
- operators.push_back(&AS_COLON_COLON);
-
- //// BUGFIX: removed the folowing lines
- //// operators.push_back(&AS_PAREN_PAREN);
- //// operators.push_back(&AS_BLPAREN_BLPAREN);
-
- operators.push_back(&AS_PLUS);
- operators.push_back(&AS_MINUS);
- operators.push_back(&AS_MULT);
- operators.push_back(&AS_DIV);
- operators.push_back(&AS_MOD);
- operators.push_back(&AS_QUESTION);
- operators.push_back(&AS_COLON);
- operators.push_back(&AS_ASSIGN);
- operators.push_back(&AS_LS);
- operators.push_back(&AS_GR);
- operators.push_back(&AS_NOT);
- operators.push_back(&AS_BIT_OR);
- operators.push_back(&AS_BIT_AND);
- operators.push_back(&AS_BIT_NOT);
- operators.push_back(&AS_BIT_XOR);
- operators.push_back(&AS_OPERATOR);
- operators.push_back(&AS_COMMA);
- //BEGIN Content Patch patch1_ssvb_patch.tar.gz
- operators.push_back(&AS_SEMICOLON);
- //END Content Patch patch1_ssvb_patch.tar.gz
- operators.push_back(&AS_RETURN);
-
- assignmentOperators.push_back(&AS_PLUS_ASSIGN);
- assignmentOperators.push_back(&AS_MINUS_ASSIGN);
- assignmentOperators.push_back(&AS_MULT_ASSIGN);
- assignmentOperators.push_back(&AS_DIV_ASSIGN);
- assignmentOperators.push_back(&AS_MOD_ASSIGN);
- assignmentOperators.push_back(&AS_XOR_ASSIGN);
- assignmentOperators.push_back(&AS_OR_ASSIGN);
- assignmentOperators.push_back(&AS_AND_ASSIGN);
- assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN);
- assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN);
- assignmentOperators.push_back(&AS_ASSIGN);
- }
-
- /**
- * initialize the ASFormatter.
- *
- * init() should be called every time a ASFormatter object is to start
- * formatting a NEW source file.
- * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object
- * that will be used to iterate through the source code. This object will be
- * deleted during the ASFormatter's destruction, and thus should not be
- * deleted elsewhere.
- *
- * @param iter a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
- */
- void ASFormatter::init(ASSourceIterator *si)
- {
- ASBeautifier::init(si);
- sourceIterator = si;
-
- INIT_CONTAINER( preBracketHeaderStack, new vector<const string*> );
- INIT_CONTAINER( bracketTypeStack, new vector<BracketType> );
- bracketTypeStack->push_back(DEFINITION_TYPE);
- INIT_CONTAINER( parenStack, new vector<int> );
- parenStack->push_back(0);
-
- currentHeader = NULL;
- currentLine = string("");
- formattedLine = "";
- currentChar = ' ';
- previousCommandChar = ' ';
- previousNonWSChar = ' ';
- quoteChar = '"';
- charNum = 0;
- previousOperator = NULL;
-
- isVirgin = true;
- isInLineComment = false;
- isInComment = false;
- isInPreprocessor = false;
- doesLineStartComment = false;
- isInQuote = false;
- isSpecialChar = false;
- isNonParenHeader = true;
- foundPreDefinitionHeader = false;
- foundPreCommandHeader = false;
- foundQuestionMark = false;
- isInLineBreak = false;
- endOfCodeReached = false;
- isLineReady = false;
- isPreviousBracketBlockRelated = true;
- isInPotentialCalculation = false;
- //foundOneLineBlock = false;
- shouldReparseCurrentChar = false;
- passedSemicolon = false;
- passedColon = false;
- isInTemplate = false;
- shouldBreakLineAfterComments = false;
- isImmediatelyPostComment = false;
- isImmediatelyPostLineComment = false;
- isImmediatelyPostEmptyBlock = false;
-
- isPrependPostBlockEmptyLineRequested = false;
- isAppendPostBlockEmptyLineRequested = false;
- prependEmptyLine = false;
-
- foundClosingHeader = false;
- previousReadyFormattedLineLength = 0;
-
- isImmediatelyPostHeader = false;
- isInHeader = false;
- }
-
- /**
- * get the next formatted line.
- *
- * @return formatted line.
- */
-
- string ASFormatter::nextLine()
- {
- const string *newHeader;
- bool isCharImmediatelyPostComment = false;
- bool isPreviousCharPostComment = false;
- bool isCharImmediatelyPostLineComment = false;
- bool isInVirginLine = isVirgin;
- bool isCharImmediatelyPostOpenBlock = false;
- bool isCharImmediatelyPostCloseBlock = false;
- bool isCharImmediatelyPostTemplate = false;
- bool isCharImmediatelyPostHeader = false;
-
- if (!isFormattingEnabled())
- return ASBeautifier::nextLine();
-
- while (!isLineReady)
- {
- if (shouldReparseCurrentChar)
- shouldReparseCurrentChar = false;
- else if (!getNextChar())
- {
- breakLine();
- return beautify(readyFormattedLine);
- }
- else // stuff to do when reading a new character...
- {
- // make sure that a virgin '{' at the begining ofthe file will be treated as a block...
- if (isInVirginLine && currentChar == '{')
- previousCommandChar = '{';
- isPreviousCharPostComment = isCharImmediatelyPostComment;
- isCharImmediatelyPostComment = false;
- isCharImmediatelyPostTemplate = false;
- isCharImmediatelyPostHeader = false;
- }
-
- if (isInLineComment)
- {
- appendCurrentChar();
-
- // explicitely break a line when a line comment's end is found.
- if (/*bracketFormatMode == ATTACH_MODE &&*/ charNum+1 == currentLine.length())
- {
- isInLineBreak = true;
- isInLineComment = false;
- isImmediatelyPostLineComment = true;
- currentChar = 0; //make sure it is a neutral char.
- }
- continue;
- }
- else if (isInComment)
- {
- if (isSequenceReached(AS_CLOSE_COMMENT))
- {
- isInComment = false;
- isImmediatelyPostComment = true;
- appendSequence(AS_CLOSE_COMMENT);
- goForward(1);
- }
- else
- appendCurrentChar();
-
- continue;
- }
-
- // not in line comment or comment
-
- else if (isInQuote)
- {
- if (isSpecialChar)
- {
- isSpecialChar = false;
- appendCurrentChar();
- }
- else if (currentChar == '\\')
- {
- isSpecialChar = true;
- appendCurrentChar();
- }
- else if (quoteChar == currentChar)
- {
- isInQuote = false;
- appendCurrentChar();
- }
- else
- {
- appendCurrentChar();
- }
-
- continue;
- }
-
-
-
- // handle white space - needed to simplify the rest.
- if (isWhiteSpace(currentChar) || isInPreprocessor)
- {
- ////// DEVEL: if (isLegalNameChar(previousChar) && isLegalNameChar(peekNextChar()))
- appendCurrentChar();
- continue;
- }
-
- /* not in MIDDLE of quote or comment or white-space of any type ... */
-
- if (isSequenceReached(AS_OPEN_LINE_COMMENT))
- {
- isInLineComment = true;
- if (shouldPadOperators)
- appendSpacePad();
- appendSequence(AS_OPEN_LINE_COMMENT);
- goForward(1);
- continue;
- }
- else if (isSequenceReached(AS_OPEN_COMMENT))
- {
- isInComment = true;
- if (shouldPadOperators)
- appendSpacePad();
- appendSequence(AS_OPEN_COMMENT);
- goForward(1);
- continue;
- }
- else if (currentChar == '"' || currentChar == '\'')
- {
- isInQuote = true;
- quoteChar = currentChar;
- //// if (shouldPadOperators) // BUGFIX: these two lines removed. seem to be unneeded, and interfere with L"
- //// appendSpacePad(); // BUFFIX: TODO make sure the removal of these lines doesn't reopen old bugs...
- appendCurrentChar();
- continue;
- }
-
- /* not in quote or comment or white-space of any type ... */
-
-
- // check if in preprocessor
- // ** isInPreprocessor will be automatically reset at the begining
- // of a new line in getnextChar()
- if (currentChar == '#')
- isInPreprocessor = true;
-
- if (isInPreprocessor)
- {
- appendCurrentChar();
- continue;
- }
-
- /* not in preprocessor ... */
-
- if (isImmediatelyPostComment)
- {
- isImmediatelyPostComment = false;
- isCharImmediatelyPostComment = true;
- }
-
- if (isImmediatelyPostLineComment)
- {
- isImmediatelyPostLineComment = false;
- isCharImmediatelyPostLineComment = true;
- }
-
- if (shouldBreakLineAfterComments)
- {
- shouldBreakLineAfterComments = false;
- shouldReparseCurrentChar = true;
- breakLine();
- continue;
- }
-
- // reset isImmediatelyPostHeader information
- if (isImmediatelyPostHeader)
- {
- isImmediatelyPostHeader = false;
- isCharImmediatelyPostHeader = true;
-
- // Make sure headers are broken from their succeeding blocks
- // (e.g.
- // if (isFoo) DoBar();
- // should become
- // if (isFoo)
- // DoBar;
- // )
- // But treat else if() as a special case which should not be broken!
- if (shouldBreakOneLineStatements)
- {
- // if may break 'else if()'s, ythen simply break the line
-
- if (shouldBreakElseIfs)
- isInLineBreak = true;
-
- else
- {
- // make sure 'else if()'s are not broken.
-
- bool isInElseIf = false;
- const string *upcomingHeader;
-
- upcomingHeader = findHeader(headers);
- if (currentHeader == &AS_ELSE && upcomingHeader == &AS_IF)
- isInElseIf = true;
-
- if (!isInElseIf)
- isInLineBreak = true; ////BUGFIX: SHOULD NOT BE breakLine() !!!
- }
- }
- }
-
- if (passedSemicolon)
- {
- passedSemicolon = false;
- if (parenStack->back() == 0)
- {
- shouldReparseCurrentChar = true;
- isInLineBreak = true;
- continue;
- }
- }
-
- if (passedColon)
- {
- passedColon = false;
- if (parenStack->back() == 0)
- {
- shouldReparseCurrentChar = true;
- isInLineBreak = true;
- continue;
- }
- }
-
- // Check if in template declaration, e.g. foo<bar> or foo<bar,fig>
- // If so, set isInTemplate to true
- //
- if (!isInTemplate && currentChar == '<')
- {
- int templateDepth = 0;
- const string *oper;
- for (unsigned int i=charNum;
- i< currentLine.length();
- i += (oper ? oper->length() : 1) )
- {
- oper = ASBeautifier::findHeader(currentLine, i, operators);
-
- if (oper == &AS_LS)
- {
- templateDepth++;
- }
- else if (oper == &AS_GR)
- {
- templateDepth--;
- if (templateDepth == 0)
- {
- // this is a template!
- //
- isInTemplate = true;
- break;
- }
- }
- else if (oper == &AS_COMMA // comma, e.g. A<int, char>
- || oper == &AS_BIT_AND // reference, e.g. A<int&>
- || oper == &AS_MULT // pointer, e.g. A<int*>
- || oper == &AS_COLON_COLON) // ::, e.g. std::string
- {
- continue;
- }
- else if (!isLegalNameChar(currentLine[i]) && !isWhiteSpace(currentLine[i]))
- {
- // this is not a template -> leave...
- //
- isInTemplate = false;
- break;
- }
- }
- }
-
-
- // handle parenthesies
- //
- if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
- {
- parenStack->back()++;
- }
- else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>'))
- {
- parenStack->back()--;
- if (isInTemplate && parenStack->back() == 0)
- {
- isInTemplate = false;
- isCharImmediatelyPostTemplate = true;
- }
-
- // check if this parenthesis closes a header, e.g. if (...), while (...)
- //
- if (isInHeader && parenStack->back() == 0)
- {
- isInHeader = false;
- isImmediatelyPostHeader = true;
- }
-
- }
-
- // handle brackets
- //
- BracketType bracketType = NULL_TYPE;
-
- if (currentChar == '{')
- {
- bracketType = getBracketType();
- foundPreDefinitionHeader = false;
- foundPreCommandHeader = false;
-
- bracketTypeStack->push_back(bracketType);
- preBracketHeaderStack->push_back(currentHeader);
- currentHeader = NULL;
-
- isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE);
- }
- else if (currentChar == '}')
- {
- // if a request has been made to append a post block empty line,
- // but the block exists immediately before a closing bracket,
- // then there is not need for the post block empty line.
- //
- isAppendPostBlockEmptyLineRequested = false;
-
- if (!bracketTypeStack->empty())
- {
- bracketType = bracketTypeStack->back();
- bracketTypeStack->pop_back();
-
- isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE);
- }
-
- if (!preBracketHeaderStack->empty())
- {
- currentHeader = preBracketHeaderStack->back();
- preBracketHeaderStack->pop_back();
- }
- else
- currentHeader = NULL;
- }
-
- if (!IS_A(bracketType, ARRAY_TYPE))
- {
-
- if (currentChar == '{')
- {
- parenStack->push_back(0);
- }
- else if (currentChar == '}')
- {
- if (!parenStack->empty())
- {
- parenStack->pop_back();
- }
- }
-
- if (bracketFormatMode != NONE_MODE)
- {
- if (currentChar == '{')
- {
- if ( ( bracketFormatMode == ATTACH_MODE
- || bracketFormatMode == BDAC_MODE && bracketTypeStack->size()>=2
- && IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], COMMAND_TYPE) /*&& isInLineBreak*/)
- && !isCharImmediatelyPostLineComment )
- {
- appendSpacePad();
- if (!isCharImmediatelyPostComment // do not attach '{' to lines that end with /**/ comments.
- && previousCommandChar != '{'
- && previousCommandChar != '}'
- && previousCommandChar != ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';'
- appendCurrentChar(false);
- else
- appendCurrentChar(true);
- continue;
- }
- else if (bracketFormatMode == BREAK_MODE
- || bracketFormatMode == BDAC_MODE && bracketTypeStack->size()>=2
- && IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], DEFINITION_TYPE))
- {
- if ( shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE) )
- breakLine();
- appendCurrentChar();
- continue;
- }
- }
- else if (currentChar == '}')
- {
- // bool origLineBreak = isInLineBreak;
-
- // mark state of immediately after empty block
- // this state will be used for locating brackets that appear immedately AFTER an empty block (e.g. '{} \n}').
- if (previousCommandChar == '{')
- isImmediatelyPostEmptyBlock = true;
-
- if ( (!(previousCommandChar == '{' && isPreviousBracketBlockRelated) ) // this '{' does not close an empty block
- && (shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE)) // astyle is allowed to break on line blocks
- && !isImmediatelyPostEmptyBlock) // this '}' does not immediately follow an empty block
- {
- breakLine();
- appendCurrentChar();
- }
- else
- {
- // Content Patch ASFormatter.cpp.patch.bz2
- // if (!isCharImmediatelyPostComment)
- if (!isCharImmediatelyPostComment &&
- !isCharImmediatelyPostLineComment)
- isInLineBreak = false;
- appendCurrentChar();
- if (shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE))
- shouldBreakLineAfterComments = true;
- }
-
- if (shouldBreakBlocks)
- {
- isAppendPostBlockEmptyLineRequested =true;
- }
-
- continue;
- }
- }
- }
-
- if ( ( (previousCommandChar == '{'
- && isPreviousBracketBlockRelated)
-
- || (previousCommandChar == '}'
- && !isImmediatelyPostEmptyBlock // <--
- && isPreviousBracketBlockRelated
- && !isPreviousCharPostComment // <-- Fixes wrongly appended newlines after '}' immediately after comments... 10/9/1999
- && peekNextChar() != ' '))
-
- && (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE)) )
- {
- isCharImmediatelyPostOpenBlock = (previousCommandChar == '{');
- isCharImmediatelyPostCloseBlock = (previousCommandChar == '}');
-
- previousCommandChar = ' ';
- isInLineBreak = true; //<----
- }
-
- // reset block handling flags
- isImmediatelyPostEmptyBlock = false;
-
- // look for headers
- if (!isInTemplate)
- {
- if ( (newHeader = findHeader(headers)) != NULL)
- {
- foundClosingHeader = false;
- const string *previousHeader;
-
- // recognize closing headers of do..while, if..else, try..catch..finally
- if ( (newHeader == &AS_ELSE && currentHeader == &AS_IF)
- || (newHeader == &AS_WHILE && currentHeader == &AS_DO)
- || (newHeader == &AS_CATCH && currentHeader == &AS_TRY)
- || (newHeader == &AS_CATCH && currentHeader == &AS_CATCH)
- || (newHeader == &AS_FINALLY && currentHeader == &AS_TRY)
- || (newHeader == &AS_FINALLY && currentHeader == &AS_CATCH) )
- foundClosingHeader = true;
-
- previousHeader = currentHeader;
- currentHeader = newHeader;
-
- // If in ATTACH or LINUX bracket modes, attach closing headers (e.g. 'else', 'catch')
- // to their preceding bracket,
- // But do not perform the attachment if the shouldBreakClosingHeaderBrackets is set!
- if (!shouldBreakClosingHeaderBrackets && foundClosingHeader && (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE) && previousNonWSChar == '}')
- {
- isInLineBreak = false;
- appendSpacePad();
-
- if (shouldBreakBlocks)
- isAppendPostBlockEmptyLineRequested = false;
- }
-
- //Check if a template definition as been reached, e.g. template<class A>
- if (newHeader == &AS_TEMPLATE)
- {
- isInTemplate = true;
- }
-
- // check if the found header is non-paren header
- isNonParenHeader = ( find(nonParenHeaders.begin(), nonParenHeaders.end(),
- newHeader) != nonParenHeaders.end() );
- appendSequence(*currentHeader);
- goForward(currentHeader->length() - 1);
- // if padding is on, and a paren-header is found
- // then add a space pad after it.
- if (shouldPadOperators && !isNonParenHeader)
- appendSpacePad();
-
-
- // Signal that a header has been reached
- // *** But treat a closing while() (as in do...while)
- // as if it where NOT a header since a closing while()
- // should never have a block after it!
- if (!(foundClosingHeader && currentHeader == &AS_WHILE))
- {
- isInHeader = true;
- if (isNonParenHeader)
- {
- isImmediatelyPostHeader = true;
- isInHeader = false;
- }
- }
-
- if (currentHeader == &AS_IF && previousHeader == &AS_ELSE)
- isInLineBreak = false;
-
- if (shouldBreakBlocks)
- {
- if (previousHeader == NULL
- && !foundClosingHeader
- && !isCharImmediatelyPostOpenBlock)
- {
- isPrependPostBlockEmptyLineRequested = true;
- }
-
- if (currentHeader == &AS_ELSE
- || currentHeader == &AS_CATCH
- || currentHeader == &AS_FINALLY
- || foundClosingHeader)
- {
- isPrependPostBlockEmptyLineRequested = false;
- }
-
- if (shouldBreakClosingHeaderBlocks
- && isCharImmediatelyPostCloseBlock)
- {
- isPrependPostBlockEmptyLineRequested = true;
- }
-
- }
-
- continue;
- }
- else if ( (newHeader = findHeader(preDefinitionHeaders)) != NULL)
- {
- foundPreDefinitionHeader = true;
- appendSequence(*newHeader);
- goForward(newHeader->length() - 1);
-
- if (shouldBreakBlocks)
- isPrependPostBlockEmptyLineRequested = true;
-
- continue;
- }
- else if ( (newHeader = findHeader(preCommandHeaders)) != NULL)
- {
- foundPreCommandHeader = true;
- appendSequence(*newHeader);
- goForward(newHeader->length() - 1);
-
- continue;
- }
- }
-
- if (previousNonWSChar == '}' || currentChar == ';')
- {
- if (shouldBreakOneLineStatements && currentChar == ';'
- && (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE)))
- {
- passedSemicolon = true;
- }
-
- if (shouldBreakBlocks && currentHeader != NULL && parenStack->back() == 0)
- {
- isAppendPostBlockEmptyLineRequested = true;
- }
-
- if (currentChar != ';')
- currentHeader = NULL; //DEVEL: is this ok?
-
- foundQuestionMark = false;
- foundPreDefinitionHeader = false;
- foundPreCommandHeader = false;
- isInPotentialCalculation = false;
-
- }
-
- if (currentChar == ':'
- && shouldBreakOneLineStatements
- && !foundQuestionMark // not in a ... ? ... : ... sequence
- && !foundPreDefinitionHeader // not in a definition block (e.g. class foo : public bar
- && previousCommandChar != ')' // not immediately after closing paren of a method header, e.g. ASFormatter::ASFormatter(...) : ASBeautifier(...)
- && previousChar != ':' // not part of '::'
- && peekNextChar() != ':') // not part of '::'
- {
- passedColon = true;
- if (shouldBreakBlocks)
- isPrependPostBlockEmptyLineRequested = true;
- }
-
- if (currentChar == '?')
- foundQuestionMark = true;
-
- if (shouldPadOperators)
- {
- if ((newHeader = findHeader(operators)) != NULL)
- {
- bool shouldPad = (newHeader != &AS_COLON_COLON
- && newHeader != &AS_PAREN_PAREN
- && newHeader != &AS_BLPAREN_BLPAREN
- && newHeader != &AS_PLUS_PLUS
- && newHeader != &AS_MINUS_MINUS
- && newHeader != &AS_NOT
- && newHeader != &AS_BIT_NOT
- && newHeader != &AS_ARROW
- && newHeader != &AS_OPERATOR
- && !(newHeader == &AS_MINUS && isInExponent())
- && !(newHeader == &AS_PLUS && isInExponent())
- && previousOperator != &AS_OPERATOR
- && !((newHeader == &AS_MULT || newHeader == &AS_BIT_AND)
- && isPointerOrReference())
- && !( (isInTemplate || isCharImmediatelyPostTemplate)
- && (newHeader == &AS_LS || newHeader == &AS_GR))
- );
-
- if (!isInPotentialCalculation)
- if (find(assignmentOperators.begin(), assignmentOperators.end(), newHeader)
- != assignmentOperators.end())
- isInPotentialCalculation = true;
-
- // pad before operator
- if (shouldPad
- && !(newHeader == &AS_COLON && !foundQuestionMark)
- && newHeader != &AS_SEMICOLON
- && newHeader != &AS_COMMA)
- appendSpacePad();
- appendSequence(*newHeader);
- goForward(newHeader->length() - 1);
-
- // since this block handles '()' and '[]',
- // the parenStack must be updated here accordingly!
- if (newHeader == &AS_PAREN_PAREN
- || newHeader == &AS_BLPAREN_BLPAREN)
- parenStack->back()--;
-
- currentChar = (*newHeader)[newHeader->length() - 1];
- // pad after operator
- // but do not pad after a '-' that is a urinary-minus.
- if ( shouldPad && !(newHeader == &AS_MINUS && isUrinaryMinus()) )
- appendSpacePad();
-
- previousOperator = newHeader;
- continue;
- }
- }
- //BEGIN Content Patch patch1_ssvb_patch.tar.gz
- if (currentChar == '(' || currentChar == '[' )
- isInPotentialCalculation = true;
- //END Content Patch patch1_ssvb_patch.tar.gz
- if (shouldPadParenthesies)
- {
- if (currentChar == '(' || currentChar == '[' )
- {
- char peekedChar = peekNextChar();
-
- isInPotentialCalculation = true;
- appendCurrentChar();
- if (!(currentChar == '(' && peekedChar == ')')
- && !(currentChar == '[' && peekedChar == ']'))
- appendSpacePad();
- continue;
- }
- else if (currentChar == ')' || currentChar == ']')
- {
- char peekedChar = peekNextChar();
-
- if (!(previousChar == '(' && currentChar == ')')
- && !(previousChar == '[' && currentChar == ']'))
- appendSpacePad();
-
- appendCurrentChar();
-
- if (peekedChar != ';' && peekedChar != ',' && peekedChar != '.'
- && !(currentChar == ']' && peekedChar == '['))
- appendSpacePad();
- continue;
- }
- }
-
- appendCurrentChar();
- }
-
- // return a beautified (i.e. correctly indented) line.
-
- string beautifiedLine;
- int readyFormattedLineLength = trim(readyFormattedLine).length();
-
- if (prependEmptyLine
- && readyFormattedLineLength > 0
- && previousReadyFormattedLineLength > 0)
- {
- isLineReady = true; // signal that a readyFormattedLine is still waiting
- beautifiedLine = beautify("");
- }
- else
- {
- isLineReady = false;
- beautifiedLine = beautify(readyFormattedLine);
- }
-
- prependEmptyLine = false;
- previousReadyFormattedLineLength = readyFormattedLineLength;
-
- return beautifiedLine;
-
- }
-
-
- /**
- * check if there are any indented lines ready to be read by nextLine()
- *
- * @return are there any indented lines ready?
- */
- bool ASFormatter::hasMoreLines() const
- {
- if (!isFormattingEnabled())
- return ASBeautifier::hasMoreLines();
- else
- return !endOfCodeReached;
- }
-
- /**
- * check if formatting options are enabled, in addition to indentation.
- *
- * @return are formatting options enabled?
- */
- bool ASFormatter::isFormattingEnabled() const
- {
- return (bracketFormatMode != NONE_MODE
- || shouldPadOperators
- || shouldConvertTabs);
- }
-
- /**
- * set the bracket formatting mode.
- * options:
- * astyle::NONE_MODE no formatting of brackets.
- * astyle::ATTACH_MODE Java, K&R style bracket placement.
- * astyle::BREAK_MODE ANSI C/C++ style bracket placement.
- *
- * @param mode the bracket formatting mode.
- */
- void ASFormatter::setBracketFormatMode(BracketMode mode)
- {
- bracketFormatMode = mode;
- }
-
- /**
- * set closing header bracket breaking mode
- * options:
- * true brackets just before closing headers (e.g. 'else', 'catch')
- * will be broken, even if standard brackets are attached.
- * false closing header brackets will be treated as standard brackets.
- *
- * @param mode the closing header bracket breaking mode.
- */
- void ASFormatter::setBreakClosingHeaderBracketsMode(bool state)
- {
- shouldBreakClosingHeaderBrackets = state;
- }
-
- /**
- * set 'else if()' breaking mode
- * options:
- * true 'else' headers will be broken from their succeeding 'if' headers.
- * false 'else' headers will be attached to their succeeding 'if' headers.
- *
- * @param mode the 'else if()' breaking mode.
- */
- void ASFormatter::setBreakElseIfsMode(bool state)
- {
- shouldBreakElseIfs = state;
- }
-
- /**
- * set operator padding mode.
- * options:
- * true statement operators will be padded with spaces around them.
- * false statement operators will not be padded.
- *
- * @param mode the padding mode.
- */
- void ASFormatter::setOperatorPaddingMode(bool state)
- {
- shouldPadOperators = state;
- }
-
- /**
- * set parentheies padding mode.
- * options:
- * true statement parenthesies will be padded with spaces around them.
- * false statement parenthesies will not be padded.
- *
- * @param mode the padding mode.
- */
- void ASFormatter::setParenthesisPaddingMode(bool state)
- {
- shouldPadParenthesies = state;
- }
-
- /**
- * set option to break/not break one-line blocks
- *
- * @param state true = break, false = don't break.
- */
- void ASFormatter::setBreakOneLineBlocksMode(bool state)
- {
- shouldBreakOneLineBlocks = state;
- }
-
- /**
- * set option to break/not break lines consisting of multiple statements.
- *
- * @param state true = break, false = don't break.
- */
- void ASFormatter::setSingleStatementsMode(bool state)
- {
- shouldBreakOneLineStatements = state;
- }
-
- /**
- * set option to convert tabs to spaces.
- *
- * @param state true = convert, false = don't convert.
- */
- void ASFormatter::setTabSpaceConversionMode(bool state)
- {
- shouldConvertTabs = state;
- }
-
-
- /**
- * set option to break unrelated blocks of code with empty lines.
- *
- * @param state true = convert, false = don't convert.
- */
- void ASFormatter::setBreakBlocksMode(bool state)
- {
- shouldBreakBlocks = state;
- }
-
- /**
- * set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines.
- *
- * @param state true = convert, false = don't convert.
- */
- void ASFormatter::setBreakClosingHeaderBlocksMode(bool state)
- {
- shouldBreakClosingHeaderBlocks = state;
- }
-
- /**
- * check if a specific sequence exists in the current placement of the current line
- *
- * @return whether sequence has been reached.
- * @param sequence the sequence to be checked
- */
- bool ASFormatter::isSequenceReached(const string &sequence) const
- {
- return currentLine.COMPARE(charNum, sequence.length(), sequence) == 0;
-
- }
-
- /**
- * jump over several characters.
- *
- * @param i the number of characters to jump over.
- */
- void ASFormatter::goForward(int i)
- {
- while (--i >= 0)
- getNextChar();
- }
-
- /**
- * peek at the next unread character.
- *
- * @return the next unread character.
- */
- char ASFormatter::peekNextChar() const
- {
- int peekNum = charNum + 1;
- int len = currentLine.length();
- char ch = ' ';
-
- while (peekNum < len)
- {
- ch = currentLine[peekNum++];
- if (!isWhiteSpace(ch))
- return ch;
- }
-
- if (shouldConvertTabs && ch == '\t')
- ch = ' ';
-
- return ch;
- }
-
- /**
- * check if current placement is before a comment or line-comment
- *
- * @return is before a comment or line-comment.
- */
- bool ASFormatter::isBeforeComment() const
- {
- int peekNum = charNum + 1;
- int len = currentLine.length();
- // char ch = ' ';
- bool foundComment = false;
-
- for (peekNum = charNum + 1;
- peekNum < len && isWhiteSpace(currentLine[peekNum]);
- ++peekNum)
- ;
-
- if (peekNum < len)
- foundComment = ( currentLine.COMPARE(peekNum, 2, AS_OPEN_COMMENT) == 0
- || currentLine.COMPARE(peekNum, 2, AS_OPEN_LINE_COMMENT) == 0 );
-
- return foundComment;
- }
-
- /**
- * get the next character, increasing the current placement in the process.
- * the new character is inserted into the variable currentChar.
- *
- * @return whether succeded to recieve the new character.
- */
- bool ASFormatter::getNextChar()
- {
- isInLineBreak = false;
- bool isAfterFormattedWhiteSpace = false;
-
- if (shouldPadOperators && !isInComment && !isInLineComment
- && !isInQuote && !doesLineStartComment && !isInPreprocessor
- && !isBeforeComment())
- {
- //BEGIN Content Patch patch1_ssvb_patch.tar.gz
- char prevchar = ' ';
- char nextchar = peekNextChar();
-
- int len = formattedLine.length();
- // if (len > 0 && isWhiteSpace(formattedLine[len-1]))
- if (len > 0) prevchar = formattedLine[len-1];
- if (isWhiteSpace(prevchar) || prevchar == '(' || prevchar == '[' ||
- nextchar == ')' || nextchar == ']')
- {
- isAfterFormattedWhiteSpace = true;
- }
- //END Content Patch patch1_ssvb_patch.tar.gz
- }
-
- previousChar = currentChar;
- if (!isWhiteSpace(currentChar))
- {
- previousNonWSChar = currentChar;
- if (!isInComment && !isInLineComment && !isInQuote
- && !isSequenceReached(AS_OPEN_COMMENT)
- && !isSequenceReached(AS_OPEN_LINE_COMMENT) )
- previousCommandChar = previousNonWSChar;
- }
-
- unsigned int currentLineLength = currentLine.length();
-
- if (charNum+1 < currentLineLength
- && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment))
- {
- currentChar = currentLine[++charNum];
- if (isAfterFormattedWhiteSpace)
- while (isWhiteSpace(currentChar) && charNum+1 < currentLineLength)
- currentChar = currentLine[++charNum];
-
- if (shouldConvertTabs && currentChar == '\t')
- currentChar = ' ';
-
- return true;
- }
- // BEGIN Content patch ASFormatter450670.patch.bz2
- else if (isInLineComment && (charNum+1 == currentLineLength))
- {
- // fix BUG #450670
- currentChar = ' ';
- return true;
- }
- // END Content patch ASFormatter450670.patch.bz2
- else
- {
- if (sourceIterator->hasMoreLines())
- {
- currentLine = sourceIterator->nextLine();
- if (currentLine.length() == 0)
- {
- /*think*/ currentLine = string(" ");
- }
-
- // unless reading in the first line of the file,
- // break a new line.
- if (!isVirgin)
- isInLineBreak = true;
- else
- isVirgin = false;
-
- if (isInLineComment)
- isImmediatelyPostLineComment = true;
- isInLineComment = false;
-
- trimNewLine();
- currentChar = currentLine[charNum];
-
- // check if is in preprocessor right after the line break and line trimming
- if (previousNonWSChar != '\\')
- isInPreprocessor = false;
-
- if (shouldConvertTabs && currentChar == '\t')
- currentChar = ' ';
-
- return true;
- }
- else
- {
- endOfCodeReached = true;
- return false;
- }
- }
- }
-
- /**
- * jump over the leading white space in the current line,
- * IF the line does not begin a comment or is in a preprocessor definition.
- */
- void ASFormatter::trimNewLine()
- {
- unsigned int len = currentLine.length();
- charNum = 0;
-
- if (isInComment || isInPreprocessor)
- return;
-
- while (isWhiteSpace(currentLine[charNum]) && charNum+1 < len)
- ++charNum;
-
- doesLineStartComment = false;
- if (isSequenceReached(string("/*")))
- {
- charNum = 0;
- doesLineStartComment = true;
- }
- }
-
- /**
- * append a character to the current formatted line.
- * Unless disabled (via canBreakLine == false), first check if a
- * line-break has been registered, and if so break the
- * formatted line, and only then append the character into
- * the next formatted line.
- *
- * @param ch the character to append.
- * @param canBreakLine if true, a registered line-break
- */
- void ASFormatter::appendChar(char ch, bool canBreakLine)
- {
- if (canBreakLine && isInLineBreak)
- breakLine();
- formattedLine.append(1, ch);
- }
-
- /**
- * append the CURRENT character (curentChar)to the current
- * formatted line. Unless disabled (via canBreakLine == false),
- * first check if a line-break has been registered, and if so
- * break the formatted line, and only then append the character
- * into the next formatted line.
- *
- * @param canBreakLine if true, a registered line-break
- */
- void ASFormatter::appendCurrentChar(bool canBreakLine)
- {
- appendChar(currentChar, canBreakLine);
- }
-
- /**
- * append a string sequence to the current formatted line.
- * Unless disabled (via canBreakLine == false), first check if a
- * line-break has been registered, and if so break the
- * formatted line, and only then append the sequence into
- * the next formatted line.
- *
- * @param sequence the sequence to append.
- * @param canBreakLine if true, a registered line-break
- */
- void ASFormatter::appendSequence(const string &sequence, bool canBreakLine)
- {
- if (canBreakLine && isInLineBreak)
- breakLine();
- formattedLine.append(sequence);
- }
-
- /**
- * append a space to the current formattedline, UNLESS the
- * last character is already a white-space character.
- */
- void ASFormatter::appendSpacePad()
- {
- int len = formattedLine.length();
- if (len == 0 || !isWhiteSpace(formattedLine[len-1]))
- formattedLine.append(1, ' ');
- }
-
- /**
- * register a line break for the formatted line.
- */
- void ASFormatter::breakLine()
- {
- isLineReady = true;
- isInLineBreak = false;
-
- // queue an empty line prepend request if one exists
- prependEmptyLine = isPrependPostBlockEmptyLineRequested;
-
- readyFormattedLine = formattedLine;
- if (isAppendPostBlockEmptyLineRequested)
- {
- isAppendPostBlockEmptyLineRequested = false;
- isPrependPostBlockEmptyLineRequested = true;
- }
- else
- {
- isPrependPostBlockEmptyLineRequested = false;
- }
-
- formattedLine = "";
- }
-
- /**
- * check if the currently reached open-bracket (i.e. '{')
- * opens a:
- * - a definition type block (such as a class or namespace),
- * - a command block (such as a method block)
- * - a static array
- * this method takes for granted that the current character
- * is an opening bracket.
- *
- * @return the type of the opened block.
- */
- BracketType ASFormatter::getBracketType() const
- {
- BracketType returnVal;
-
- if (foundPreDefinitionHeader)
- returnVal = DEFINITION_TYPE;
- else
- {
- bool isCommandType;
- isCommandType = ( foundPreCommandHeader
- || ( currentHeader != NULL && isNonParenHeader )
- || ( previousCommandChar == ')' )
- || ( previousCommandChar == ':' && !foundQuestionMark )
- || ( previousCommandChar == ';' )
- || ( ( previousCommandChar == '{' || previousCommandChar == '}')
- && isPreviousBracketBlockRelated ) );
-
- returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE);
- }
-
- if (isOneLineBlockReached())
- returnVal = (BracketType) (returnVal | SINGLE_LINE_TYPE);
-
- return returnVal;
- }
-
- /**
- * check if the currently reached '*' or '&' character is
- * a pointer-or-reference symbol, or another operator.
- * this method takes for granted that the current character
- * is either a '*' or '&'.
- *
- * @return whether current character is a reference-or-pointer
- */
- bool ASFormatter::isPointerOrReference() const
- {
- bool isPR;
- isPR = ( !isInPotentialCalculation
- || IS_A(bracketTypeStack->back(), DEFINITION_TYPE)
- || (!isLegalNameChar(previousNonWSChar)
- && previousNonWSChar != ')'
- && previousNonWSChar != ']')
- );
-
- if (!isPR)
- {
- char nextChar = peekNextChar();
- isPR |= (!isWhiteSpace(nextChar)
- && nextChar != '-'
- && nextChar != '('
- && nextChar != '['
- && !isLegalNameChar(nextChar));
- }
-
- return isPR;
- }
-
-
- /**
- * check if the currently reached '-' character is
- * a urinary minus
- * this method takes for granted that the current character
- * is a '-'.
- *
- * @return whether the current '-' is a urinary minus.
- */
- bool ASFormatter::isUrinaryMinus() const
- {
- return ( (previousOperator == &AS_RETURN || !isalnum(previousCommandChar))
- && previousCommandChar != '.'
- && previousCommandChar != ')'
- && previousCommandChar != ']' );
- }
-
-
- /**
- * check if the currently reached '-' or '+' character is
- * part of an exponent, i.e. 0.2E-5.
- * this method takes for granted that the current character
- * is a '-' or '+'.
- *
- * @return whether the current '-' is in an exponent.
- */
- bool ASFormatter::isInExponent() const
- {
- int formattedLineLength = formattedLine.length();
- if (formattedLineLength >= 2)
- {
- char prevPrevFormattedChar = formattedLine[formattedLineLength - 2];
- char prevFormattedChar = formattedLine[formattedLineLength - 1];
-
- return ( (prevFormattedChar == 'e' || prevFormattedChar == 'E')
- && (prevPrevFormattedChar == '.' || isdigit(prevPrevFormattedChar)) );
- }
- else
- return false;
- }
-
- /**
- * check if a one-line bracket has been reached,
- * i.e. if the currently reached '{' character is closed
- * with a complimentry '}' elsewhere on the current line,
- *.
- * @return has a one-line bracket been reached?
- */
- bool ASFormatter::isOneLineBlockReached() const
- {
- bool isInComment = false;
- bool isInQuote = false;
- int bracketCount = 1;
- int currentLineLength = currentLine.length();
- int i = 0;
- char ch = ' ';
- char quoteChar = ' ';
-
- for (i = charNum + 1; i < currentLineLength; ++i)
- {
- ch = currentLine[i];
-
- if (isInComment)
- {
- if (currentLine.COMPARE(i, 2, "*/") == 0)
- {
- isInComment = false;
- ++i;
- }
- continue;
- }
-
- if (ch == '\\')
- {
- ++i;
- continue;
- }
-
- if (isInQuote)
- {
- if (ch == quoteChar)
- isInQuote = false;
- continue;
- }
-
- if (ch == '"' || ch == '\'')
- {
- isInQuote = true;
- quoteChar = ch;
- continue;
- }
-
- if (currentLine.COMPARE(i, 2, "//") == 0)
- break;
-
- if (currentLine.COMPARE(i, 2, "/*") == 0)
- {
- isInComment = true;
- ++i;
- continue;
- }
-
- if (ch == '{')
- ++bracketCount;
- else if (ch == '}')
- --bracketCount;
-
- if(bracketCount == 0)
- return true;
- }
-
- return false;
- }
-
-
- /**
- * check if one of a set of headers has been reached in the
- * current position of the current line.
- *
- * @return a pointer to the found header. Or a NULL if no header has been reached.
- * @param headers a vector of headers
- * @param checkBoundry
- */
- const string *ASFormatter::findHeader(const vector<const string*> &headers, bool checkBoundry)
- {
- return ASBeautifier::findHeader(currentLine, charNum, headers, checkBoundry);
- }
-
-
-
-#ifdef USES_NAMESPACE
-}
-#endif
-/*
- * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
- *
- * compiler_defines.h (1 January 1999)
- * by Tal Davidson (davidsont@bigfoot.com)
- * This file is a part of "Artistic Style" - an indentater and reformatter
- * of C, C++, C# and Java source files.
- *
- * The "Artistic Style" project, including all files needed to compile it,
- * is free software; you can redistribute it and/or use it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program.
- */
-
-
-#ifndef ASFORMATTER_H
-#define ASFORMATTER_H
-
-#include "ASBeautifier.h"
-//#include "enums.h"
-#include "compiler_defines.h"
-
-namespace astyle {
-
- class ASFormatter : public ASBeautifier
- {
- public:
- ASFormatter();
- virtual ~ASFormatter();
- virtual void init(ASSourceIterator* iter);
- virtual bool hasMoreLines() const;
- virtual string nextLine();
- void setBracketFormatMode(BracketMode mode);
- void setBreakClosingHeaderBracketsMode(bool state);
- void setOperatorPaddingMode(bool mode);
- void setParenthesisPaddingMode(bool mode);
- void setBreakOneLineBlocksMode(bool state);
- void setSingleStatementsMode(bool state);
- void setTabSpaceConversionMode(bool state);
- void setBreakBlocksMode(bool state);
- void setBreakClosingHeaderBlocksMode(bool state);
- void setBreakElseIfsMode(bool state);
-
- private:
- void ASformatter(ASFormatter &copy); // not to be imlpemented
- void operator=(ASFormatter&); // not to be implemented
- void staticInit();
- bool isFormattingEnabled() const;
- void goForward(int i);
- bool getNextChar();
- char peekNextChar() const;
- bool isBeforeComment() const;
- void trimNewLine();
- BracketType getBracketType() const;
- bool isPointerOrReference() const;
- bool isUrinaryMinus() const;
- bool isInExponent() const;
- bool isOneLineBlockReached() const;
- void appendChar(char ch, bool canBreakLine = true);
- void appendCurrentChar(bool canBreakLine = true);
- void appendSequence(const string &sequence, bool canBreakLine = true);
- void appendSpacePad();
- void breakLine();
- inline bool isSequenceReached(const string &sequence) const;
- const string *findHeader(const vector<const string*> &headers, bool checkBoundry = true);
-
- static vector<const string*> headers;
- static vector<const string*> nonParenHeaders;
- static vector<const string*> preprocessorHeaders;
- static vector<const string*> preDefinitionHeaders;
- static vector<const string*> preCommandHeaders;
- static vector<const string*> operators;
- static vector<const string*> assignmentOperators;
- static bool calledInitStatic;
-
- ASSourceIterator *sourceIterator;
- vector<const string*> *preBracketHeaderStack;
- vector<BracketType> *bracketTypeStack;
- vector<int> *parenStack;
- string readyFormattedLine;
- string currentLine;
- string formattedLine;
- const string *currentHeader;
- const string *previousOperator;
- char currentChar;
- char previousChar;
- char previousNonWSChar;
- char previousCommandChar;
- char quoteChar;
- unsigned int charNum;
- BracketMode bracketFormatMode;
- bool isVirgin;
- bool shouldPadOperators;
- bool shouldPadParenthesies;
- bool shouldConvertTabs;
- bool isInLineComment;
- bool isInComment;
- bool isInPreprocessor;
- bool isInTemplate; // true both in template definitions (e.g. template<class A>) and template usage (e.g. F<int>).
- bool doesLineStartComment;
- bool isInQuote;
- bool isSpecialChar;
- bool isNonParenHeader;
- bool foundQuestionMark;
- bool foundPreDefinitionHeader;
- bool foundPreCommandHeader;
- bool isInLineBreak;
- bool isInClosingBracketLineBreak;
- bool endOfCodeReached;
- bool isLineReady;
- bool isPreviousBracketBlockRelated;
- bool isInPotentialCalculation;
- //bool foundOneLineBlock;
- bool shouldBreakOneLineBlocks;
- bool shouldReparseCurrentChar;
- bool shouldBreakOneLineStatements;
- bool shouldBreakLineAfterComments;
- bool shouldBreakClosingHeaderBrackets;
- bool shouldBreakElseIfs;
- bool passedSemicolon;
- bool passedColon;
- bool isImmediatelyPostComment;
- bool isImmediatelyPostLineComment;
- bool isImmediatelyPostEmptyBlock;
-
- bool shouldBreakBlocks;
- bool shouldBreakClosingHeaderBlocks;
- bool isPrependPostBlockEmptyLineRequested;
- bool isAppendPostBlockEmptyLineRequested;
-
- bool prependEmptyLine;
- bool foundClosingHeader;
- int previousReadyFormattedLineLength;
-
- bool isInHeader;
- bool isImmediatelyPostHeader;
-
- };
-
-}
-
-#endif
-/*
-* Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
-*
-* ASResource.cpp
-* by Tal Davidson (davidsont@bigfoot.com)
-* This file is a part of "Artistic Style" - an indentater and reformatter
-* of C, C, C# and Java source files.
-*
- * The "Artistic Style" project, including all files needed to compile it,
- * is free software; you can redistribute it and/or use it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program.
-*/
-
-#include "compiler_defines.h"
-#include "ASResource.h"
-
-#include <string>
-
-
-#ifdef USES_NAMESPACE
-using namespace std;
-
-namespace astyle
- {
-#endif
-
- const string ASResource::AS_IF = string("if");
- const string ASResource::AS_ELSE = string ("else");
- const string ASResource::AS_FOR = string("for");
- const string ASResource::AS_DO = string("do");
- const string ASResource::AS_WHILE = string("while");
- const string ASResource::AS_SWITCH = string ("switch");
- const string ASResource::AS_CASE = string ("case");
- const string ASResource::AS_DEFAULT = string("default");
- const string ASResource::AS_CLASS = string("class");
- const string ASResource::AS_STRUCT = string("struct");
- const string ASResource::AS_UNION = string("union");
- const string ASResource::AS_INTERFACE = string("interface");
- const string ASResource::AS_NAMESPACE = string("namespace");
- const string ASResource::AS_EXTERN = string("extern");
- const string ASResource::AS_PUBLIC = string("public");
- const string ASResource::AS_PROTECTED = string("protected");
- const string ASResource::AS_PRIVATE = string("private");
- const string ASResource::AS_STATIC = string("static");
- const string ASResource::AS_SYNCHRONIZED = string("synchronized");
- const string ASResource::AS_OPERATOR = string("operator");
- const string ASResource::AS_TEMPLATE = string("template");
- const string ASResource::AS_TRY = string("try");
- const string ASResource::AS_CATCH = string("catch");
- const string ASResource::AS_FINALLY = string("finally");
- const string ASResource::AS_THROWS = string("throws");
- const string ASResource::AS_CONST = string("const");
-
- const string ASResource::AS_ASM = string("asm");
-
- const string ASResource::AS_BAR_DEFINE = string("#define");
- const string ASResource::AS_BAR_INCLUDE = string("#include");
- const string ASResource::AS_BAR_IF = string("#if");
- const string ASResource::AS_BAR_EL = string("#el");
- const string ASResource::AS_BAR_ENDIF = string("#endif");
-
- const string ASResource::AS_OPEN_BRACKET = string("{");
- const string ASResource::AS_CLOSE_BRACKET = string("}");
- const string ASResource::AS_OPEN_LINE_COMMENT = string("//");
- const string ASResource::AS_OPEN_COMMENT = string("/*");
- const string ASResource::AS_CLOSE_COMMENT = string("*/");
-
- const string ASResource::AS_ASSIGN = string("=");
- const string ASResource::AS_PLUS_ASSIGN = string("+=");
- const string ASResource::AS_MINUS_ASSIGN = string("-=");
- const string ASResource::AS_MULT_ASSIGN = string("*=");
- const string ASResource::AS_DIV_ASSIGN = string("/=");
- const string ASResource::AS_MOD_ASSIGN = string("%=");
- const string ASResource::AS_OR_ASSIGN = string("|=");
- const string ASResource::AS_AND_ASSIGN = string("&=");
- const string ASResource::AS_XOR_ASSIGN = string("^=");
- const string ASResource::AS_GR_GR_ASSIGN = string(">>=");
- const string ASResource::AS_LS_LS_ASSIGN = string("<<=");
- const string ASResource::AS_GR_GR_GR_ASSIGN = string(">>>=");
- const string ASResource::AS_LS_LS_LS_ASSIGN = string("<<<=");
- const string ASResource::AS_RETURN = string("return");
-
- const string ASResource::AS_EQUAL = string("==");
- const string ASResource::AS_PLUS_PLUS = string("++");
- const string ASResource::AS_MINUS_MINUS = string("--");
- const string ASResource::AS_NOT_EQUAL = string("!=");
- const string ASResource::AS_GR_EQUAL = string(">=");
- const string ASResource::AS_GR_GR = string(">>");
- const string ASResource::AS_GR_GR_GR = string(">>>");
- const string ASResource::AS_LS_EQUAL = string("<=");
- const string ASResource::AS_LS_LS = string("<<");
- const string ASResource::AS_LS_LS_LS = string("<<<");
- const string ASResource::AS_ARROW = string("->");
- const string ASResource::AS_AND = string("&&");
- const string ASResource::AS_OR = string("||");
- const string ASResource::AS_COLON_COLON = string("::");
- const string ASResource::AS_PAREN_PAREN = string("()");
- const string ASResource::AS_BLPAREN_BLPAREN = string("[]");
-
- const string ASResource::AS_PLUS = string("+");
- const string ASResource::AS_MINUS = string("-");
- const string ASResource::AS_MULT = string("*");
- const string ASResource::AS_DIV = string("/");
- const string ASResource::AS_MOD = string("%");
- const string ASResource::AS_GR = string(">");
- const string ASResource::AS_LS = string("<");
- const string ASResource::AS_NOT = string("!");
- const string ASResource::AS_BIT_OR = string("|");
- const string ASResource::AS_BIT_AND = string("&");
- const string ASResource::AS_BIT_NOT = string("~");
- const string ASResource::AS_BIT_XOR = string("^");
- const string ASResource::AS_QUESTION = string("?");
- const string ASResource::AS_COLON = string(":");
- const string ASResource::AS_COMMA = string(",");
- const string ASResource::AS_SEMICOLON = string(";");
-
- const string ASResource::AS_FOREACH = string("foreach");
- const string ASResource::AS_LOCK = string("lock");
- const string ASResource::AS_UNSAFE = string("unsafe");
- const string ASResource::AS_FIXED = string("fixed");
- const string ASResource::AS_GET = string("get");
- const string ASResource::AS_SET = string("set");
- const string ASResource::AS_ADD = string("add");
- const string ASResource::AS_REMOVE = string("remove");
-
-#ifdef USES_NAMESPACE
-}
-#endif
-
-
-/*
- * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
- *
- * compiler_defines.h (1 January 1999)
- * by Tal Davidson (davidsont@bigfoot.com)
- * This file is a part of "Artistic Style" - an indentater and reformatter
- * of C, C++, C# and Java source files.
- *
- * The "Artistic Style" project, including all files needed to compile it,
- * is free software; you can redistribute it and/or use it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program.
- */
-
-
-#ifndef ASRES_H
-#define ASRES_H
-
-#include "compiler_defines.h"
-#include "ASStreamIterator.h"
-
-#include <iostream>
-#include <fstream>
-#include <string>
-
-namespace astyle {
-
-class ASResource
- {
- public:
- static const string AS_IF, AS_ELSE;
- static const string AS_DO, AS_WHILE;
- static const string AS_FOR;
- static const string AS_SWITCH, AS_CASE, AS_DEFAULT;
- static const string AS_TRY, AS_CATCH, AS_THROWS, AS_FINALLY;
- static const string AS_PUBLIC, AS_PROTECTED, AS_PRIVATE;
- static const string AS_CLASS, AS_STRUCT, AS_UNION, AS_INTERFACE, AS_NAMESPACE, AS_EXTERN;
- static const string AS_STATIC;
- static const string AS_CONST;
- static const string AS_SYNCHRONIZED;
- static const string AS_OPERATOR, AS_TEMPLATE;
- static const string AS_OPEN_BRACKET, AS_CLOSE_BRACKET;
- static const string AS_OPEN_LINE_COMMENT, AS_OPEN_COMMENT, AS_CLOSE_COMMENT;
- static const string AS_BAR_DEFINE, AS_BAR_INCLUDE, AS_BAR_IF, AS_BAR_EL, AS_BAR_ENDIF;
- static const string AS_RETURN;
- static const string AS_ASSIGN, AS_PLUS_ASSIGN, AS_MINUS_ASSIGN, AS_MULT_ASSIGN;
- static const string AS_DIV_ASSIGN, AS_MOD_ASSIGN, AS_XOR_ASSIGN, AS_OR_ASSIGN, AS_AND_ASSIGN;
- static const string AS_GR_GR_ASSIGN, AS_LS_LS_ASSIGN, AS_GR_GR_GR_ASSIGN, AS_LS_LS_LS_ASSIGN;
- static const string AS_EQUAL, AS_PLUS_PLUS, AS_MINUS_MINUS, AS_NOT_EQUAL, AS_GR_EQUAL, AS_GR_GR_GR, AS_GR_GR;
- static const string AS_LS_EQUAL, AS_LS_LS_LS, AS_LS_LS, AS_ARROW, AS_AND, AS_OR;
- static const string AS_COLON_COLON, AS_PAREN_PAREN, AS_BLPAREN_BLPAREN;
- static const string AS_PLUS, AS_MINUS, AS_MULT, AS_DIV, AS_MOD, AS_GR, AS_LS;
- static const string AS_NOT, AS_BIT_XOR, AS_BIT_OR, AS_BIT_AND, AS_BIT_NOT;
- static const string AS_QUESTION, AS_COLON, AS_SEMICOLON, AS_COMMA;
- static const string AS_ASM;
- static const string AS_FOREACH, AS_LOCK, AS_UNSAFE, AS_FIXED;
- static const string AS_GET, AS_SET, AS_ADD, AS_REMOVE;
- };
-}
-#endif
-
-#ifndef ASSOURCEITERATOR_H
-#define ASSOURCEITERATOR_H
-
-#include <string>
-#include "compiler_defines.h"
-
-namespace astyle
- {
-
- class ASSourceIterator
- {
- public:
- virtual bool hasMoreLines() const = 0;
- virtual std::string nextLine() = 0;
- };
-}
-
-#endif
-#include "compiler_defines.h"
-#include "ASStreamIterator.h"
-
-#include <iostream>
-#include <fstream>
-#include <string>
-
-using namespace astyle;
-
-ASStreamIterator::ASStreamIterator(istream *in)
-{
- inStream = in;
-}
-
-ASStreamIterator::~ASStreamIterator()
-{
- delete inStream;
-}
-
-
-bool ASStreamIterator::hasMoreLines() const
- {
- if (*inStream)
- return true;
- else
- return false;
- }
-
-/*
-string ASStreamIterator::nextLine()
-{
- char theInChar;
- char peekedChar;
- int theBufferPosn = 0;
-
- //
- // treat '\n', '\r', '\n\r' and '\r\n' as an endline.
- //
- while (theBufferPosn < 2047 && inStream->get(theInChar))
- // while not eof
- {
- if (theInChar != '\n' && theInChar != '\r')
- {
- buffer[theBufferPosn] = theInChar;
- theBufferPosn++;
- }
- else
- {
- peekedChar = inStream->peek();
- if (peekedChar != theInChar && (peekedChar == '\r' || peekedChar == '\n') )
- {
- inStream->get(theInChar);
- }
- break;
- }
- }
- buffer[theBufferPosn] = '\0';
-
- return string(buffer);
-}
-*/
-
-
-string ASStreamIterator::nextLine()
-{
- char *srcPtr;
- char *filterPtr;
-
- inStream->getline(buffer, 2047);
- srcPtr = filterPtr = buffer;
-
- while (*srcPtr != 0)
- {
- if (*srcPtr != '\r')
- *filterPtr++ = *srcPtr;
- srcPtr++;
- }
- *filterPtr = 0;
-
- return string(buffer);
-}
-
-/*
- * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
- *
- * compiler_defines.h (1 January 1999)
- * by Tal Davidson (davidsont@bigfoot.com)
- * This file is a part of "Artistic Style" - an indentater and reformatter
- * of C, C++, C# and Java source files.
- *
- * The "Artistic Style" project, including all files needed to compile it,
- * is free software; you can redistribute it and/or use it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program.
- */
-
-
-#ifndef ASSTREAMITERATOR_H
-#define ASSTREAMITERATOR_H
-
-#include "ASSourceIterator.h"
-
-using namespace std;
-
-namespace astyle
- {
- class ASStreamIterator :
- public ASSourceIterator
- {
- public:
- ASStreamIterator(istream *in);
- virtual ~ASStreamIterator();
- bool hasMoreLines() const;
- string nextLine();
-
- private:
- istream * inStream;
- char buffer[2048];
- };
-
-}
-
-#endif
-/***************************************************************************
- charcodes.cpp - description
- -------------------
- begin : Wed Nov 24 2003
- copyright : (C) 2003 by André imon
- email : andre.simon1@gmx.de
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-// FILE SHOULD BE REMOVED FROM PROJECT
-
-#ifndef CHAR_CODES
-#define CHAR_CODES
-
-#ifdef _WIN32
-
-#define AUML_LC 228
-#define OUML_LC 246
-#define UUML_LC 252
-
-#define AUML_UC 196
-#define OUML_UC 214
-#define UUML_UC 220
-
-
-#define AACUTE_LC 225
-#define EACUTE_LC 233
-#define OACUTE_LC 243
-#define UACUTE_LC 250
-
-#define AACUTE_UC 193
-#define EACUTE_UC 201
-#define OACUTE_UC 211
-#define UACUTE_UC 218
-
-#define AGRAVE_LC 224
-#define EGRAVE_LC 232
-#define OGRAVE_LC 242
-#define UGRAVE_LC 249
-
-#define AGRAVE_UC 192
-#define EGRAVE_UC 200
-#define OGRAVE_UC 210
-#define UGRAVE_UC 217
-
-#define SZLIG 223
-
-/* DOS CONSOLE CODES
-#define AUML_LC 132
-#define OUML_LC 148
-#define UUML_LC 129
-
-#define AUML_UC 142
-#define OUML_UC 153
-#define UUML_UC 154
-
-
-#define AACUTE_LC 160
-#define EACUTE_LC 130
-#define OACUTE_LC 162
-#define UACUTE_LC 163
-
-#define AACUTE_UC 181
-#define EACUTE_UC 144
-#define OACUTE_UC 224
-#define UACUTE_UC 233
-
-#define AGRAVE_LC 133
-#define EGRAVE_LC 138
-#define OGRAVE_LC 149
-#define UGRAVE_LC 151
-
-#define AGRAVE_UC 183
-#define EGRAVE_UC 212
-#define OGRAVE_UC 227
-#define UGRAVE_UC 235
-
-#define SZLIG 225
-*/
-
-#else
-
-#define AUML_LC 164
-#define OUML_LC 182
-#define UUML_LC 188
-
-#define AUML_UC 132
-#define OUML_UC 150
-#define UUML_UC 156
-
-
-#define AACUTE_LC 161
-#define EACUTE_LC 169
-#define OACUTE_LC 179
-#define UACUTE_LC 186
-
-#define AACUTE_UC 129
-#define EACUTE_UC 137
-#define OACUTE_UC 147
-#define UACUTE_UC 154
-
-#define AGRAVE_LC 160
-#define EGRAVE_LC 168
-#define OGRAVE_LC 178
-#define UGRAVE_LC 185
-
-#define AGRAVE_UC 128
-#define EGRAVE_UC 136
-#define OGRAVE_UC 146
-#define UGRAVE_UC 153
-
-#define SZLIG 159
-
-#endif
-
-#endif
-/***************************************************************************
- cmdlineoptions.cpp - description
- -------------------
- begin : Sun Nov 25 2001
- copyright : (C) 2001 by André Simon
- email : andre.simon1@gmx.de
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#include "cmdlineoptions.h"
-
-using namespace std;
-
-/* Siehe man getopt (3)
- Konstruktor legt Optionen und Argumente fest
-*/
-CmdLineOptions::CmdLineOptions(int argc, char *argv[]):
- numberSpaces(0),
- wrappingStyle(highlight::WRAP_DISABLED),
- outputType (highlight::HTML),
- opt_language (false),
- opt_include_style (false),
- opt_help (false),
- opt_version (false),
- opt_verbose (false),
- opt_linenumbers (false),
- opt_style (false),
- opt_batch_mode (false),
- opt_fragment (false) ,
- opt_attach_line_anchors (false),
- opt_show_themes (false),
- opt_show_langdefs (false),
- opt_printindex(false),
- opt_quiet(false),
- opt_xslfo_fop(false),
- opt_replacequotes(false),
- opt_print_progress(false),
- opt_fill_zeroes(false),
- opt_stylepath_explicit(false),
- opt_force_output(false),
- configFileRead(false),
- helpLang("en"),
- charset("ISO-8859-1")
-{
-
- loadConfigurationFile();
-
- int c, option_index = 0;
- static struct option long_options[] =
- {
- {OPT_OUT, 1, 0, S_OPT_OUT},
- {OPT_IN, 1, 0, S_OPT_IN},
- {OPT_SYNTAX, 1, 0, S_OPT_SYNTAX},
- {OPT_VERBOSE, 0, 0, S_OPT_VERBOSE},
- {OPT_INC_STYLE, 0, 0, S_OPT_INC_STYLE},
- {OPT_HELP, 0, 0, S_OPT_HELP},
- {OPT_HELPINT, 1, 0, S_OPT_HELPINT},
- {OPT_LINENO,0,0,S_OPT_LINENO},
- {OPT_STYLE, 1,0,S_OPT_STYLE},
- {OPT_STYLE_OUT, 1, 0,S_OPT_STYLE_OUT},
- {OPT_STYLE_IN, 1, 0,S_OPT_STYLE_IN},
- {OPT_DELTABS,1,0,S_OPT_DELTABS},
- {OPT_XHTML, 0,0,S_OPT_XHTML},
- {OPT_RTF, 0,0,S_OPT_RTF},
- {OPT_TEX,0, 0,S_OPT_TEX},
- {OPT_LATEX,0, 0,S_OPT_LATEX},
- {OPT_XSLFO,0, 0,S_OPT_XSLFO},
- {OPT_ANSI,0, 0,S_OPT_ANSI},
- {OPT_XML,0, 0,S_OPT_XML},
- {OPT_BATCHREC,1,0,S_OPT_BATCHREC},
- {OPT_FRAGMENT,0,0,S_OPT_FRAGMENT},
- {OPT_ANCHORS, 0,0,S_OPT_ANCHORS },
- {OPT_LISTTHEMES, 0,0,S_OPT_LISTTHEMES },
- {OPT_LISTLANGS, 0,0,S_OPT_LISTLANGS },
- {OPT_OUTDIR,1,0,S_OPT_OUTDIR},
- {OPT_VERSION,0,0,0},
- {OPT_FORMATSTYLE,1,0,S_OPT_FORMATSTYLE},
- {OPT_DATADIR,1,0,S_OPT_DATADIR},
- {OPT_ADDDATADIR,1,0,S_OPT_ADDDATADIR},
- {OPT_INDEXFILE,0,0,S_OPT_INDEXFILE},
- {OPT_WRAP,0,0,S_OPT_WRAP},
- {OPT_WRAPSIMPLE,0,0,S_OPT_WRAPSIMPLE},
- {OPT_QUIET,0,0,S_OPT_QUIET},
- {OPT_REPLACE_QUOTES,0,0,S_OPT_REPLACE_QUOTES},
- {OPT_PROGRESSBAR,0,0,S_OPT_PROGRESSBAR},
- {OPT_FILLZEROES,0,0,S_OPT_FILLZEROES},
- {OPT_ENCODING,1,0,S_OPT_ENCODING},
-
- //remove as soon as APAche fixes the bug in FOP (0.20.5)
- {OPT_FOP,0,0,S_OPT_FOP},
-
- //deprecated
- {OPT_CSSOUT,1,0,0},
- {OPT_CSSIN,1,0,0},
- {OPT_INC_CSS,0,0,0},
- {OPT_FORCE_OUTPUT,0,0,0},
-
- {0, 0, 0, 0}
- };
-
- while (1)
- {
- c = getopt_long (argc, argv,S_OPTIONS_STRING,long_options, &option_index);
- if (c == -1)
- break;
-
- switch (c)
- {
- case 0: // long options
- if (long_options[option_index].name==OPT_VERSION) {
- opt_version = true;
- }
- if (long_options[option_index].name==OPT_CSSOUT) {
- styleOutFilename=string(optarg);
- printDeprecatedWarning(OPT_CSSOUT, OPT_STYLE_OUT);
- }
- if (long_options[option_index].name==OPT_CSSIN) {
- styleInFilename=string(optarg);
- printDeprecatedWarning(OPT_CSSIN, OPT_STYLE_IN);
- }
- if (long_options[option_index].name==OPT_INC_CSS) {
- opt_include_style = true;
- printDeprecatedWarning(OPT_INC_CSS, OPT_INC_STYLE);
- }
- if (long_options[option_index].name==OPT_FORCE_OUTPUT) {
- opt_force_output = true;
- }
- break;
- case S_OPT_OUT:
- outFilename=string(optarg);
- break;
- case S_OPT_IN:
- inputFileNames.push_back(string(optarg));
- break;
- case S_OPT_STYLE_OUT:
- styleOutFilename=string(optarg);
- opt_stylepath_explicit=true;
- break;
- case S_OPT_STYLE_IN:
- styleInFilename=string(optarg);
- break;
- case S_OPT_VERBOSE:
- opt_verbose = true;
- break;
- case S_OPT_QUIET:
- opt_quiet = true;
- break;
- case S_OPT_INC_STYLE:
- opt_include_style = true;
- break;
- case S_OPT_HELPINT:
- helpLang=string(optarg);
- case S_OPT_HELP:
- opt_help = true;
- break;
- case S_OPT_LINENO:
- opt_linenumbers = true;
- break;
- case '?':
- //opt_help = true;
- break;
- case S_OPT_STYLE:
- styleName=string(optarg);
- opt_style = true;
- break;
- case S_OPT_SYNTAX:
- language=string(optarg);
- opt_language = true;
- break;
- case S_OPT_DELTABS:
- numberSpaces = StringTools::str2int (string(optarg));
- break;
- case S_OPT_XHTML:
- outputType=highlight::XHTML;
- break;
- case S_OPT_RTF:
- outputType=highlight::RTF;
- break;
- case S_OPT_TEX:
- outputType=highlight::TEX;
- break;
- case S_OPT_LATEX:
- outputType=highlight::LATEX;
- break;
- case S_OPT_XSLFO:
- outputType=highlight::XSLFO;
- break;
- case S_OPT_ANSI:
- outputType=highlight::ANSI;
- break;
- case S_OPT_XML:
- outputType=highlight::XML;
- break;
- case S_OPT_BATCHREC:
- opt_batch_mode = true;
- readDirectory(string(optarg));
- break;
- case S_OPT_FRAGMENT:
- opt_fragment = true;
- break;
- case S_OPT_ANCHORS:
- opt_attach_line_anchors = true;
- break;
- case S_OPT_LISTTHEMES:
- opt_show_themes = true;
- break;
- case S_OPT_LISTLANGS:
- opt_show_langdefs = true;
- break;
- case S_OPT_OUTDIR:
- outDirectory = validateDirPath(string(optarg));
- break;
- case S_OPT_FORMATSTYLE:
- indentScheme =string(optarg);
- break;
- case S_OPT_ENCODING:
- charset =string(optarg);
- break;
- case S_OPT_DATADIR:
- dataDir=validateDirPath(string(optarg));
- break;
- case S_OPT_ADDDATADIR:
- additionalDataDir=validateDirPath(string(optarg));
- break;
- case S_OPT_INDEXFILE:
- opt_printindex=true;
- break;
- case S_OPT_WRAPSIMPLE:
- wrappingStyle = highlight::WRAP_SIMPLE;
- break;
- case S_OPT_WRAP:
- wrappingStyle = highlight::WRAP_DEFAULT;
- break;
- case S_OPT_FOP:
- opt_xslfo_fop=true;
- break;
- case S_OPT_REPLACE_QUOTES:
- opt_replacequotes=true;
- break;
- case S_OPT_PROGRESSBAR:
- opt_print_progress=true;
- break;
- case S_OPT_FILLZEROES:
- opt_fill_zeroes=true;
- break;
- default:
- cerr <<"higlight: Unknown option " <<c<< endl;
- }
- }
-
- if (optind < argc) //still args left
- {
- if (inputFileNames.empty()) {
- while (optind < argc){
- inputFileNames.push_back(string(argv[optind++]));
- }
- }
- } else if (inputFileNames.empty()) {
- inputFileNames.push_back("");
- }
- if (printDebugInfo() && configFileRead) {
- cout << "Configuration file \""<<configFilePath<<"\" was read.\n";
- }
-}
-
-CmdLineOptions::~CmdLineOptions(){
-}
-
-const string &CmdLineOptions::getSingleOutFilename()
- {
- if (!inputFileNames.empty() && !outDirectory.empty()) {
- if (outFilename.empty()) {
- outFilename = outDirectory;
- int delim = getSingleInFilename().find_last_of(Platform::pathSeparator)+1;
- outFilename += getSingleInFilename().substr((delim>-1)?delim:0)
- + getOutFileSuffix();
- }
- }
- return outFilename;
- }
-
-const string &CmdLineOptions::getSingleInFilename() const
- {
- return inputFileNames[0];
- }
-
-const string &CmdLineOptions::getOutDirectory()
- {
- if (!outFilename.empty() && !enableBatchMode()){
- outDirectory=getDirName(outFilename);
- }
- return outDirectory;
- }
-
-const string CmdLineOptions::getStyleOutFilename() const
- {
- if (!styleOutFilename.empty()) return styleOutFilename;
- return (outputType==highlight::HTML ||
- outputType==highlight::XHTML)? "highlight.css":"highlight.sty";
- }
-const string &CmdLineOptions::getStyleInFilename() const
- {
- return styleInFilename;
- }
-int CmdLineOptions::getNumberSpaces() const
- {
- return numberSpaces;
- }
-bool CmdLineOptions::printVersion()const
- {
- return opt_version;
- }
-bool CmdLineOptions::printHelp()const
- {
- return opt_help;
- }
-bool CmdLineOptions::printDebugInfo()const
- {
- return opt_verbose;
- }
-bool CmdLineOptions::quietMode()const
- {
- return opt_quiet;
- }
-bool CmdLineOptions::includeStyleDef()const
- {
- return opt_include_style;
- }
-
-bool CmdLineOptions::formatSupportsExtStyle(){
- return outputType==highlight::HTML ||
- outputType==highlight::XHTML ||
- outputType==highlight::LATEX ||
- outputType==highlight::TEX;
-}
-
-bool CmdLineOptions::printLineNumbers()const
- {
- return opt_linenumbers;
- }
-
-string CmdLineOptions::getStyleName()const
- {
- return ( ( opt_style) ? styleName+".style" : "kwrite.style" );
- }
-bool CmdLineOptions::enableBatchMode()const{
- return inputFileNames.size()>1 || opt_batch_mode;
-}
-bool CmdLineOptions::fragmentOutput()const{
- return opt_fragment;
-}
-string CmdLineOptions::getOutFileSuffix()const{
- switch (outputType){
- case highlight::XHTML: return ".xhtml";
- case highlight::RTF: return ".rtf";
- case highlight::TEX:
- case highlight::LATEX: return ".tex";
- case highlight::XSLFO: return ".fo";
- case highlight::XML: return ".xml";
- default: return ".html";
- }
-}
-string CmdLineOptions::getDirName(const string & path) {
- size_t dirNameLength=path.rfind(Platform::pathSeparator);
- return (dirNameLength==string::npos)?string():path.substr(0, dirNameLength+1);
-}
-bool CmdLineOptions::attachLineAnchors()const{
- return opt_attach_line_anchors;
-}
-bool CmdLineOptions::showThemes()const{
- return opt_show_themes;
-}
-bool CmdLineOptions::showLangdefs()const{
- return opt_show_langdefs;
-}
-bool CmdLineOptions::outDirGiven()const{
- return !outFilename.empty();
-}
-bool CmdLineOptions::fopCompatible() const {
- return opt_xslfo_fop;
-}
-bool CmdLineOptions::replaceQuotes() const {
- return opt_replacequotes;
-}
-bool CmdLineOptions::getFlag( const string& paramVal){
- return StringTools::lowerCase(paramVal)=="true";
-}
-bool CmdLineOptions::formattingEnabled(){
- return !indentScheme.empty();
-}
-bool CmdLineOptions::dataDirGiven()const {
- return !dataDir.empty();
-}
-bool CmdLineOptions::additionalDataDirGiven()const {
- return !additionalDataDir.empty();
-}
-const string &CmdLineOptions::getDataDir() const {
- return dataDir;
-}
-const string &CmdLineOptions::getIndentScheme() const {
- return indentScheme;
-}
-const string &CmdLineOptions::getAdditionalDataDir()const{
- return additionalDataDir;
-}
-const string &CmdLineOptions::getLanguage() const {
- return language;
-}
-const string&CmdLineOptions::getCharSet() const{
- return charset;
-}
-bool CmdLineOptions::printIndexFile() const{
- return opt_printindex && (outputType==highlight::HTML ||
- outputType==highlight::XHTML);
-}
-bool CmdLineOptions::printProgress() const{
- return opt_print_progress;
-}
-bool CmdLineOptions::fillLineNrZeroes() const{
- return opt_fill_zeroes;
-}
-bool CmdLineOptions::syntaxGiven() const{
- return opt_language;
-}
-bool CmdLineOptions::omitEncodingName() const{
- return StringTools::lowerCase(charset)=="none";
-}
-bool CmdLineOptions::forceOutput() const{
- return opt_force_output;
-}
-const string CmdLineOptions::getHelpLang()const{
- return helpLang+".help";
-}
-highlight::WrapMode CmdLineOptions::getWrappingStyle() const {
- return wrappingStyle;
-}
-const vector <string> & CmdLineOptions::getInputFileNames() const{
- return inputFileNames;
-}
-void CmdLineOptions::readDirectory(const string & wildcard){
- // get matching files, use recursive search
- bool directoryOK=Platform::getDirectoryEntries(inputFileNames, wildcard, true);
- if (!directoryOK)
- {
- cerr << "highlight: No files matched the pattern \""
- << wildcard << "\"."<< endl;
- }
-}
-void CmdLineOptions::loadConfigurationFile()
-{
- #ifndef _WIN32
- #ifdef CONFIG_FILE_PATH
- configFilePath=CONFIG_FILE_PATH;
- #else
- char* homeEnv=getenv("HOME");
- if (homeEnv==NULL) return;
- configFilePath=string(homeEnv)+"/.highlightrc";
- #endif
- #else
- configFilePath = Platform::getAppPath() + "highlight.conf";
- #endif
- ConfigurationReader presets(configFilePath);
-
- if (presets.found())
- {
- string paramVal;
- configFileRead=true;
-
- styleOutFilename = presets.getParameter(OPT_STYLE_OUT);
- styleInFilename = presets.getParameter(OPT_STYLE_IN);
- styleName = presets.getParameter(OPT_STYLE);
- opt_style = !styleName.empty();
- language = presets.getParameter(OPT_SYNTAX);
- opt_language = !language.empty();
- numberSpaces = StringTools::str2int(presets.getParameter(OPT_DELTABS));
- indentScheme = presets.getParameter(OPT_FORMATSTYLE);
-
- paramVal = presets.getParameter(OPT_DATADIR);
- if (!paramVal.empty()) {
- dataDir=validateDirPath( paramVal);
- }
- paramVal = presets.getParameter(OPT_ADDDATADIR);
- if (!paramVal.empty()) {
- additionalDataDir=validateDirPath(paramVal);
- }
- paramVal = presets.getParameter(OPT_OUTDIR);
- if (!paramVal.empty()) {
- outDirectory=validateDirPath(paramVal);
- }
- paramVal = presets.getParameter(OPT_ENCODING);
- if (!paramVal.empty()) {
- charset=paramVal;
- }
-
- opt_include_style=getFlag(presets.getParameter(OPT_INC_STYLE));
- opt_verbose=getFlag(presets.getParameter(OPT_VERBOSE));
- opt_linenumbers=getFlag(presets.getParameter(OPT_LINENO));
- opt_fragment=getFlag(presets.getParameter(OPT_FRAGMENT));
- opt_attach_line_anchors=getFlag(presets.getParameter(OPT_ANCHORS));
- opt_printindex=getFlag(presets.getParameter(OPT_INDEXFILE));
- opt_quiet=getFlag(presets.getParameter(OPT_QUIET));
- opt_xslfo_fop=getFlag(presets.getParameter(OPT_FOP));
- opt_replacequotes=getFlag(presets.getParameter(OPT_REPLACE_QUOTES));
- opt_print_progress=getFlag(presets.getParameter(OPT_PROGRESSBAR));
- opt_fill_zeroes=getFlag(presets.getParameter(OPT_FILLZEROES));
-
- if (getFlag(presets.getParameter(OPT_WRAP))) {
- wrappingStyle=highlight::WRAP_DEFAULT;
- }
- if (getFlag(presets.getParameter(OPT_WRAPSIMPLE))) {
- wrappingStyle=highlight::WRAP_SIMPLE;
- }
- if (getFlag(presets.getParameter(OPT_XHTML))) {
- outputType=highlight::XHTML;
- } else if (getFlag(presets.getParameter(OPT_RTF))) {
- outputType=highlight::RTF;
- } else if (getFlag(presets.getParameter(OPT_TEX))) {
- outputType=highlight::TEX;
- } else if (getFlag(presets.getParameter(OPT_LATEX))) {
- outputType=highlight::LATEX;
- } else if (getFlag(presets.getParameter(OPT_XSLFO))) {
- outputType=highlight::XSLFO;
- } else if (getFlag(presets.getParameter(OPT_ANSI))) {
- outputType=highlight::ANSI;
- } else if (getFlag(presets.getParameter(OPT_XML))) {
- outputType=highlight::XML;
- }
- }
-}
-
-string CmdLineOptions::validateDirPath(const string & path){
- return (path[path.length()-1] !=Platform::pathSeparator)?
- path+Platform::pathSeparator : path;
-}
-
-highlight::OutputType CmdLineOptions::getOutputType() const {
- return outputType;
-}
-
-void CmdLineOptions::printDeprecatedWarning(const char *oldOption, const char *newOption){
- cerr << "Warning: Long option \""<<oldOption << "\" is DEPRECATED.";
- cerr << " Use \""<<newOption << "\" instead.\n";
-}
-/***************************************************************************
- cmdlineoptions.h - description
- -------------------
- begin : Sun Nov 25 2001
- copyright : (C) 2001 by André Simon
- email : andre.simon1@gmx.de
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#ifndef CMDLINEOPTIONS_H
-#define CMDLINEOPTIONS_H
-
-#include <string>
-#include <map>
-#include <cstdlib>
-#include <iostream>
-#include <fstream>
-
-#include "platform_fs.h"
-#include "configurationreader.h"
-#include "datadir.h"
-#include "enums.h"
-
-#ifdef _WIN32
- #include <windows.h>
-#endif
-
-// If your system does not know getopt_long, define USE_LOCAL_GETOPT
-#if defined(_WIN32) || defined(__SVR4) || defined(__sun__)
- // some compilers don't like redefinitions...
- #ifndef USE_LOCAL_GETOPT
- #define USE_LOCAL_GETOPT
- #endif
-#endif
-
-#ifdef USE_LOCAL_GETOPT
- #include "getopt.h"
-#else
- #include <getopt.h>
-#endif
-
-#define OPT_VERBOSE "verbose"
-#define OPT_INC_STYLE "include-style"
-#define OPT_HELP "help"
-#define OPT_LINENO "linenumbers"
-#define OPT_XHTML "xhtml"
-#define OPT_RTF "rtf"
-#define OPT_TEX "tex"
-#define OPT_LATEX "latex"
-#define OPT_XSLFO "xsl-fo"
-#define OPT_FRAGMENT "fragment"
-#define OPT_ANCHORS "anchors"
-#define OPT_LISTTHEMES "list-themes"
-#define OPT_LISTLANGS "list-langs"
-#define OPT_VERSION "version"
-#define OPT_IN "input"
-#define OPT_OUT "output"
-#define OPT_SYNTAX "syntax"
-#define OPT_STYLE "style"
-#define OPT_STYLE_OUT "style-outfile"
-#define OPT_STYLE_IN "style-infile"
-
-#define OPT_DELTABS "replace-tabs"
-#define OPT_BATCHREC "batch-recursive"
-#define OPT_OUTDIR "outdir"
-#define OPT_FORMATSTYLE "format-style"
-#define OPT_DATADIR "data-dir"
-#define OPT_ADDDATADIR "add-data-dir"
-#define OPT_INDEXFILE "print-index"
-#define OPT_HELPINT "help-int"
-#define OPT_WRAP "wrap"
-#define OPT_WRAPSIMPLE "wrap-simple"
-#define OPT_QUIET "quiet"
-#define OPT_REPLACE_QUOTES "replace-quotes"
-#define OPT_FOP "fop-compatible"
-#define OPT_PROGRESSBAR "progress"
-#define OPT_FILLZEROES "zeroes"
-#define OPT_ANSI "ansi"
-#define OPT_XML "xml"
-#define OPT_ENCODING "encoding"
-#define OPT_FORCE_OUTPUT "force"
-
-#define S_OPT_ANSI 'A'
-#define S_OPT_OUT 'o'
-#define S_OPT_IN 'i'
-#define S_OPT_SYNTAX 'S'
-#define S_OPT_VERBOSE 'v'
-#define S_OPT_INC_STYLE 'I'
-#define S_OPT_HELP 'h'
-#define S_OPT_HELPINT 'H'
-#define S_OPT_LINENO 'l'
-#define S_OPT_STYLE 's'
-#define S_OPT_STYLE_OUT 'c'
-#define S_OPT_STYLE_IN 'e'
-#define S_OPT_DELTABS 't'
-#define S_OPT_XHTML 'X'
-#define S_OPT_RTF 'R'
-#define S_OPT_TEX 'T'
-#define S_OPT_LATEX 'L'
-#define S_OPT_XSLFO 'Y'
-#define S_OPT_XML 'Z'
-#define S_OPT_BATCHREC 'B'
-#define S_OPT_FRAGMENT 'f'
-#define S_OPT_ANCHORS 'a'
-#define S_OPT_LISTTHEMES 'w'
-#define S_OPT_LISTLANGS 'p'
-#define S_OPT_OUTDIR 'O'
-
-#define S_OPT_FORMATSTYLE 'F'
-#define S_OPT_DATADIR 'D'
-#define S_OPT_ADDDATADIR 'E'
-#define S_OPT_INDEXFILE 'C'
-#define S_OPT_WRAP 'W'
-#define S_OPT_WRAPSIMPLE 'V'
-#define S_OPT_QUIET 'q'
-#define S_OPT_FOP 'g'
-#define S_OPT_REPLACE_QUOTES 'r'
-#define S_OPT_VERSION 'Q'
-#define S_OPT_PROGRESSBAR 'P'
-#define S_OPT_FILLZEROES 'z'
-#define S_OPT_ENCODING 'u'
-
-// deprecated:
-#define OPT_CSSOUT "css-outfile"
-#define OPT_CSSIN "css-infile"
-#define OPT_INC_CSS "include-css"
-
-
-#define S_OPTIONS_STRING "o:i:S:B:O:s:c:e:t:u:F:D:H:E:afghlvwpqrzACILYRTZXUV::W::P"
-
-using namespace std;
-
-/**Command line options*/
-
-class CmdLineOptions
- {
- public:
-
- /**Constructor
- \param argc Argument count
- \param argv Argument strings
- */
- CmdLineOptions(int argc, char *argv[]);
- ~CmdLineOptions();
-
- /** \return Single output file name*/
- const string &getSingleOutFilename();
-
- /** \return Single input file name*/
- const string &getSingleInFilename() const;
-
- /** \return Output directory*/
- const string& getOutDirectory() ;
-
- /** \return Style output file name*/
- const string getStyleOutFilename() const;
-
- /** \return Style input file name*/
- const string&getStyleInFilename() const;
-
- /** \return Char set*/
- const string&getCharSet() const;
-
- /** \return Number of spaces to replace a tab*/
- int getNumberSpaces() const;
-
- /** \return True if version information should be printed*/
- bool printVersion() const;
-
- /** \return True if help information should be printed*/
- bool printHelp() const;
-
- /** \return True if debug information should be printed*/
- bool printDebugInfo()const;
-
- /** \return True if Style definition should be included in output*/
- bool includeStyleDef() const;
-
- /** \return True if line numbers should be printed*/
- bool printLineNumbers() const;
-
- /** \return colour theme name */
- string getStyleName()const ;
-
- /** gibt true zurck, falls deutsche Hilfe ausgegeben werden soll */
- int helpLanguage() const;
-
- /** \return True if batch mode is active*/
- bool enableBatchMode() const;
-
- /** \return True if output shluld be fragmented*/
- bool fragmentOutput() const;
-
- /** \return output file suffix */
- string getOutFileSuffix() const;
-
- /** \return True if anchors should be attached to line numbers*/
- bool attachLineAnchors() const;
-
- /** \return True if list of installed themes should be printed*/
- bool showThemes() const;
-
- /** \return True if list of installed language definitions should be printed*/
- bool showLangdefs() const;
-
- /** \return True if loutput directory is given*/
- bool outDirGiven() const;
-
- /** \return True if refomatting is enabled*/
- bool formattingEnabled();
-
- /** \return True if a new data directory is given*/
- bool dataDirGiven()const;
-
- /** \return True if an additional data directory is given*/
- bool additionalDataDirGiven()const;
-
- /** \return True if index file should be printed*/
- bool printIndexFile() const;
-
- /** \return True if quotes should be replaced by /dq in LaTeX*/
- bool replaceQuotes() const;
-
- /** \return Data directory*/
- const string &getDataDir()const;
-
- /** \return Additional data directory*/
- const string &getAdditionalDataDir()const;
-
- /** \return True if language syntax is given*/
- bool syntaxGiven() const;
-
- /** \return True if quiet mode is active*/
- bool quietMode() const;
-
- /** \return True if XSL-FO output should be FOP compatible*/
- bool fopCompatible() const;
-
- /** \return True if progress bar should be printed in batch mode */
- bool printProgress() const;
-
- /** \return True if line numbers are filled with leading zeroes */
- bool fillLineNrZeroes() const;
-
- /** \return name of help message file*/
- const string getHelpLang() const;
-
- /** \return programming language */
- const string &getLanguage()const ;
-
- /** \return Wrapping style*/
- highlight::WrapMode getWrappingStyle() const;
-
- /** \return List of input file names*/
- const vector <string> & getInputFileNames() const;
-
- /** \return Name of indentation scheme file */
- const string &getIndentScheme() const;
-
- /** \return Output file format */
- highlight::OutputType getOutputType() const;
-
- /** \return True if chosen output format supports referenced style files */
- bool formatSupportsExtStyle();
-
- /** \return True if style output path was defined by user*/
- bool styleOutPathDefined() const{
- return opt_stylepath_explicit;
- }
-
- /** \return True if encoding nasme should be omitted in output*/
- bool omitEncodingName() const;
-
- /** \return True if output should be generated if languege type is unknown*/
- bool forceOutput() const;
-
- private:
-
- int numberSpaces; // number of spaces which replace a tab
- highlight::WrapMode wrappingStyle; // line wrapping mode
- highlight::OutputType outputType;
-
- // name of single output file
- string outFilename,
- // output directory
- outDirectory,
- // programming language which will be loaded
- language,
- // name of colour theme
- styleName,
- // name of external style file
- styleOutFilename,
- // name of file to be included in external style file
- styleInFilename,
- // used to define data directories at runtime
- dataDir, additionalDataDir;
- // name of indenation scheme
- string indentScheme;
-
- bool opt_language;
- bool opt_include_style;
- bool opt_help;
- bool opt_version ;
- bool opt_verbose;
- bool opt_linenumbers;
- bool opt_style;
- bool opt_batch_mode;
- bool opt_fragment;
- bool opt_attach_line_anchors;
- bool opt_show_themes;
- bool opt_show_langdefs;
- bool opt_asformat_output;
- bool opt_printindex;
- bool opt_quiet;
- bool opt_xslfo_fop;
- bool opt_replacequotes;
- bool opt_print_progress;
- bool opt_fill_zeroes;
- bool opt_stylepath_explicit;
- bool opt_force_output;
-
- bool configFileRead;
-
- string helpLang, charset;
- string configFilePath;
-
- // list of all input file names
- vector <string> inputFileNames;
-
- /** load highlight configuration file */
- void loadConfigurationFile();
-
- /** \return file suffix */
- string getFileSuffix( const string & fileName) const;
-
- /** \return directory name of path */
- string getDirName( const string & path);
-
- /** get all entries in the directory defined by wildcard */
- void readDirectory(const string & wildcard);
-
- /** \return Boolean value of paramVal */
- bool getFlag(const string& paramVal);
-
- /** \return Valid path name */
- string validateDirPath(const string & path);
-
- void printDeprecatedWarning(const char *oldOption, const char *newOption);
- };
-
-#endif
-/***************************************************************************
- codeparser.cpp - description
- -------------------
- begin : Die Jul 9 2002
- copyright : (C) 2002 by André Simon
- email : andre.simon1@gmx.de
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#include "codegenerator.h"
-
-#include "htmlgenerator.h"
-#include "xhtmlgenerator.h"
-#include "rtfgenerator.h"
-#include "latexgenerator.h"
-#include "texgenerator.h"
-#include "xslfogenerator.h"
-#include "xmlgenerator.h"
-#ifndef __WXMSW__
- #include "ansigenerator.h"
-#endif
-
-
-using namespace std;
-
-namespace highlight {
-
-CodeGenerator* CodeGenerator::generator=NULL;
-
-CodeGenerator* CodeGenerator::getInstance(OutputType type,
- const string& styleInfoPath,
- const string& styleInPath,
- const string& styleOutPath,
- const string& encoding,
- bool includeStyle,
- bool attachAnchors,
- bool replaceQuotes,
- bool fopCompatible,
- int numSpaces,
- WrapMode lineWrappingMode,
- bool ln,
- bool lnz,
- bool fragment,
- bool omitEncoding
- ) {
- if (generator==NULL){
- switch (type){
- case TEX:
- generator = new TexGenerator (styleInfoPath);
- break;
- case LATEX:
- generator = new LatexGenerator(styleInfoPath, replaceQuotes);
- break;
- case RTF:
- generator = new RtfGenerator (styleInfoPath);
- break;
- case XSLFO:
- generator = new XslFoGenerator(styleInfoPath, encoding, omitEncoding,
- fopCompatible);
- break;
- case XML:
- generator = new XmlGenerator(styleInfoPath,encoding, omitEncoding);
- break;
- case XHTML:
- generator = new XHtmlGenerator(styleInfoPath, encoding, omitEncoding,
- attachAnchors);
- break;
- #ifndef __WXMSW__
- case ANSI:
- generator = new AnsiGenerator (styleInfoPath);
- break;
- #endif
- default:
- generator = new HtmlGenerator(styleInfoPath, encoding, omitEncoding,
- attachAnchors);
- }
- }
- generator->setType(type);
- generator->setStyleInputPath(styleInPath);
- generator->setStyleOutputPath(styleOutPath);
- generator->setIncludeStyle(includeStyle);
- generator->setPrintLineNumbers(ln);
- generator->setPrintZeroes(lnz);
- generator->setFragmentCode(fragment);
- generator->setPreformatting(lineWrappingMode,
- (generator->getPrintLineNumbers()) ?
- MAX_LINE__WIDTH - LINE_NUMBER_WIDTH : MAX_LINE__WIDTH,
- numSpaces );
- return generator;
-}
-
-void CodeGenerator::deleteInstance(){
- delete generator;
- generator=NULL;
-}
-
-
-CodeGenerator::CodeGenerator():
- in(NULL),
- out(NULL),
- maskWs(false),
- excludeWs(false),
- fragmentOutput(false),
- showLineNumbers (false),
- lineNumberFillZeroes(false),
- lineNumber(0),
- includeStyleDef(false),
- lineIndex(0),
- formatter(NULL),
- preFormatter(NULL),
- formattingEnabled(false),
- formattingPossible(false),
- outputType(highlight::HTML)
-{}
-
-CodeGenerator::CodeGenerator(const string &colourTheme)
- :in(NULL),
- out(NULL),
- maskWs(false),
- excludeWs(false),
- fragmentOutput(false),
- showLineNumbers (false),
- lineNumberFillZeroes(false),
- lineNumber(0),
- includeStyleDef(false),
- stylePath(colourTheme),
- lineIndex(0),
- formatter(NULL),
- preFormatter(NULL),
- formattingEnabled(false),
- formattingPossible(false),
- outputType(highlight::HTML)
-{
- line.reserve(100);
- docStyle.load(stylePath);
-}
-
-CodeGenerator::~CodeGenerator()
-{
- delete preFormatter;
- delete formatter;
-}
-
-
-/** Getter and Setter*/
-
-void CodeGenerator::setPrintLineNumbers(bool flag){
- showLineNumbers=flag;
-}
-
-bool CodeGenerator::getPrintLineNumbers(){
- return showLineNumbers;
-}
-
-void CodeGenerator::setPrintZeroes(bool flag){
- lineNumberFillZeroes=flag;
-}
-
-bool CodeGenerator::getPrintZeroes(){
- return lineNumberFillZeroes;
-}
-
-void CodeGenerator::setFragmentCode(bool flag){
- fragmentOutput=flag;
-}
-
-void CodeGenerator::setIncludeStyle(bool flag){
- includeStyleDef = flag;
-}
-
-void CodeGenerator::setStyleInputPath(const string& path){
- styleInputPath = path;
-}
-void CodeGenerator::setStyleOutputPath(const string& path){
- styleOutputPath = path;
-}
-
-const string& CodeGenerator::getStyleInputPath(){
- return styleInputPath;
-}
-const string& CodeGenerator::getStyleOutputPath(){
- return styleOutputPath;
-}
-
-
-bool CodeGenerator::getFragmentCode(){
- return fragmentOutput;
-}
-
-void CodeGenerator::setStyleName(const string& s){
- stylePath=s;
-}
-
-void CodeGenerator::setType(OutputType t){
- outputType = t;
-}
-
-const string& CodeGenerator::getStyleName(){
- return stylePath;
-}
-
-bool CodeGenerator::formattingDisabled(){
- return !formattingEnabled;
-}
-
-bool CodeGenerator::formattingIsPossible(){
- return formattingPossible;
-}
-
-void CodeGenerator::setPreformatting(WrapMode lineWrappingStyle,
- unsigned int lineLength,
- int numberSpaces ){
- bool enableWrap = lineWrappingStyle!=WRAP_DISABLED;
- bool replaceTabs = numberSpaces > 0;
- if (enableWrap || replaceTabs) {
- preFormatter=new PreFormatter(enableWrap, replaceTabs);
- if (enableWrap)
- preFormatter->setWrappingProperties(lineLength, lineWrappingStyle==WRAP_DEFAULT);
- if (replaceTabs)
- preFormatter->setNumberSpaces(numberSpaces);
- }
-}
-
-/*
-WrapMode CodeGenerator::getLineWrapping(){
- if (preFormatter==NULL) return WRAP_DISABLED;
- return (preFormatter->indentCode()?WRAP_DEFAULT:WRAP_SIMPLE);
-}
-*/
-LanguageDefinition &CodeGenerator::getLanguage(){
- return langInfo;
-}
-
-void CodeGenerator::reset()
-{
- lineIndex = lineNumber = 0;
- line.clear();
-}
-
-
-/** sucht vorwaerts ab Position searchPos Ziffer in s und liefert Integerwert
-der gefundenen Zahl zurueck.
-Im SymbolString stehen die den einzelnen Symbolen zugeordneten Konstanten
-immer HINTER diesen Symbolen*/
-State CodeGenerator::getState(const string &s, unsigned int searchPos)
-{
- unsigned int i= searchPos+1, result=0;
-
- // nach Ziffer in s suchen
- do {
- ++i;
- } while ((i<s.length()) && !isdigit(s[i])) ;
-
- // Zahl zusammensetzen
- while ((i<s.length()) && isdigit(s[i])){
- result = result *10 + (s[i]-'0');
- ++i;
- }
- return ((result)? (State)result:_UNKNOWN);
-}
-
-string CodeGenerator::getIdentifier()
-{
- --lineIndex;
- unsigned int startPos=lineIndex;
- char c= line[lineIndex];
-
- while ( ( lineIndex < line.length()
- && ( StringTools::isAlpha(c)
- || isdigit(c))
- || isAllowedChar(c))
- )
- {
- ++lineIndex;
- c= line[lineIndex];
- }
- return string(line, startPos, lineIndex - startPos);
-}
-
-string CodeGenerator::getNumber()
-{
- --lineIndex;
- unsigned int startPos=lineIndex;
- char c=line[lineIndex];
-
- while ( lineIndex < line.length() && (
- isdigit(c)
- // don't highlight methods applied on numbers as part of the number
- // i.e. Ruby: 3.xxx()
- || (c == '.' && isdigit(line[lineIndex+1]))
- // '-' is accepted as first character
- || (c == '-' && lineIndex == startPos)
- || (StringTools::isAlpha(c) && line[lineIndex-1]=='0')
- || (isxdigit(c) || c=='L' || c=='U' || c=='l' || c=='u') ))
- {
- ++lineIndex;
- c= line[lineIndex];
- }
- return string(line,startPos, lineIndex-startPos);
-}
-
-unsigned int CodeGenerator::getLineNumber()
-{
- return lineNumber;
-}
-
-bool CodeGenerator::readNewLine(string &newLine){
- bool eof;
- terminatingChar=newLine[lineIndex-1];
- if (formattingPossible && formattingEnabled)
- {
- eof=!formatter->hasMoreLines();
- if (!eof)
- {
- newLine = formatter->nextLine();
- }
- }
- else // reformatting not enabled
- {
- eof = ! getline( *in, newLine);
- }
- return eof;
-}
-
-unsigned char CodeGenerator::getInputChar()
-{
- bool eol = lineIndex == line.length();
-
- if (eol) {
- bool eof=false;
- if (preFormatter!=NULL){
- if (!preFormatter->hasMoreLines()) {
- eof=readNewLine(line);
- preFormatter->setLine(line);
- }
- line = preFormatter->getNextLine();
- } else {
- eof=readNewLine(line);
- }
- lineIndex=0;
- ++lineNumber;
- line=StringTools::trimRight(line);
- return (eof)?'\0':'\n';
- }
- return line[lineIndex++];
-}
-
-State CodeGenerator::getCurrentState (bool lastStateWasNumber)
-{
- unsigned char c;
-
- if (token.length()==0) {
- c=getInputChar();
- } else {
- lineIndex-= (token.length()-1);
- c=token[0];
- }
- if (c=='\n'){
- return _EOL; // End of line
- }
-
- if (c=='\0') {
- return _EOF; // End of file
- }
-
- if (isspace(c)) {
- token= c;
- return _WS;
- }
-
- // numbers have to be searched before using the symbolstring,
- // as numbers are part of this string
- if (isdigit(c)
- // recognize floats like .5
- || (c=='.' && isdigit(line[lineIndex]))
- // test if '-' belongs to a term like "1-2"
- || ((c == '-')
- && (!lastStateWasNumber)
- && isdigit(StringTools::getNextNonWs(line, lineIndex))) )
- {
- token = getNumber();
- return NUMBER;
- }
- unsigned int symbolLength;
- size_t symbolPos;
- bool found=false;
- string symbols=langInfo.getSymbolString();
-
- symbolPos = symbols.find(c);
- // search symbols (comment delimiters, directives etc.)
- // before keywords, because alphabetic chars may be part of symbols, too
- while ((symbolPos!= string::npos) && (!found))
- {
- symbolLength=symbols.find(' ', symbolPos)-symbolPos;
- token = symbols.substr(symbolPos, symbolLength);
-
- // TODO Ruby =ende, =end bugfix (whitespace after symbol needs to be checked)
-
- // Abfrage nach Leerzeichen in SymbolString verhindert falsches
- // Erkennen von Symbolteilen:
- if (lineIndex && token == line.substr(lineIndex-1, symbolLength)
- && isspace(symbols[symbolPos-1]) ) {
- found = true;
- lineIndex += (symbolLength-1);
- } else {
- symbolPos = symbols.find_first_not_of(' ',symbols.find(' ',symbolPos));
- }
- }
-
- // dirty workaround stuff in here
- if (found) {
- State foundState = getState(symbols, symbolPos);
-
- // get the current keyword class id to apply the corresponding formatting style
- if (foundState==KEYWORD_BEGIN || foundState==TAG_BEGIN ) {
- currentKeywordClass=langInfo.getDelimPrefixClassID(token);
- }
-
- // Full line quotes must start in coloumn 1 (Fortran 77)
- if (langInfo.isFullLineComment() && foundState==SL_COMMENT){
- if (lineIndex==1) {
- return SL_COMMENT;
- }
- }
- // VHDL Workaround: distinguish string delimiters and event markers
- // (same eymbol: ')
- else if (langInfo.isVHDL()
- && foundState==STRING && currentState!=STRING
- && lineIndex > 1
- &&(isdigit(line[lineIndex-2]) || isalpha(line[lineIndex-2]))){
- c=line[lineIndex-1];
- // do not return, continue search...
- } else {
- return foundState;
- }
- }
-
- // Alphanumerisches Token parsen und als Keyword oder Type erkennen
- if (StringTools::isAlpha(c) || langInfo.isPrefix(c) || isAllowedChar(c))
- {
- if (langInfo.isPrefix(c)){
- token = c;
- ++lineIndex;
- token += getIdentifier();
- } else {
- token = getIdentifier();
- }
- string reservedWord=(langInfo.isIgnoreCase()) ?
- StringTools::lowerCase(token):token;
- currentKeywordClass=langInfo.isKeyword(reservedWord);
- return (currentKeywordClass) ? KEYWORD : STANDARD;
- }
-
- // Character not referring to any state
- token = c;
- return STANDARD;
-}
-
-string CodeGenerator::maskString(const string & s)
-{
- ostringstream ss;
- for (unsigned int i=0;i< s.length();i++){
- ss << maskCharacter(s[i]);
- }
- return ss.str();
-}
-
-void CodeGenerator::printMaskedToken(bool flushWhiteSpace)
-{
- if(flushWhiteSpace) flushWs();
- *out << maskString(token);
- token.clear();
-}
-
-bool CodeGenerator::isAllowedChar(char c)
-{
- return ( langInfo.getAllowedChars().find(c)!= string::npos);
-}
-
-bool CodeGenerator::styleFound(){
- return docStyle.found();
-}
-
-bool CodeGenerator::printIndexFile(const vector<string> &fileList,
- const string &outPath){
- return true;
-}
-
-bool CodeGenerator::initIndentationScheme(const string &schemePath){
-
- if (formatter!=NULL){
- return true;
- }
-
- ConfigurationReader indentScheme(schemePath);
- if (indentScheme.found()){
- if (formatter==NULL) {
- formatter=new astyle::ASFormatter();
-
- string brackets=indentScheme.getParameter("brackets");
- if (!brackets.empty()){
- // Break brackets from pre-block code (i.e. ANSI C/C++ style).
- if (brackets=="break"){
- formatter->setBracketFormatMode(astyle::BREAK_MODE);
- }
- //Attach brackets to pre-block code (i.e. Java/K&R style).
- else if (brackets=="attach"){
- formatter->setBracketFormatMode(astyle::ATTACH_MODE);
- }
- // Break definition-block brackets and attach command-block brackets.
- else if (brackets=="linux"){
- formatter->setBracketFormatMode(astyle::BDAC_MODE);
- }
- // Break brackets before closing headers (e.g. 'else', 'catch', ..).
- // Should be appended to --brackets=attach or --brackets=linux.
- else if (brackets=="break-closing-headers"){
- formatter->setBreakClosingHeaderBracketsMode(true);
- }
- }
-
- string pad=indentScheme.getParameter("pad");
- if (!pad.empty()){
- //Insert space paddings around parenthesies only.
- if (pad=="paren"){
- formatter->setParenthesisPaddingMode(true);
- }
- // Insert space paddings around operators only.
- else if (pad=="oper"){
- formatter->setOperatorPaddingMode(true);
- }
- //Insert space paddings around operators AND parenthesies.
- else if (pad=="all"){
- formatter->setOperatorPaddingMode(true);
- formatter->setParenthesisPaddingMode(true);
- }
- }
-
- string oneLine=indentScheme.getParameter("one-line");
- if (!oneLine.empty()){
- // Don't break one-line blocks.
- if (oneLine=="keep-blocks"){
- formatter->setBreakOneLineBlocksMode(false);
- }
- // Don't break complex statements and multiple statements residing in a
- // single line.
- else if (oneLine=="keep-statements"){
- formatter->setSingleStatementsMode(false);
- }
- }
-
- // Insert empty lines around unrelated blocks, labels, classes, ...
- string breakBlocks=indentScheme.getParameter("break-blocks");
- if (!breakBlocks.empty()){
- if (breakBlocks=="all"){
- //Like --break-blocks, except also insert empty lines around closing
- //headers (e.g. 'else', 'catch', ...).
- formatter->setBreakClosingHeaderBlocksMode(true);
- }
- formatter->setBreakBlocksMode(true);
- }
- string trueVal="true";
-
- // Other options...
-
- //Indent using # spaces per indent. Not specifying # will result in a
- //default of 4 spaces per indent.
- string indentSpaces=indentScheme.getParameter("indent-spaces");
-
- // Indent a minimal # spaces in a continuous conditional belonging to a
- //conditional header.
- string minConditionalIndent=indentScheme.getParameter("min-conditional-indent");
-
- // Indent a maximal # spaces in a continuous statement, relatively to the
- // previous line.
- string maxInStatementIndent=indentScheme.getParameter("max-instatement-indent");
-
- // Add extra indentation to '{' and '}' block brackets.
- string indentBrackets=indentScheme.getParameter("indent-brackets");
-
- // Add extra indentation entire blocks (including brackets).
- string indentBlocks=indentScheme.getParameter("indent-blocks");
-
- // Indent the contents of namespace blocks.
- string indentNamespaces=indentScheme.getParameter("indent-namespaces");
-
- // Indent 'class' blocks, so that the inner 'public:','protected:' and
- // 'private: headers are indented inrelation to the class block.
- string indentClasses=indentScheme.getParameter("indent-classes");
-
- // Indent 'switch' blocks, so that the inner 'case XXX:' headers are
- // indented in relation to the switch block.
- string indentSwitches=indentScheme.getParameter("indent-switches");
-
- // Indent 'case XXX:' lines, so that they are flush with their bodies..
- string indentCases=indentScheme.getParameter("indent-cases");
-
- // Indent labels so that they appear one indent less than the current
- // indentation level, rather than being flushed completely to the left
- // (which is the default).
- string indentLabels=indentScheme.getParameter("indent-labels");
-
- // Indent multi-line #define statements
- string indentPreprocessor=indentScheme.getParameter("indent-preprocessor");
-
- // Break 'else if()' statements into two different lines.
- string breakElseIfs = indentScheme.getParameter("break-elseifs");
-
- string javaStyle = indentScheme.getParameter("java-style");
-
- // default values in ASBeautifier are false, it is ok to set them false
- // if parameter does not exist in scheme file
- formatter->setBracketIndent(indentBrackets==trueVal);
- formatter->setBlockIndent(indentBlocks==trueVal);
- formatter->setNamespaceIndent(indentNamespaces==trueVal);
- formatter->setClassIndent(indentClasses==trueVal);
- formatter->setSwitchIndent(indentSwitches==trueVal);
- formatter->setCaseIndent(indentCases==trueVal);
- formatter->setLabelIndent(indentLabels==trueVal);
- formatter->setPreprocessorIndent(indentPreprocessor==trueVal);
- formatter->setBreakElseIfsMode(breakElseIfs==trueVal);
-
- if (javaStyle==trueVal){
- formatter->setJavaStyle();
- }
-
- if (!indentSpaces.empty()){
- formatter->setSpaceIndentation(StringTools::str2int(indentSpaces));
- }
- if (!minConditionalIndent.empty()){
- formatter->setMinConditionalIndentLength(
- StringTools::str2int(minConditionalIndent));
- }
- if (!maxInStatementIndent.empty()){
- formatter->setMinConditionalIndentLength(
- StringTools::str2int(maxInStatementIndent));
- }
- }
- formattingEnabled=(formatter != NULL);
- return true;
- } else {
- return false;
- }
-}
-
-LoadResult CodeGenerator::initLanguage(const string& langDefPath){
- bool reloadNecessary= langInfo.needsReload(langDefPath);
- if (reloadNecessary){
- bool failure = !langInfo.load(langDefPath);
-
- if (failure) {
- return LOAD_FAILED;
- }
-
- formattingPossible=langInfo.enableReformatting();
-
- if (styleTagOpen.size()>NUMBER_BUILTIN_STYLES){
- // remove dynamic keyword tag delimiters of the old language definition
- vector<string>::iterator keyStyleOpenBegin =
- styleTagOpen.begin() + NUMBER_BUILTIN_STYLES;
- vector<string>::iterator keyStyleCloseBegin =
- styleTagClose.begin()+ NUMBER_BUILTIN_STYLES;
- styleTagOpen.erase(keyStyleOpenBegin, styleTagOpen.end());
- styleTagClose.erase(keyStyleCloseBegin, styleTagClose.end());
- }
- // add new keyword delimiters
- for (unsigned int i=0;i< langInfo.getKeywordClasses().size(); i++){
- styleTagOpen.push_back(getMatchingOpenTag(i));
- styleTagClose.push_back(getMatchingCloseTag(i));
- }
- }
- return (reloadNecessary) ? LOAD_NEW : LOAD_NONE;
-}
-
-ParseError CodeGenerator::printOutput (const string & inFileName,
- const string &outFileName)
-{
- if (!docStyle.found()) {
- return BAD_STYLE;
- }
- reset();
-
- ParseError error=PARSE_OK;
-
- in = (inFileName.empty()? &cin :new ifstream (inFileName.c_str()));
- if (!in->fail()) {
- out = (outFileName.empty()? &cout :new ofstream (outFileName.c_str()));
- if ( out->fail()) {
- error=BAD_OUTPUT;
- }
- }
-
- if ( in->fail()){
- error=BAD_INPUT;
- }
-
- if (error==PARSE_OK) {
- if (formatter != NULL){
- formatter->init(new astyle::ASStreamIterator(in));
- }
- if (! fragmentOutput){
- *out << getHeader(inFileName);
- }
- printBody();
- if (! fragmentOutput){
- *out << getFooter();
- }
- }
-
- if (!outFileName.empty()){
- delete out; out=NULL;
- }
- if (!inFileName.empty()) {
- delete in; in=NULL;
- }
- return error;
-}
-
-
-unsigned int CodeGenerator::getStyleID(State s, unsigned int kwClassID){
- if (s==KEYWORD && kwClassID){
- return NUMBER_BUILTIN_STYLES + kwClassID-1;
- }
- return (unsigned int) s ;
-}
-
-void CodeGenerator::closeTag(State s){
- *out << styleTagClose[(unsigned int)s];
- flushWs();
- currentState=_UNKNOWN;
-}
-
-void CodeGenerator::openTag(State s){
- *out << styleTagOpen[(unsigned int)s];
- currentState=s;
-}
-
-void CodeGenerator::closeKWTag(unsigned int kwClassID){
- *out << styleTagClose[getStyleID(KEYWORD, kwClassID)];
-
- flushWs();
- currentState=_UNKNOWN;
-}
-
-void CodeGenerator::openKWTag(unsigned int kwClassID){
- *out << styleTagOpen[getStyleID(KEYWORD, kwClassID)];
- currentState=KEYWORD;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-
-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/bench/example.delphi b/bench/example.delphi
deleted file mode 100644
index 8670459..0000000
--- a/bench/example.delphi
+++ /dev/null
@@ -1,2708 +0,0 @@
-// vim:ft=pascal
-
-unit YTools;
-
-{===============================================================================
-
- cYcnus.YTools 1.0.3 Beta for Delphi 4+
- by licenser and Murphy
-
- ©2000-2003 by cYcnus
- visit www.cYcnus.de
-
- licenser@cYcnus.de (Heinz N. Gies)
- murphy@cYcnus.de (Kornelius Kalnbach)
-
- this unit is published under the terms of the GPL
-
-===============================================================================}
-
-interface
-
-uses
- Windows, SysUtils, Classes, YTypes;
-
-const
- BackSpace = #8;
- Tab = #9;
- LF = #10; //Line Feed
- CR = #13; //Carriage Return
- Space = #32;
- EOLChars = [CR, LF];
-{$IFNDEF VER140}
- sLineBreak = #13#10;
- SwitchChars = ['/', '-'];
-{$ENDIF}
- EOL = sLineBreak;
- MaxCard = High(Cardinal);
- AllChars = [#0..#255];
- Alphabetical = ['A'..'Z', 'a'..'z'];
- DecimalChars = ['0'..'9'];
- AlphaNumerical = Alphabetical + DecimalChars;
- StrangeChars = [#0..#31, #127, #129, #141..#144, #157, #158];
-
- HexadecimalChars = DecimalChars + ['A'..'F', 'a'..'f'];
- OctalChars = ['0'..'7'];
- BinaryChars = ['0', '1'];
-
- QuoteChars = ['''', '"'];
- WildCards = ['*', '?'];
- FileNameEnemies = WildCards + ['\', '/', ':', '<', '>', '|'];
-
- HexChar: array[THex] of Char = (
- '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
- LowerHexChar: array[THex] of Char = (
- '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
- BaseNChar: array[TBaseN] of Char = (
- '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H',
- 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
-
- cYcnusOverlayColor = $050001;
-
- faFindEveryFile = faReadOnly + faHidden + faSysFile + faArchive;
-
- platWin9x = [VER_PLATFORM_WIN32s, VER_PLATFORM_WIN32_WINDOWS];
-
-
-{ Debugging }
-procedure ClearReport(const ReportName: string);
-procedure Report(const ReportName, Text: string);
-procedure ReportFmt(const ReportName, Fmt: string; const Args: array of const);
-
-{ Params }
-procedure GetParams(Strings: TStrings); overload;
-function GetParams(const Separator: string = ' '): string; overload;
-
-function ParamNum(const S: string): Integer;
-function ParamPrefixNum(const Prefix: string): Integer;
-function Param(const S: string): Boolean;
-function ParamPrefix(const Prefix: string): Boolean;
-
-function Switch(const Switch: string; const PrefixChars: TCharSet = SwitchChars;
- IgnoreCase: Boolean = True): Boolean;
-function GetParam(const Prefix: string = ''; const Default: string = ''): string;
-
-{ Dirs & UserName}
-function GetMyDir(FullPath: Boolean = False): string;
-function WinDir: string;
-function SysDir: string;
-function UserName: string;
-
-{ Strings & Chars}
-function FirstChar(const S: string): Char;
-function LastChar(const S: string): Char;
-
-function CharPos(C: Char; const S: string; Offset: Integer = 1): Integer; overload;
-function CharPos(C: TCharSet; const S: string; Offset: Integer = 1): Integer; overload;
-function CharPosR(C: Char; const S: string; Offset: Integer = -1): Integer;
-function PosEx(const SubStr, S: string; Offset: Integer = 1): Integer;
-function PosExText(const SubStr, S: string; Offset: Integer = 1): Integer;
-function PosExAnsiText(const SubStr, S: string; Offset: Integer = 1): Integer;
-
-function UntilChar(const S: string; Brake: Char): string; overload;
-function UntilChar(const S: string; Brake: TCharSet): string; overload;
-function UntilLastChar(const S: string; Brake: Char;
- IgnoreNoBrake: Boolean = True): string;
-
-function FromChar(const S: string; Brake: Char): string; overload;
-function FromChar(const S: string; Brake: TCharSet): string; overload;
-function FromLastChar(const S: string; Brake: Char;
- IgnoreNoBrake: Boolean = False): string;
-
-function BetweenChars(const S: string; Start, Finish: Char;
- Inclusive: Boolean = False): string;
-
-function UntilStr(const S: string; Brake: string): string;
-function FromStr(const S: string; Brake: string): string;
-
-function StringWrap(const S: string; Width: Integer; const LineEnd: string = EOL): string;
-
-{ Splitting & Combining }
-function Split(const S, Separator: string; IgnoreMultiSep: Boolean = True;
- MinCount: Integer = 0): TStrA; overload;
-procedure Split(const S, Separator: string; Strings: TStrings;
- IgnoreMultiSep: Boolean = True); overload;
-function Split(const S: string; Separators: TCharSet;
- IgnoreMultiSep: Boolean = True; MinCount: Integer = 0): TStrA; overload;
-
-procedure TileStr(const S: string; BrakeStart: Integer; BrakeEnd: Integer;
- out Left, Right: string);
-
-function Join(Strings: TStrings; Separator: string = ' '): string; overload;
-function Join(StrA: TStrA; Separator: string = ' '): string; overload;
-
-function MulStr(const S: string; Count: Integer): string;
-
-{ Strings ausrichten }
-function AlignR(const S: string; Width: Integer; Filler: Char = ' '): string;
-function MaxStr(const S: string; MaxLen: Integer): string;
-
-{ Stringing }
-function TrimAll(const S: string): string;
-
-function ControlChar(C: Char): Boolean;
-function FriendlyChar(C: Char): Char;
-
-function FriendlyStr(const S: string): string; overload;
-function FriendlyStr(a: TByteA): string; overload;
-
-function Quote(const S: string; Quoter: Char = '"'): string;
-function UnQuote(const S: string): string;
-function DeQuote(const S: string): string;
-
-function StrNumerus(const Value: Integer; const Singular, Plural: string;
- const Zero: string = '0'): string;
-
-function MakeStr(const Items: array of const; Separator: string = ''): string;
-procedure ShowText(const Items: array of const; Separator: string = '');
-
-{ Delete }
-function DeleteChars(const S: string; C: Char): string; overload;
-function DeleteChars(const S: string; C: TCharSet): string; overload;
-function ExtractChars(const S: string; C: TCharSet): string;
-
-{ Find }
-function CharCount(const S: string; C: Char): Integer;
-
-function CharIn(const S: string; C: Char): Boolean; overload;
-function CharIn(const S: string; C: TCharSet): Boolean; overload;
-
-function StrAtPos(const S: string; Pos: Integer; const Str: string): Boolean;
-function StrAtBegin(const S, Str: string): Boolean;
-function StrIn(const S, SubStr: string): Boolean; overload;
-function StrIn(A: TStrA; const S: string): Boolean; overload;
-function StrIn(SL: TStrings; const S: string): Boolean; overload;
-function StrIndex(A: TStrA; const S: string): Integer; overload;
-function StrIndex(SL: TStrings; const S: string): Integer; overload;
-
-function TextAtPos(const S: string; Pos: Integer; const Text: string): Boolean;
-function TextAtBegin(const S, Text: string): Boolean;
-function TextIn(const S, Text: string): Boolean; overload;
-function TextIn(A: TStrA; const Text: string): Boolean; overload;
-function TextIn(SL: TStrings; const Text: string): Boolean; overload;
-function TextIndex(A: TStrA; const Text: string): Integer; overload;
-function TextIndex(SL: TStrings; const Text: string): Integer; overload;
-
-{ Replace }
-function ReplaceChars(const S: string; Old, New: Char): string; overload;
-function ReplaceChars(const S: string; Old: TCharSet; New: Char): string; overload;
-
-function Replace(const S, Old, New: string): string;
-
-{ TStrings }
-function SLOfFile(const FileName: string): TStringList;
-function ContainsEmptyLines(SL: TStrings): Boolean;
-procedure DeleteEmptyLines(SL: TStrings);
-procedure DeleteCommentLines(SL: TStrings; const CommentSign: string = '//');
-procedure WriteSL(Strings: TStrings; const Prefix: string = '';
- const Suffix: string = '');
-
-function FindLine(SL: TStrings; const S: string): Integer;
-
-procedure QuickSortSL(SL: TStringList);
-
-{ TStrA }
-function IncStrA(StrA: TStrA): Integer;
-
-{ TByteA }
-function StrOfByteA(a: TByteA): string;
-function ByteAOfStr(const S: string): TByteA;
-function ByteAOfInt(i: Integer): TByteA;
-function IntOfByteA(A: TByteA): Integer;
-function ByteAOfHex(const Hex: string): TByteA;
-
-function SameByteA(const A, B: TByteA): Boolean;
-function Reverse(a: TByteA): TByteA;
-function SaveByteA(Data: TByteA; const FileName: string; Overwrite: Boolean = True): Boolean;
-function LoadByteA(const FileName: string): TByteA;
-
-function Endian(i: Integer): Integer;
-
-{ Files }
-function SizeOfFile(const FileName: string): Integer;
-function FileEx(const FileName: string; AllowFolders: Boolean = False): Boolean;
-function LWPSolve(const Dir: string): string;
-function LWPSlash(const Dir: string): string;
-
-function ExtractDrive(const FileName: string): string;
-function ExtractPath(const FileName: string): string;
-function ExtractPrefix(const FileName: string): string;
-function ExtractSuffix(const FileName: string): string;
-
-function IsValidFileName(const FileName: string): Boolean;
-function MakeValidFileName(FileName: string; const Default: string = 'File'): string;
-
-{ Converting }
-function IsValidInteger(const S: string): Boolean;
-function IsValidCardinal(const S: string): Boolean;
-
-function StrOfBool(flag: Boolean; const TrueStr: string = 'True';
- const FalseStr: string = 'False'): string;
-function StrOfInt(i: Integer): string;
-function CardOfStr(const S: string): Cardinal;
-
-function HexOrd(Hex: Char): THex;
-function ByteOfHex(Hex: THexByteStr): Byte;
-
-function DecOfHex(const Hex: string): string;
-function HexOfByte(b: Byte): THexByteStr;
-function HexOfCard(i: Cardinal): string; overload;
-function HexOfCard(i: Cardinal; Digits: Integer): string; overload;
-
-function PascalHexArray(a: TByteA; Name: string): string;
-
-function HexOfByteA(a: TByteA; Blocks: Integer = 1;
- const Splitter: string = ' '): string;
-function BinOfByteA(a: TByteA; Blocks: Integer = 4;
- const Splitter: string = ' '): string;
-
-function CardOfHex(Hex: string): Cardinal;
-function IntOfBin(Bin: string): Cardinal;
-
-function BinOfIntFill(n: cardinal; MinCount: Integer = 8): string;
-function BinOfInt(n: cardinal): string;
-
-function BaseNOfInt(I: Cardinal; B: TBaseN): string;
-function IntOfBaseN(V: string; B: TBaseN): Cardinal;
-
-{ Ranges }
-function KeepIn(i, Bottom, Top: Variant): Variant;
-function InRange(Value, Bottom, Top: Variant): Boolean;
-function InStrictRange(Value, Bottom, Top: Variant): Boolean;
-function Min(const A, B: Integer): Integer; overload;
-function Min(const A: TIntA): Integer; overload;
-function Max(const A, B: Integer): Integer; overload;
-function Max(const A: TIntA): Integer; overload;
-
-const
- RangesSeparator = ',';
- RangeInnerSeparator = '-';
- RangeInfinite = '*';
- RangeSpecialChars = [RangesSeparator, RangeInnerSeparator, RangeInfinite];
-
-function RangesOfStr(const S: string): TRanges;
-function InRanges(Ranges: TRanges; TestValue: Cardinal): Boolean;
-
-function Success(Res: Integer; ResultOnSuccess: Integer = ERROR_SUCCESS): Boolean;
-function Failure(Res: Integer; ResultOnSuccess: Integer = ERROR_SUCCESS): Boolean;
-
-function ExpandString(const S: string): string;
-
-{ Files }
-procedure DeleteFiles(const Mask: string; ScanSubDirs: Boolean = True;
- Attributes: Integer = faFindEveryFile);
-procedure FileNew(const FileName: string);
-function DateTimeOfFileTime(const FileTime: TFileTime): TDateTime;
-
-{ FileNames }
-function GetFileNew(FileName: string; NoFloppyDrives: Boolean = True): string;
-
-{ Finding Files }
-function FindAll(Strings: TStrings; const Mask: string;
- ScanSubDirs: Boolean = True; Attributes: Integer = faFindEveryFile;
- FileReturn: TFileNameFunc = nil): Boolean;
-function FindAllFirst(const Mask: string; ScanSubDirs: Boolean = True;
- Attributes: Integer = faFindEveryFile): string;
-
-function FullOSInfo: string;
-function Win32PlatformStr: string;
-function Win9x: Boolean;
-function WinNT: Boolean;
-function Win2000: Boolean;
-function WinXP: Boolean;
-
-var
- MyDir: string = '';
- LastSuccessRes: Integer = 0;
-
-{ Backward compatibility }
-{$IFNDEF VER130}
-function SameText(const S1, S2: string): Boolean;
-{$ENDIF}
-
-implementation
-{$IFNDEF VER140}
-uses FileCtrl;
-{$ENDIF}
-
-{$IFNDEF VER130}
-function SameText(const S1, S2: string): Boolean;
-begin
- Result := CompareText(S1, S2) = 0;
-end;
-{$ENDIF}
-
-procedure Report(const ReportName, Text: string);
-var
- F: TextFile;
- FileName: string;
-begin
- FileName := MyDir + ReportName + '.rep';
- Assign(F, FileName);
- try
- if not FileExists(FileName) then
- Rewrite(F)
- else
- Append(F);
- WriteLn(F, Text);
- finally
- Close(F);
- end;
-end;
-
-procedure ClearReport(const ReportName: string);
-var
- FileName: string;
-begin
- FileName := MyDir + ReportName + '.rep';
- DeleteFile(FileName);
-end;
-
-procedure ReportFmt(const ReportName, Fmt: string; const Args: array of const);
-begin
- Report(ReportName, Format(Fmt, Args));
-end;
-
-procedure GetParams(Strings: TStrings);
-var
- P: PChar;
- Param: string;
-
- function GetParamStr(var P: PChar; var Param: string): Boolean;
- var
- Quoted: Boolean;
- begin
- Param := '';
-
- repeat
- while (P[0] <> #0) and (P[0] <= ' ') do
- Inc(P);
-
- Quoted := False;
- while P[0] <> #0 do begin
- if P[0] = '"' then begin
- Quoted := not Quoted;
- Inc(P);
- Continue; end;
- if (P[0] <= ' ') and not Quoted then
- Break;
- Param := Param + P[0];
- Inc(P);
- end;
- until (Param <> '') or (P[0] = #0);
-
- Result := Param <> '';
- end;
-
-begin
- Strings.Clear;
- P := GetCommandLine;
- GetParamStr(P, Param);
- while GetParamStr(P, Param) do
- Strings.Add(Param);
-end;
-
-function GetParams(const Separator: string = ' '): string;
-var
- SL: TStringList;
-begin
- SL := TStringList.Create;
- GetParams(SL);
- Result := Join(SL, Separator);
- SL.Free;
-end;
-
-function Switch(const Switch: string; const PrefixChars: TCharSet = SwitchChars;
- IgnoreCase: Boolean = True): Boolean;
-//= SysUtils.FindCmdLineSwitch
-var
- i: Integer;
- s: string;
-begin
- Result := True;
-
- for i := 1 to ParamCount do begin
- s := ParamStr(i);
-
- if (s <> '') and (s[1] in PrefixChars) then begin
- //i know that always s <> '', but this is saver
- s := Copy(s, 2, MaxInt);
- if (s = Switch) or (IgnoreCase and (0=AnsiCompareText(s, Switch))) then
- Exit;
- end;
- end;
-
- Result := False;
-end;
-
-function ParamNum(const S: string): Integer;
-begin
- for Result := 1 to ParamCount do
- if 0=AnsiCompareText(ParamStr(Result), S) then
- Exit;
-
- Result := 0;
-end;
-
-function ParamPrefixNum(const Prefix: string): Integer;
-var
- Len: Integer;
-begin
- Len := Length(Prefix);
- for Result := 1 to ParamCount do
- if 0=AnsiCompareText(Copy(ParamStr(Result), 1, Len), Prefix) then
- Exit;
-
- Result := 0;
-end;
-
-function Param(const S: string): Boolean;
-begin
- Result := ParamNum(S) > 0;
-end;
-
-function ParamPrefix(const Prefix: string): Boolean;
-begin
- Result := ParamPrefixNum(Prefix) > 0;
-end;
-
-function GetParam(const Prefix: string = ''; const Default: string = ''): string;
-var
- i: Integer;
-begin
- Result := Default;
-
- if Prefix = '' then begin
- Result := ParamStr(1);
- Exit; end;
-
- i := ParamPrefixNum(Prefix);
- if i > 0 then
- Result := Copy(ParamStr(i), Length(Prefix) + 1, MaxInt);
-end;
-
-function GetMyDir(FullPath: Boolean = False): string;
-var
- Buffer: array[0..260] of Char;
-begin
- Result := '';
- SetString(Result, Buffer, GetModuleFileName(0, Buffer, SizeOf(Buffer)));
- if FullPath then
- Result := GetFileNew(Result);
- Result := ExtractPath(Result);
-end;
-
-function WinDir: string;
-var
- Res: PChar;
-begin
- Result := '\';
- GetMem(Res, MAX_PATH);
- GetWindowsDirectory(Res, MAX_PATH);
- Result := Res + '\';
- FreeMem(Res, MAX_PATH);
-end;
-
-function SysDir: string;
-var
- Res: PChar;
-begin
- Result := '\';
- GetMem(Res, MAX_PATH);
- GetSystemDirectory(Res, MAX_PATH);
- Result := Res + '\';
- FreeMem(Res, MAX_PATH);
-end;
-
-function UserName: string;
-var
- Len: Cardinal;
- Res: PChar;
-begin
- Result := '';
- GetMem(Res, MAX_PATH);
- Len := MAX_PATH;
- GetUserName(Res, Len);
- Result := Res;
- FreeMem(Res, MAX_PATH);
-end;
-
-function FirstChar(const S: string): Char;
-begin
- if s = '' then
- Result := #0
- else
- Result := s[1];
-end;
-
-function LastChar(const S: string): Char;
-begin
- if s = '' then
- Result := #0
- else
- Result := s[Length(s)];
-end;
-
-function CharPos(C: Char; const S: string; Offset: Integer = 1): Integer;
-var
- MaxPosToSearch: Integer;
-begin
- Result := Offset;
- MaxPosToSearch := Length(S);
-
- while Result <= MaxPosToSearch do begin
- if S[Result] = C then
- Exit;
- Inc(Result);
- end;
-
- Result := 0;
-end;
-
-function CharPos(C: TCharSet; const S: string; Offset: Integer = 1): Integer;
-var
- MaxPosToSearch: Integer;
-begin
- Result := Offset;
- MaxPosToSearch := Length(S);
-
- while Result <= MaxPosToSearch do begin
- if S[Result] in C then
- Exit;
- Inc(Result);
- end;
-
- Result := 0;
-end;
-
-function CharPosR(C: Char; const S: string; Offset: Integer = -1): Integer;
-begin
- if Offset < 0 then
- Result := Length(S) + 1 - Offset
- else
- Result := Offset;
- if Result > Length(S) then
- Result := Length(S);
-
- while Result > 0 do begin
- if S[Result] = C then
- Exit;
- Dec(Result);
- end;
-end;
-
-function PosEx(const SubStr, S: string; Offset: Integer = 1): Integer;
-var
- MaxPosToSearch, LenSubStr, i: Integer;
-begin
- if SubStr = '' then begin
- Result := 0;
- Exit; end;
-
- if Offset < 1 then
- Result := 1
- else
- Result := Offset;
-
- LenSubStr := Length(SubStr);
- MaxPosToSearch := Length(S) - LenSubStr + 1;
-
- while Result <= MaxPosToSearch do begin
- if S[Result] = SubStr[1] then begin
- i := 1;
-
- while (i < LenSubStr)
- and (S[Result + i] = SubStr[i + 1]) do
- Inc(i);
-
- if i = LenSubStr then
- Exit;
- end;
- Inc(Result);
- end;
-
- Result := 0;
-end;
-
-function PosExText(const SubStr, S: string; Offset: Integer = 1): Integer;
-var
- MaxPosToSearch, LenSubStr, i: Integer;
-
- function SameChar(a, b: Char): Boolean;
- begin
- Result := UpCase(a) = UpCase(b)
- end;
-
-begin
- if SubStr = '' then begin
- Result := 0;
- Exit; end;
-
- if Offset < 1 then
- Result := 1
- else
- Result := Offset;
-
- LenSubStr := Length(SubStr);
- MaxPosToSearch := Length(S) - LenSubStr + 1;
-
- while Result <= MaxPosToSearch do begin
- if SameChar(S[Result], SubStr[1]) then begin
- i := 1;
-
- while (i < LenSubStr)
- and (SameChar(S[Result + i], SubStr[i + 1])) do
- Inc(i);
-
- if i = LenSubStr then
- Exit;
- end;
- Inc(Result);
- end;
-
- Result := 0;
-end;
-
-function PosExAnsiText(const SubStr, S: string; Offset: Integer = 1): Integer;
-var
- MaxPosToSearch, LenSubStr, i: Integer;
-
- function SameChar(a, b: Char): Boolean;
- begin
- Result := CharLower(PChar(a)) = CharLower(PChar(b));
- end;
-
-begin
- if SubStr = '' then begin
- Result := 0;
- Exit; end;
-
- if Offset < 1 then
- Result := 1
- else
- Result := Offset;
-
- LenSubStr := Length(SubStr);
- MaxPosToSearch := Length(S) - LenSubStr + 1;
-
- while Result <= MaxPosToSearch do begin
- if SameChar(S[Result], SubStr[1]) then begin
- i := 1;
-
- while (i < LenSubStr)
- and (SameChar(S[Result + i], SubStr[i + 1])) do
- Inc(i);
-
- if i = LenSubStr then
- Exit;
- end;
- Inc(Result);
- end;
-
- Result := 0;
-end;
-
-function UntilChar(const S: string; Brake: Char): string;
-var
- p: Integer;
-begin
- p := CharPos(Brake, S);
-
- if p > 0 then
- Result := Copy(S, 1, p - 1)
- else
- Result := S;
-end;
-
-function UntilChar(const S: string; Brake: TCharSet): string;
-var
- p: Integer;
-begin
- Result := '';
- p := CharPos(Brake, S);
-
- if p > 0 then
- Result := Copy(S, 1, p - 1)
- else
- Result := S;
-end;
-
-function UntilLastChar(const S: string; Brake: Char;
- IgnoreNoBrake: Boolean = True): string;
-var
- p: Integer;
-begin
- Result := '';
- p := CharPosR(Brake, S);
-
- if p > 0 then
- Result := Copy(S, 1, p - 1)
- else if IgnoreNoBrake then
- Result := S;
-end;
-
-function FromChar(const S: string; Brake: Char): string;
-var
- p: Integer;
-begin
- Result := '';
- p := CharPos(Brake, S);
-
- if p > 0 then
- Result := Copy(S, p + 1, Length(S) - p);
-end;
-
-function FromChar(const S: string; Brake: TCharSet): string;
-var
- p: Integer;
-begin
- Result := '';
- p := CharPos(Brake, S);
-
- if p > 0 then
- Result := Copy(S, p + 1, Length(S) - p);
-end;
-
-function FromLastChar(const S: string; Brake: Char;
- IgnoreNoBrake: Boolean = False): string;
-var
- p: Integer;
-begin
- Result := '';
- p := CharPosR(Brake, S);
-
- if p > 0 then
- Result := Copy(S, p + 1, Length(S) - p)
- else if IgnoreNoBrake then
- Result := S;
-end;
-
-function BetweenChars(const S: string; Start, Finish: Char;
- Inclusive: Boolean = False): string;
-var
- p, fin: Integer;
-begin
- Result := '';
-
- p := CharPos(Start, S);
- if p = 0 then
- Exit;
-
- fin := CharPos(Finish, S, p + 1);
- if fin = 0 then
- Exit;
-
- if not Inclusive then begin
- Inc(p);
- Dec(fin);
- end;
-
- Result := Copy(S, p, fin - p + 1);
-end;
-
-function UntilStr(const S: string; Brake: string): string;
-var
- p: Integer;
-begin
- if Length(Brake) = 1 then begin
- Result := UntilChar(S, Brake[1]);
- Exit; end;
-
- p := PosEx(Brake, S);
-
- if p > 0 then
- Result := Copy(S, 1, p - 1)
- else
- Result := S;
-end;
-
-function FromStr(const S: string; Brake: string): string;
-var
- p: Integer;
-begin
- if Length(Brake) = 1 then begin
- Result := FromChar(S, Brake[1]);
- Exit; end;
-
- Result := '';
- p := PosEx(Brake, s);
-
- if p > 0 then begin
- Inc(p, Length(Brake));
- Result := Copy(S, p, Length(S) - p + 1);
- end;
-end;
-
-function StringWrap(const S: string; Width: Integer; const LineEnd: string = EOL): string;
-var
- i: Integer;
-begin
- Result := '';
- if (S = '') or (Width < 1) then
- Exit;
-
- i := 1;
- while True do begin
- Result := Result + Copy(S, i, Width);
- Inc(i, Width);
- if i <= Length(S) then
- Result := Result + LineEnd
- else
- Exit;
- end;
-end;
-
-function Split(const S, Separator: string; IgnoreMultiSep: Boolean = True;
- MinCount: Integer = 0): TStrA;
-var
- p, fin, SepLen: Integer;
-
- procedure Add(const S: string);
- begin
- if IgnoreMultiSep and (S = '') then
- Exit;
- SetLength(Result, Length(Result) + 1);
- Result[High(Result)] := S;
- end;
-
-begin
- if S = '' then begin
- if Length(Result) < MinCount then
- SetLength(Result, MinCount);
- Exit; end;
-
- Result := nil;
- SepLen := Length(Separator);
-
- p := 1;
- fin := PosEx(Separator, S);
- while fin > 0 do begin
- Add(Copy(S, p, fin - p));
- p := fin + SepLen;
- fin := PosEx(Separator, S, p);
- end;
- Add(Copy(S, p, Length(S) - p + 1));
-
- if Length(Result) < MinCount then
- SetLength(Result, MinCount);
-end;
-
-procedure Split(const S, Separator: string; Strings: TStrings;
- IgnoreMultiSep: Boolean = True);
-var
- p, fin, SepLen: Integer;
-
- procedure Add(const S: string);
- begin
- if IgnoreMultiSep and (S = '') then
- Exit;
- Strings.Add(S);
- end;
-
-begin
- if S = '' then
- Exit;
-
- Strings.BeginUpdate;
- SepLen := Length(Separator);
- p := 1;
- fin := PosEx(Separator, S);
- while fin > 0 do begin
- Add(Copy(S, p, fin - p));
- p := fin + SepLen;
- fin := PosEx(Separator, S, p);
- end;
- Add(Copy(S, p, Length(S) - p + 1));
- Strings.EndUpdate;
-end;
-
-function Split(const S: string; Separators: TCharSet;
- IgnoreMultiSep: Boolean = True; MinCount: Integer = 0): TStrA;
-var
- p, fin: Integer;
-
- procedure Add(const S: string);
- begin
- if IgnoreMultiSep and (S = '') then
- Exit;
- SetLength(Result, Length(Result) + 1);
- Result[High(Result)] := S;
- end;
-
-begin
- if S = '' then begin
- if Length(Result) < MinCount then
- SetLength(Result, MinCount);
- Exit; end;
-
- Result := nil;
-
- p := 1;
- fin := CharPos(Separators, S);
- while fin > 0 do begin
- Add(Copy(S, p, fin - p));
- p := fin + 1;
- fin := CharPos(Separators, S, p);
- end;
- Add(Copy(S, p, Length(S) - p + 1));
-
- if Length(Result) < MinCount then
- SetLength(Result, MinCount);
-end;
-
-procedure TileStr(const S: string; BrakeStart: Integer; BrakeEnd: Integer;
- out Left, Right: string);
-begin
- Left := Copy(S, 1, BrakeStart-1);
- Right := Copy(S, BrakeEnd + 1, MaxInt);
-end;
-
-function Join(Strings: TStrings; Separator: string = ' '): string;
-var
- i, imax: Integer;
-begin
- Result := '';
- imax := Strings.Count-1;
- for i := 0 to imax do begin
- Result := Result + Strings[i];
- if i < imax then
- Result := Result + Separator;
- end;
-end;
-
-function Join(StrA: TStrA; Separator: string = ' '): string; overload;
-var
- i: Integer;
-begin
- Result := '';
- for i := 0 to High(StrA) do begin
- Result := Result + StrA[i];
- if i < High(StrA) then
- Result := Result + Separator;
- end;
-end;
-
-function MulStr(const S: string; Count: Integer): string;
-var
- P: PChar;
- Len, i: Integer;
-begin
- Result := '';
- if Count = 0 then
- Exit;
-
- Len := Length(S);
- SetLength(Result, Len * Count);
-
- P := Pointer(Result);
- for i := 1 to Count do begin
- Move(Pointer(S)^, P^, Len);
- Inc(P, Len);
- end;
-end;
-
-function AlignR(const S: string; Width: Integer; Filler: Char = ' '): string;
-begin
- Result := MulStr(Filler, Width - Length(S)) + S;
-end;
-
-function MaxStr(const S: string; MaxLen: Integer): string;
-var
- Len: Integer;
-begin
- Len := Length(S);
- if Len <= MaxLen then begin
- Result := S;
- Exit end;
-
- Result := Copy(S, 1, MaxLen - 3) + '...';
-end;
-
-function TrimAll(const S: string): string;
-var
- i: Integer;
-begin
- for i := 1 to Length(S) do
- if S[i] > #32 then
- Result := Result + S[i];
-end;
-
-function ControlChar(C: Char): Boolean;
-begin
- Result := C in StrangeChars;
-end;
-
-function FriendlyChar(C: Char): Char;
-begin
- case C of
- #0: Result := '.';
- #1..#31: Result := '?';
- #255: Result := '#';
- else
- Result := C;
- end;
-end;
-
-function FriendlyStr(const S: string): string;
-var
- i: Integer;
-begin
- SetLength(Result, Length(S));
- for i := 1 to Length(S) do
- Result[i] := FriendlyChar(S[i]);
-end;
-
-function FriendlyStr(a: TByteA): string;
-var
- i: Integer;
-begin
- SetLength(Result, Length(a));
- for i := 0 to High(a) do
- Result[i + 1] := FriendlyChar(Char(a[i]));
-end;
-
-function Quote(const S: string; Quoter: Char = '"'): string;
-begin
- Result := S;
-
- if FirstChar(S) <> Quoter then
- Result := Quoter + Result;
-
- if LastChar(S) <> Quoter then
- Result := Result + Quoter;
-end;
-
-function DeQuote(const S: string): string;
-begin
- Result := '';
- if Length(S) > 2 then
- Result := Copy(S, 2, Length(S) - 2);
-end;
-
-function UnQuote(const S: string): string;
-var
- Start, Len: Integer;
-begin
- Start := 1;
- Len := Length(S);
-
- if (S <> '') and (S[1] in ([#0..#32] + QuoteChars)) then begin
- if (LastChar(S) = S[1]) then
- Dec(Len);
- Inc(Start);
- end;
-
- Result := Copy(S, Start, Len - Start + 1);
-end;
-
-function StrNumerus(const Value: Integer; const Singular, Plural: string;
- const Zero: string = '0'): string;
-begin
- if Abs(Value) = 1 then
- Result := IntToStr(Value) + ' ' + Singular
- else if Value = 0 then
- Result := Zero + ' ' + Plural
- else
- Result := IntToStr(Value) + ' ' + Plural;
-end;
-
-function MakeStr(const Items: array of const; Separator: string = ''): string;
-const
- BoolStrings: array[Boolean] of string = ('False', 'True');
-
-var
- i: Integer;
-
- function StrOfP(P: Pointer): string;
- begin
- if P = nil then
- Result := '[nil]'
- else
- Result := '[' + IntToStr(Cardinal(P)) + ']';
- end;
-
- procedure Add(const S: string);
- begin
- Result := Result + s + Separator;
- end;
-
-begin
- Result := '';
- for i := 0 to High(Items) do
- with Items[i] do
- case VType of
- vtString: Add(VString^);
- vtInteger: Add(IntToStr(VInteger));
- vtBoolean: Add(BoolStrings[VBoolean]);
- vtChar: Add(VChar);
- vtPChar: Add(VPChar);
- vtExtended: Add(FloatToStr(VExtended^));
- vtObject: if VObject is TComponent then
- Add(TComponent(VObject).Name)
- else
- Add(VObject.ClassName);
- vtClass: Add(VClass.ClassName);
- vtAnsiString: Add(string(VAnsiString));
- vtCurrency: Add(CurrToStr(VCurrency^));
- vtInt64: Add(IntToStr(VInt64^));
- vtVariant: Add(string(VVariant^));
-
- vtWideChar: Add(VWideChar);
- vtPWideChar: Add(VPWideChar);
- vtInterface: Add(StrOfP(VInterface));
- vtPointer: Add(StrOfP(VPointer));
- vtWideString: Add(WideString(VWideString));
- end;
- if Result <> '' then
- SetLength(result, Length(Result) - Length(Separator));
-end;
-
-procedure ShowText(const Items: array of const; Separator: string = '');
-var
- Text: string;
-begin
- Text := MakeStr(Items, Separator);
-
- MessageBox(0, PChar(Text), 'Info', MB_OK and MB_APPLMODAL);
-end;
-
-function DeleteChars(const S: string; C: Char): string;
-var
- i: Integer;
-begin
- Result := '';
- for i := 1 to Length(S) do
- if S[i] <> C then
- Result := Result + S[i];
-end;
-
-function DeleteChars(const S: string; C: TCharSet): string;
-var
- i: Integer;
-begin
- Result := '';
- for i := 1 to Length(S) do
- if not (S[i] in C) then
- Result := Result + S[i];
-end;
-
-function ExtractChars(const S: string; C: TCharSet): string;
-var
- i: Integer;
-begin
- Result := '';
- for i := 1 to Length(S) do
- if S[i] in C then
- Result := Result + S[i];
-end;
-
-function CharCount(const S: string; C: Char): Integer;
-var
- i: Integer;
-begin
- Result := 0;
- for i := 1 to Length(S) do
- if S[i] = C then
- Inc(Result);
-end;
-
-function StrAtPos(const S: string; Pos: Integer; const Str: string): Boolean;
-begin
- Result := (Str <> '') and (Str = Copy(S, Pos, Length(Str)));
-end;
-
-function TextAtPos(const S: string; Pos: Integer; const Text: string): Boolean;
-begin
- Result := (Text <> '') and SameText(Text, Copy(S, Pos, Length(Text)));
-end;
-
-function StrAtBegin(const S, Str: string): Boolean;
-begin
- Result := StrAtPos(S, 1, Str);
-end;
-
-function TextAtBegin(const S, Text: string): Boolean;
-begin
- Result := TextAtPos(S, 1, Text);
-end;
-
-function CharIn(const S: string; C: Char): Boolean;
-var
- i: Integer;
-begin
- Result := True;
- for i := 1 to Length(S) do
- if S[i] = C then Exit;
- Result := False;
-end;
-
-function CharIn(const S: string; C: TCharSet): Boolean;
-var
- i: Integer;
-begin
- Result := False;
- for i := 1 to Length(S) do begin
- Result := S[i] in C;
- if Result then
- Exit;
- end;
-end;
-
-function StrIn(const S, SubStr: string): Boolean;
-begin
- Result := PosEx(SubStr, S) > 0;
-end;
-
-function StrIn(SL: TStrings; const S: string): Boolean;
-var
- i: Integer;
-begin
- Result := False;
- for i := 0 to SL.Count-1 do begin
- Result := (S = SL[i]);
- if Result then
- Exit;
- end;
-end;
-
-function StrIn(A: TStrA; const S: string): Boolean;
-var
- i: Integer;
-begin
- Result := False;
- for i := Low(A) to High(A) do begin
- Result := (S = A[i]);
- if Result then
- Exit;
- end;
-end;
-
-function TextIn(const S, Text: string): Boolean;
-begin
- Result := PosExText(Text, S) > 0;
-end;
-
-function TextIn(SL: TStrings; const Text: string): Boolean;
-var
- i: Integer;
-begin
- Result := False;
- for i := 0 to SL.Count-1 do begin
- Result := SameText(Text, SL[i]);
- if Result then
- Exit;
- end;
-end;
-
-function TextIn(A: TStrA; const Text: string): Boolean;
-var
- i: Integer;
-begin
- Result := False;
- for i := Low(A) to High(A) do begin
- Result := SameText(Text, A[i]);
- if Result then
- Exit;
- end;
-end;
-
-function StrIndex(SL: TStrings; const S: string): Integer;
-begin
- for Result := 0 to SL.Count-1 do
- if S = SL[Result] then
- Exit;
- Result := -1;
-end;
-
-function StrIndex(A: TStrA; const S: string): Integer;
-begin
- for Result := Low(A) to High(A) do
- if S = A[Result] then
- Exit;
- Result := -1;
-end;
-
-function TextIndex(SL: TStrings; const Text: string): Integer;
-begin
- for Result := 0 to SL.Count-1 do
- if SameText(Text, SL[Result]) then
- Exit;
- Result := -1;
-end;
-
-function TextIndex(A: TStrA; const Text: string): Integer;
-begin
- for Result := Low(A) to High(A) do
- if SameText(Text, A[Result]) then
- Exit;
- Result := -1;
-end;
-
-function ReplaceChars(const S: string; Old, New: Char): string;
-var
- i: Integer;
-begin
- Result := S;
- for i := 1 to Length(Result) do
- if Result[i] = Old then
- Result[i] := New;
-end;
-
-function ReplaceChars(const S: string; Old: TCharSet; New: Char): string;
-var
- i: Integer;
-begin
- Result := S;
- for i := 1 to Length(Result) do
- if Result[i] in Old then
- Result[i] := New;
-end;
-
-function Replace(const S, Old, New: string): string;
-var
- oldp, ps: Integer;
-begin
- ps := 1;
- Result := '';
- while True do begin
- oldp := ps;
- ps := PosEx(Old, S, oldp);
- if ps = 0 then begin
- Result := Result + Copy(S, oldp, Length(S) - oldp + 1);
- Exit; end;
- Result := Result + Copy(S, oldp, ps - oldp) + New;
- Inc(ps, Length(Old));
- end;
-end;
-
-function SLOfFile(const FileName: string): TStringList;
-begin
- Result := TStringList.Create;
- if FileExists(FileName) then
- Result.LoadFromFile(FileName);
-end;
-
-function ContainsEmptyLines(SL: TStrings): Boolean;
-begin
- Result := StrIn(SL, '');
-end;
-
-procedure DeleteEmptyLines(SL: TStrings);
-var
- i: Integer;
-begin
- i := 0;
- while i < SL.Count do begin
- if SL[i] = '' then
- SL.Delete(i)
- else
- Inc(i);
- end;
-end;
-
-procedure DeleteCommentLines(SL: TStrings; const CommentSign: string = '//');
-var
- i: Integer;
-begin
- i := 0;
- while i < SL.Count do begin
- if (SL[i] = '') or (StrAtBegin(TrimLeft(SL[i]), CommentSign)) then
- SL.Delete(i)
- else
- Inc(i);
- end;
-end;
-
-function FindLine(SL: TStrings; const S: string): Integer;
-begin
- for Result := 0 to SL.Count-1 do
- if TextAtBegin(SL[Result], S) then
- Exit;
- Result := -1;
-end;
-
-procedure QuickSortSL(SL: TStringList);
-
- procedure Sort(l, r: Integer);
- var
- i,j: Integer;
- z,x: string;
- begin
- i := l;
- j := r;
- x := SL[(j + i) div 2];
- repeat
- while SL[i] < x do Inc(i);
- while SL[j] > x do Dec(j);
- if i <= j then begin
- z := SL[i];
- SL[i] := SL[j];
- SL[j] := z;
- Inc(i); Dec(j);
- end;
- until i > j;
- if j > l then Sort(l, j);
- if i < r then Sort(i, r);
- end;
-
-begin
- if SL.Count > 0 then
- Sort(0, SL.Count-1);
-end;
-
-function IncStrA(StrA: TStrA): Integer;
-begin
- SetLength(StrA, Length(StrA) + 1);
- Result := High(StrA);
-end;
-
-function StrOfByteA(a: TByteA): string;
-begin
- Result := string(Copy(a, 0, Length(a)));
-end;
-
-function ByteAOfStr(const S: string): TByteA;
-begin
- Result := TByteA(Copy(S, 1, Length(s)));
-end;
-
-function ByteAOfInt(i: Integer): TByteA;
-begin
- SetLength(Result, SizeOf(Integer));
- Move(i, Pointer(Result)^, SizeOf(Integer));
-end;
-
-function IntOfByteA(A: TByteA): Integer;
-begin
- Result := 0;
- Move(Pointer(A)^, Result, Min(Length(A), SizeOf(Integer)));
-end;
-
-function ByteAOfHex(const Hex: string): TByteA;
-var
- i: Integer;
- h: string;
-begin
- h := ExtractChars(Hex, HexadecimalChars);
- SetLength(Result, Length(h) div 2);
- for i := 0 to High(Result) do
- Result[i] := ByteOfHex(Copy(h, (i shl 1) + 1, 2));
-end;
-
-function SizeOfFile(const FileName: string): Integer;
-var
- F: file;
-begin
- AssignFile(F, FileName);
- {$I-}Reset(F, 1);{$I+}
- if IOResult = 0 then begin
- Result := FileSize(F);
- CloseFile(F);
- end else
- Result := 0;
-end;
-
-function FileEx(const FileName: string; AllowFolders: Boolean = False): Boolean;
-var
- FindData: TWin32FindData;
-begin
- if FileName = '' then begin
- Result := False;
- Exit; end;
-
- Result := (AllowFolders and DirectoryExists(FileName)) or
- (FindFirstFile(PChar(FileName), FindData) <> INVALID_HANDLE_VALUE);
- Result := Result and not CharIn(FileName, WildCards);
- Result := Result and (AllowFolders
- or ((FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0));
-end;
-
-function LWPSolve(const Dir: string): string;
-begin
- if (Dir <> '') and (Dir[Length(Dir)] = '\') then begin
- Result := Copy(Dir, 1, Length(Dir) - 1);
- end else
- Result := Dir;
-end;
-
-function LWPSlash(const Dir: string): string;
-begin
- if (Dir <> '') and (Dir[Length(Dir)] = '\') then begin
- Result := Copy(Dir, 1, Length(Dir));
- end else
- Result := Dir + '\';
-end;
-
-function ExtractDrive(const FileName: string): string;
-begin
- Result := '';
- if (Length(FileName) >= 2) and (FileName[2] = ':') then
- Result := UpperCase(FileName[1] + ':\');
-end;
-
-function ExtractPath(const FileName: string): string;
-var
- p: Integer;
-begin
- p := CharPosR('\', FileName);
- if P > 0 then
- Result := Copy(FileName, 1, p)
- else
- Result := FileName;
-end;
-
-function ExtractPrefix(const FileName: string): string;
-begin
- Result := UntilLastChar(ExtractFileName(FileName), '.');
-end;
-
-function ExtractSuffix(const FileName: string): string;
-begin
- Result := FromLastChar(ExtractFileName(FileName), '.');
-end;
-
-function SameByteA(const A, B: TByteA): Boolean;
-begin
- Result := (A = B) or ((Length(A) = Length(B)) and CompareMem(A, B, Length(A)));
-end;
-
-function Reverse(A: TByteA): TByteA;
-var
- i: Integer;
-begin
- SetLength(Result, Length(A));
-
- for i := 0 to High(A) do
- Result[High(Result) - i] := A[i];
-end;
-
-function Endian(i: Integer): Integer;
-type
- EndianArray = packed array[0..3] of Byte;
-var
- a, b: EndianArray;
-begin
- a := EndianArray(i);
- b[0] := a[3];
- b[1] := a[2];
- b[2] := a[1];
- b[3] := a[0];
- Result := Integer(b);
-end;
-
-function SaveByteA(Data: TByteA; const FileName: string;
- Overwrite: Boolean = True): Boolean;
-var
- F: file;
-begin
- if FileExists(FileName) and not Overwrite then begin
- Result := False;
- Exit end;
-
- AssignFile(F, FileName);
- {$I-}Rewrite(F, 1);{$I+}
- if IOResult = 0 then begin
- if Length(Data) > 0 then
- BlockWrite(F, Data[0], Length(Data));
- CloseFile(F);
- Result := True;
- end else
- Result := False;
-end;
-
-function LoadByteA(const FileName: string): TByteA;
-var
- F: file;
-begin
- AssignFile(F, FileName);
- {$I-}Reset(F, 1);{$I+}
- if IOResult = 0 then begin
- SetLength(Result, FileSize(F));
- if Length(Result) > 0 then
- BlockRead(F, Result[0], FileSize(F));
- CloseFile(F);
- end else
- SetLength(Result, 0);
-end;
-
-function IsValidFileName(const FileName: string): Boolean;
-begin
- Result := (FileName <> '') and not CharIn(FileName, FileNameEnemies)
- and CharIn(Trim(FileName), AllChars - ['.']);
-end;
-
-function MakeValidFileName(FileName: string; const Default: string = 'File'): string;
-begin
- if FileName = '' then
- FileName := Default;
-
- if CharIn(FileName, FileNameEnemies) then
- Result := ReplaceChars(FileName, FileNameEnemies, '_')
- else if not CharIn(Trim(FileName), AllChars - ['.']) then
- Result := Default
- else
- Result := FileName;
-end;
-
-function IsValidInteger(const S: string): Boolean;
-{const
- LowInt = '2147483648';
- HighInt = '2147483647';
-var
- len, RealLen, i, o: Integer;
- c: Char;
-begin
- Result := False;
- if S = '' then
- Exit;
-
- len := Length(S);
- o := 1;
-
- if S[1] = '-' then begin
- if len = 1 then
- Exit;
- Inc(o);
- while (o <= len) and (S[o] = '0') do
- Inc(o);
- if o > len then
- Exit;
- if o < len then begin
- RealLen := len - o + 1;
- if RealLen > Length(LowInt) then
- Exit
- else if RealLen = Length(LowInt) then begin
- for i := 1 to Length(LowInt) do begin
- c := S[i + o - 1];
- if (c < '0') or (c > LowInt[i]) then
- Exit;
- if c in ['0'..Char((Byte(LowInt[i])-1))] then
- Break;
- end;
- Inc(o, i);
- end;
- end;
- end else begin
- while (o <= len) and (S[o] = '0') do
- Inc(o);
- if o <= len then begin
- RealLen := len - o + 1;
- if RealLen > Length(HighInt) then
- Exit
- else if RealLen = Length(HighInt) then begin
- for i := 1 to Length(HighInt) do begin
- c := S[i + o - 1];
- if (c < '0') or (c > HighInt[i]) then
- Exit;
- if c in ['0'..Char((Byte(HighInt[i])-1))] then
- Break;
- end;
- Inc(o, i);
- end;
- end;
- end;
-
- for i := o to len do
- if not (S[i] in ['0'..'9']) then
- Exit;
-
- Result := True; }
-var
- i: Int64;
-begin
- i := StrToInt64Def(S, High(Int64));
- Result := (i >= Low(Integer)) and (i <= High(Integer));
-end;
-
-function IsValidCardinal(const S: string): Boolean;
-{const
- HighCard = '4294967295';
-var
- len, RealLen, i, o: Integer;
-begin
- Result := False;
- if S = '' then
- Exit;
-
- len := Length(S);
- o := 1;
-
- while (o <= len) and (S[o] = '0') do
- Inc(o);
- if o <= len then begin
- RealLen := len - o + 1;
- if RealLen > Length(HighCard) then
- Exit
- else if RealLen = Length(HighCard) then begin
- for i := 1 to Length(HighCard) do begin
- if S[i + o - 1] > HighCard[i] then
- Exit;
- if S[i + o - 1] in ['0'..Char((Byte(HighCard[i])-1))] then
- Break;
- end;
- Inc(o, i);
- end;
- end;
-
- for i := o to len do
- if not (S[i] in ['0'..'9']) then
- Exit;
-
- Result := True; }
-var
- i: Int64;
-begin
- i := StrToInt64Def(S, -1);
- Result := (i >= 0) and (i <= High(Cardinal));
-end;
-
-function StrOfBool(flag: Boolean; const TrueStr: string = 'True';
- const FalseStr: string = 'False'): string;
-begin
- if Flag then
- Result := TrueStr
- else
- Result := FalseStr;
-end;
-
-function StrOfInt(i: Integer): string;
-begin
-{ if i = 0 then begin
- Result := '0';
- Exit end;
-
- while i > 0 do begin
- Result := Char(Byte('0') + (i mod 10)) + Result;
- i := i div 10;
- end;}
- Result := IntToStr(i);
-end;
-
-function CardOfStr(const S: string): Cardinal;
-var
- Res: Int64;
-begin
- Res := StrToInt64Def(S, -1);
- if Res > High(Cardinal) then
- Res := High(Cardinal)
- else if Res < 0 then
- Res := 0;
- Result := Cardinal(Res);
-end;
-
-function HexOrd(Hex: Char): THex;
-begin
- case Hex of
- '0'..'9':
- Result := Byte(Hex) - 48;
- 'A'..'F':
- Result := Byte(Hex) - 55;
- 'a'..'f':
- Result := Byte(Hex) - 87;
- else
- Result := 0;
- end;
-end;
-
-function ByteOfHex(Hex: THexByteStr): Byte;
-begin
- Result := (HexOrd(Hex[1]) shl 4) + HexOrd(Hex[2]);
-end;
-
-function DecOfHex(const Hex: string): string;
-begin
- Result := IntToStr(CardOfHex(Hex));
-end;
-
-function HexOfByte(b: Byte): THexByteStr;
-begin
- Result := HexChar[(b and $F0) shr 4]
- + HexChar[ b and $0F ];
-end;
-
-{function HexOfCard2(c: Cardinal): string;
-var
- Data: array[0..(1 shl 4) - 1] of Char;
- i: Integer;
-begin
- for i := 0 to (1 shl 4) - 1 do
- if i < 10 then
- Data[i] := Char(Ord('0') + i)
- else
- Data[i] := Char(Ord('A') + i - 10);
-
- Result := Data[(c and (((1 shl (1 shl 2)) - 1) shl (7 shl 2))) shr (7 shl 2)]
- + Data[(c and (((1 shl (1 shl 2)) - 1) shl (6 shl 2))) shr (6 shl 2)]
- + Data[(c and (((1 shl (1 shl 2)) - 1) shl (5 shl 2))) shr (5 shl 2)]
- + Data[(c and (((1 shl (1 shl 2)) - 1) shl (4 shl 2))) shr (4 shl 2)]
- + Data[(c and (((1 shl (1 shl 2)) - 1) shl (3 shl 2))) shr (3 shl 2)]
- + Data[(c and (((1 shl (1 shl 2)) - 1) shl (2 shl 2))) shr (2 shl 2)]
- + Data[(c and (((1 shl (1 shl 2)) - 1) shl (1 shl 2))) shr (1 shl 2)]
- + Data[(c and (((1 shl (1 shl 2)) - 1) shl (0 shl 2))) shr (0 shl 2)];
-end; }
-
-function HexOfCard(i: Cardinal): string;
-var
- a: Cardinal;
-begin
- Result := '';
- while i > 0 do begin
- a := i and $F;
- Result := HexChar[a] + Result;
- i := i shr 4;
- end;
-end;
-
-function HexOfCard(i: Cardinal; Digits: Integer): string;
-var
- a: Cardinal;
-begin
- Result := '';
- while i > 0 do begin
- a := i and $F;
- Result := HexChar[a] + Result;
- i := i shr 4;
- end;
- Result := MulStr('0', Digits - Length(Result)) + Result;
-end;
-
-function PascalHexArray(a: TByteA; Name: string): string;
-var
- i, len: Integer;
-begin
- Result := 'const' + EOL +
- ' ' + Name + ': array[0..' + IntToStr(High(a)) + '] of Byte = (';
-
- len := Length(a);
- for i := 0 to len-1 do begin
- if (i mod 19) = 0 then
- Result := Result + EOL + ' ' + ' ';
- Result := Result + '$' + HexOfByte(a[i]);
- if i < len-1 then
- Result := Result + ',';
- end;
- Result := Result + EOL + ' );';
-end;
-
-function HexOfByteA(a: TByteA; Blocks: Integer = 1;
- const Splitter: string = ' '): string;
-var
- i: Integer;
-begin
- Result := '';
-
- if Blocks > 0 then
- for i := 0 to High(a) do begin
- Result := Result + HexOfByte(a[i]);
- if i < High(a) then
- if ((i+1) mod Blocks) = 0 then
- Result := Result + Splitter;
- end
- else
- for i := 0 to High(a) do
- Result := Result + HexOfByte(a[i]);
-end;
-
-function BinOfByteA(a: TByteA; Blocks: Integer = 4;
- const Splitter: string = ' '): string;
-var
- i, max: Integer;
- Bit: Boolean;
-begin
- Result := '';
-
- if Blocks > 0 then begin
- max := 8 * (High(a)) + 7;
- for i := 0 to max do begin
- Bit := 7-(i mod 8) in TBitSet(a[i div 8]);
- Result := Result + Char(Byte('0') + Byte(Bit));
- if i < max then
- if ((i+1) mod Blocks) = 0 then
- Result := Result + Splitter;
- end;
- end else
- for i := 0 to High(a) do
- Result := Result + Char(Byte('0') + a[i] shr (i and 8));
-end;
-
-function CardOfHex(Hex: string): Cardinal;
-var
- i: Integer;
-begin
- Result := 0;
- Hex := Copy(ExtractChars(Hex, HexadecimalChars), 1, 8);
-
- for i := 1 to Length(Hex) do
- if Hex[i] <> '0' then
- Inc(Result, HexOrd(Hex[i]) shl ((Length(Hex) - i) shl 2));
-end;
-
-function IntOfBin(Bin: string): Cardinal;
-var
- i: Integer;
-begin
- Result := 0;
- Bin := Copy(ExtractChars(Bin, BinaryChars), 1, 32);
-
- for i := Length(Bin) downto 1 do
- if Bin[i] = '1' then
- Inc(Result, 1 shl (Length(Bin) - i));
-end;
-
-function BinOfInt(n: Cardinal): string;
-var
- a: Integer;
-begin
- if n = 0 then begin
- Result := '0';
- exit; end;
-
- Result := '';
- while n > 0 do begin
- a := n and 1;
- Result := Char(a + Byte('0')) + Result;
- n := n shr 1;
- end;
-end;
-
-function BinOfIntFill(n: Cardinal; MinCount: Integer = 8): string;
-var
- a: Integer;
-begin
- if n = 0 then begin
- Result := MulStr('0', MinCount);
- Exit; end;
-
- Result := '';
- while n > 0 do begin
- a := n and 1;
- Result := Char(a + Byte('0')) + Result;
- n := n shr 1;
- end;
- Result := MulStr('0', MinCount - Length(Result)) + Result;
-end;
-
-function BaseNOfInt(I: Cardinal; B: TBaseN): string;
-var
- a: Integer;
-begin
- if (B < 2) or (i = 0) then begin
- Result := '0';
- Exit; end;
-
- Result := '';
- while i > 0 do begin
- a := i mod B;
- Result := BaseNChar[a] + Result;
- i := i div B;
- end;
-end;
-
-function IntOfBaseN(V: string; B: TBaseN): Cardinal;
-var
- i: Integer;
- F: Cardinal;
- c: Byte;
-begin
- Result := 0;
- V := TrimAll(V);
- F := 1;
- for i := Length(V) downto 1 do begin
- c := Byte(UpCase(V[i]));
- case Char(c) of
- '0'..'9': c := c - 48;
- 'A'..'Z': c := c - 55;
- end;
- if c < B then
- Result := Result + Byte(c) * F;
- F := F * B;
- end;
-end;
-
-function KeepIn(i, Bottom, Top: Variant): Variant;
-begin
- Result := i;
- if Result > Top then
- Result := Top
- else if Result < Bottom then
- Result := Bottom;
-end;
-
-function InRange(Value, Bottom, Top: Variant): Boolean;
-begin
- Result := (Value >= Bottom) and (Value <= Top);
-end;
-
-function InStrictRange(Value, Bottom, Top: Variant): Boolean;
-begin
- Result := (Value > Bottom) and (Value < Top);
-end;
-
-function Min(const A, B: Integer): Integer;
-begin
- if A < B then
- Result := A
- else
- Result := B;
-end;
-
-function Min(const A: TIntA): Integer;
-var
- i: Integer;
-begin
- Result := 0;
- if Length(A) = 0 then
- Exit;
-
- Result := A[0];
- for i := 1 to High(A) do
- if A[i] < Result then
- Result := A[i];
-end;
-
-function Max(const A, B: Integer): Integer;
-begin
- if A > B then
- Result := A
- else
- Result := B;
-end;
-
-function Max(const A: TIntA): Integer;
-var
- i: Integer;
-begin
- Result := 0;
- if Length(A) = 0 then
- Exit;
-
- Result := A[0];
- for i := 1 to High(A) do
- if A[i] > Result then
- Result := A[i];
-end;
-
-function RangesOfStr(const S: string): TRanges;
-var
- SL: TStringList;
- r, b, t: string;
- i, p: Integer;
-
- function TryStrToCard(const S: string; out Value: Cardinal): Boolean;
- var
- E: Integer;
- begin
- Val(S, Value, E);
- Result := E = 0;
- end;
-
-begin
- Result := nil;
- SL := TStringList.Create;
- try
- Split(S, RangesSeparator, SL);
- SetLength(Result, SL.Count);
- for i := 0 to SL.Count-1 do begin
- r := SL[i];
- with Result[i] do begin
- p := CharPos(RangeInnerSeparator, r);
- Simple := p = 0; // no '-' found
- if Simple then begin
- if r = RangeInfinite then begin // * --> *-*
- Simple := False;
- Bottom := Low(Bottom);
- Top := High(Top);
- end else if not TryStrToCard(r, Value) then
- Break;
-
- end else begin
- TileStr(r, p, p, b, t);
-
- if b = RangeInfinite then
- Bottom := Low(Bottom)
- else if not TryStrToCard(b, Bottom) then
- Break;
-
- if t = RangeInfinite then
- Top := High(Top)
- else if not TryStrToCard(t, Top) then
- Break;
- if Bottom > Top then begin
- p := Bottom; Bottom := Top; Top := p;
- end;
- end;
- end;
- end;
-
- if i <> SL.Count then
- Result := nil;
-
- finally
- SL.Free;
- end;
-end;
-
-function InRanges(Ranges: TRanges; TestValue: Cardinal): Boolean;
-var
- i: Integer;
-begin
- Result := True;
-
- for i := 0 to High(Ranges) do
- with Ranges[i] do
- if Simple then begin
- if TestValue = Value then
- Exit;
- end else begin
- if InRange(TestValue, Bottom, Top) then
- Exit;
- end;
-
- Result := False;
-end;
-
-procedure WriteSL(Strings: TStrings; const Prefix: string = '';
- const Suffix: string = '');
-var
- i: Integer;
-begin
- for i := 0 to Strings.Count-1 do
- WriteLn(Prefix + Strings[i] + Suffix);
-end;
-
-function Success(Res: Integer; ResultOnSuccess: Integer = ERROR_SUCCESS): Boolean;
-begin
- Result := (Res = ResultOnSuccess);
- LastSuccessRes := Res;
-end;
-
-function Failure(Res: Integer; ResultOnSuccess: Integer = ERROR_SUCCESS): Boolean;
-begin
- Result := not Success(Res, ResultOnSuccess);
-end;
-
-function ExpandString(const S: string): string;
-var
- Len: Integer;
- P, Res: PChar;
-begin
- Result := '';
- P := PChar(S);
- Len := ExpandEnvironmentStrings(P, nil, 0);
- if Len = 0 then
- Exit;
-
- GetMem(Res, Len);
- ExpandEnvironmentStrings(P, Res, Len);
-
- Result := Res;
- FreeMem(Res, Len);
-end;
-
-function FindAll(Strings: TStrings; const Mask: string;
- ScanSubDirs: Boolean = True; Attributes: Integer = faFindEveryFile;
- FileReturn: TFileNameFunc = nil): Boolean;
-var
- Path, FileName: string;
-
- procedure ScanDir(const Path, FileName: string);
- var
- PSR: TSearchRec;
- Res: Integer;
-
- procedure Add(const S: string);
- begin
- if S <> '' then
- Strings.Add(S);
- end;
-
- begin
- Res := FindFirst(Path + FileName, Attributes, PSR);
- while Success(Res, 0) do begin
- if Assigned(FileReturn) then
- Add(FileReturn(Path + PSR.Name))
- else
- Add(Path + PSR.Name);
- Res := FindNext(PSR);
- end;
- FindClose(PSR);
- if not ScanSubDirs then
- Exit;
-
- Res := FindFirst(Path + '*', faDirectory, PSR);
- while Success(Res, 0) do begin
- if (PSR.Attr and faDirectory > 0)
- and (PSR.Name <> '.') and (PSR.Name <> '..') then
- ScanDir(Path + PSR.Name + '\', FileName);
- Res := FindNext(PSR);
- end;
- FindClose(PSR);
- end;
-
-begin
- Strings.Clear;
- Path := ExtractPath(Mask);
- FileName := ExtractFileName(Mask);
- ScanDir(Path, FileName);
- Result := Strings.Count > 0;
-end;
-
-function FindAllFirst(const Mask: string; ScanSubDirs: Boolean = True;
- Attributes: Integer = faFindEveryFile): string;
-var
- Path, FileName: string;
-
- function ScanDir(const Path, FileName: string): Boolean;
- var
- PSR: TSearchRec;
- Res: Integer;
- begin
- Result := False;
- if Success(FindFirst(Path + FileName, Attributes, PSR), 0) then begin
- FindAllFirst := Path + PSR.Name;
- Result := True;
- FindClose(PSR);
- Exit; end;
- if not ScanSubDirs then
- Exit;
-
- Res := FindFirst(Path + '*', faDirectory, PSR);
- while not Result and Success(Res, 0) do begin
- if (PSR.Attr and faDirectory > 0)
- and (PSR.Name <> '.') and (PSR.Name <> '..') then
- Result := ScanDir(Path + PSR.Name + '\', FileName);
- Res := FindNext(PSR);
- end;
- FindClose(PSR);
- end;
-begin
- Result := '';
- Path := ExtractPath(Mask);
- FileName := ExtractFileName(Mask);
- ScanDir(Path, FileName);
-end;
-
-procedure DeleteFiles(const Mask: string; ScanSubDirs: Boolean = True;
- Attributes: Integer = faFindEveryFile);
-var
- Path, FileName: string;
-
- procedure ScanDir(const Path, FileName: string);
- var
- PSR: TSearchRec;
- Res: Integer;
-
- procedure TryDeleteFile(const FileName: string);
- begin
- try
- DeleteFile(Path + PSR.Name);
- except
- end;
- end;
-
- begin
- Res := FindFirst(Path + FileName, Attributes, PSR);
- while Success(Res, 0) do begin
- TryDeleteFile(Path + PSR.Name);
- Res := FindNext(PSR);
- end;
- FindClose(PSR);
- if not ScanSubDirs then
- Exit;
-
- Res := FindFirst(Path + '*', faDirectory, PSR);
- while Success(Res, 0) do begin
- if (PSR.Attr and faDirectory > 0)
- and (PSR.Name <> '.') and (PSR.Name <> '..') then begin
- ScanDir(Path + PSR.Name + '\', FileName);
- TryDeleteFile(Path + PSR.Name);
- end;
- Res := FindNext(PSR);
- end;
- FindClose(PSR);
- end;
-begin
- Path := ExtractPath(Mask);
- FileName := ExtractFileName(Mask);
- ScanDir(Path, FileName);
-end;
-
-function GetFileNew(FileName: string; NoFloppyDrives: Boolean = True): string;
-var
- Drive: string;
- pf, pd, Len: Integer;
- PSR: TSearchRec;
-begin
- Result := '';
- FileName := Trim(FileName);
- if Length(FileName) < 2 then
- Exit;
-
- Drive := ExtractDrive(FileName);
- if not DirectoryExists(Drive) then
- Exit;
-
- if NoFloppyDrives and (Drive[1] in ['A', 'B']) then
- Exit;
-
- Len := Length(FileName);
- Result := Drive;
- pf := Length(Drive) + 1;
- while pf <= Len do begin
- if FileName[pf] = '\' then begin
- Result := Result + '\';
- Inc(pf);
- Continue; end;
-
- pd := CharPos('\', FileName, pf);
- if pd = 0 then begin
- if 0=FindFirst(Result + Copy(FileName, pf, MaxInt), faFindEveryFile, PSR) then begin
- Result := Result + PSR.Name;
- Break; end else begin
- FindClose(PSR);
- if 0=FindFirst(Result + Copy(FileName, pf, MaxInt), faDirectory, PSR) then
- Result := Result + PSR.Name + '\'
- else
- Result := '';
- FindClose(PSR);
- if Result = '' then
- Break;
- end;
- end;
-
- if 0=FindFirst(Result + Copy(FileName, pf, pd - pf), faDirectory, PSR) then
- Result := Result + PSR.Name + '\'
- else
- Result := '';
- FindClose(PSR);
- if Result = '' then
- Break;
-
- pf := pd + 1;
- end;
-
- if (Result <> '') and not FileEx(Result, True) then
- Result := '';
-end;
-
-function DateTimeOfFileTime(const FileTime: TFileTime): TDateTime;
-var
- LocalFileTime: TFileTime;
- Res: Integer;
-begin
- Result := 0;
-
- FileTimeToLocalFileTime(FileTime, LocalFileTime);
- if not FileTimeToDosDateTime(LocalFileTime, LongRec(Res).Hi,
- LongRec(Res).Lo) then
- Res := -1;
-
- if (Res = -1) or (Res = 0) then
- Exit;
- try
- Result := FileDateToDateTime(Res);
- except
- end;
-end;
-
-procedure FileNew(const FileName: string);
-var
- Handle: Integer;
-begin
- Handle := FileCreate(FileName);
- FileClose(Handle);
-end;
-
-function Win32PlatformStr: string;
-const
- PlatformStrings: array[VER_PLATFORM_WIN32s..VER_PLATFORM_WIN32_NT] of string =
- ('VER_PLATFORM_WIN32s', 'VER_PLATFORM_WIN32_WINDOWS', 'VER_PLATFORM_WIN32_NT');
-begin
- Result := PlatformStrings[Win32Platform];
-end;
-
-function FullOSInfo: string;
-begin
- Result := Format(
- 'Platform: %s' + EOL +
- 'Version: %d.%d Build %d' + EOL +
- 'CSD: %s',
- [
- Win32PlatformStr,
- Win32MajorVersion, Win32MinorVersion, Win32BuildNumber,
- Win32CSDVersion
- ]
- );
-end;
-
-function Win9x: Boolean;
-begin
- Result := Win32Platform = VER_PLATFORM_WIN32_WINDOWS;
-end;
-
-function WinNT: Boolean;
-begin
- Result := Win32Platform = VER_PLATFORM_WIN32_NT;
-end;
-
-function Win2000: Boolean;
-begin
- Result := (Win32Platform = VER_PLATFORM_WIN32_NT)
- and (Win32MajorVersion = 4);
-end;
-
-function WinXP: Boolean;
-begin
- Result := Win32MajorVersion >= 5;
-end;
-
-initialization
- MyDir := GetMyDir;
-
-end.
-
-unit FifoStream;
-
-interface
-
-uses Classes, windows, Dialogs;
-
-const
- DefaultChunksize = 32768; // 32kb per chunk as default.
-
-type
- PMemChunk = ^TMemChunk;
- TMemChunk = record
- Filled: Longword;
- Read: Longword;
- Data: pointer;
- end;
-
- TFifo = class
- private
- FBuffers: TList;
- FChunksize: Longword;
- FCritSect: TRTLCriticalSection;
- FIsWinNT: boolean;
- FBytesInFifo: LongWord;
- protected
- function GetBytesInFifo: LongWord;
- public
- constructor Create;
- destructor Destroy; override;
- procedure Write(Data: pointer; Size: LongWord);
- procedure Read(Buff: pointer; var ReqSize: LongWord);
- procedure PeekData(Buff: pointer; var ReqSize: LongWord);
- published
- property BytesInFifo: LongWord read FBytesInFifo;
- end;
-
-implementation
-
-constructor TFifo.Create;
-begin
- inherited;
- FBuffers := TList.Create;
- // set default chunksize...
- FChunksize := DefaultChunksize;
- InitializeCriticalSection(FCritSect);
-end;
-
-destructor TFifo.Destroy;
-var
- I: Integer;
-begin
- EnterCriticalSection(FCritSect);
- for I := 0 to FBuffers.count - 1 do
- begin
- FreeMem(PMemChunk(Fbuffers[I]).Data);
- Dispose(PMemChunk(Fbuffers[I]));
- end;
- FBuffers.Clear;
- FBuffers.Free;
- LeaveCriticalSection(FCritSect);
-
- DeleteCriticalSection(FCritSect);
- inherited;
-end;
-
-function TFifo.GetBytesInFifo: LongWord;
-begin
- Result := 0;
- if FBuffers.Count = 0 then
- begin
- exit;
- end
- else
- begin
- if FBuffers.Count > 1 then
- Inc(Result, (FBuffers.Count - 1) * FChunkSize);
- Inc(Result, PMemChunk(FBuffers[Fbuffers.Count - 1]).Filled);
- Dec(Result, PMemChunk(FBuffers[0]).Read);
- end;
-end;
-
-procedure TFifo.Write(Data: pointer; Size: LongWord);
-var
- Privpointer: pointer;
- PrivSize: LongWord;
- Chunk: PMemChunk;
- PosInChunk: pointer;
-begin
- if LongWord(Data) = 0 then
- begin
- // null pointer? somebody is trying to fool us, get out...
- Exit;
- end;
- EnterCriticalSection(FCritSect);
- PrivPointer := Data;
- PrivSize := 0;
- // are already buffers there?
- if FBuffers.count > 0 then
- begin
- // is the last one of them not completely filled?
- if PMemChunk(FBuffers[FBuffers.count - 1]).filled < FChunksize then
- // not completely filled, so fill up the buffer.
- begin
- Chunk := PMemChunk(FBuffers[FBuffers.count - 1]);
- // fetch chunkdata.
- PosInChunk := Chunk.Data;
- // move to current fill pos...
- Inc(LongWord(PosInChunk), Chunk.Filled);
- // can we fill the chunk completely?
- if Size > FChunksize - Chunk.Filled then
- begin
- // yes we can.
- Move(PrivPointer^, PosInChunk^, FChunksize - Chunk.Filled);
- Inc(PrivSize, FChunksize - Chunk.Filled);
- Inc(LongWord(PrivPointer), FChunksize - Chunk.Filled);
- Chunk.Filled := FChunkSize;
- end
- else
- // we have to less data for filling the chunk completely,
- // just put everything in.
- begin
- Move(PrivPointer^, PosInChunk^, Size);
- Inc(PrivSize, Size);
- Inc(Chunk.Filled, Size);
- end;
- end;
- end;
- // as long as we have remaining stuff put it into new chunks.
- while (PrivSize < Size) do
- begin
- new(Chunk);
- GetMem(Chunk.Data, FChunksize);
- Chunk.Read := 0;
- // can we fill an entire chunk with the remaining data?
- if Privsize + FChunksize < Size then
- begin
- // yes we can, so put the stuff in.
- Move(Privpointer^, Chunk.Data^, FChunksize);
- Inc(LongWord(PrivPointer), FChunksize);
- Inc(PrivSize, FChunksize);
- Chunk.Filled := FChunksize;
- end
- else // we have to less data to fill the entire chunk, just put the remaining stuff in.
- begin
- Move(Privpointer^, Chunk.Data^, Size - Privsize);
- Chunk.Filled := Size - Privsize;
- Inc(PrivSize, Size - Privsize);
- end;
- Fbuffers.Add(Chunk);
- end;
- if Size <> Privsize then
- Showmessage('miscalculation in TFifo.write');
- FBytesInFifo := GetBytesInFifo;
- LeaveCriticalSection(FCritSect);
-end;
-
-procedure TFifo.Read(Buff: pointer; var ReqSize: LongWord);
-var
- PrivSize: Integer;
- Privpos: pointer;
- Chunk: PMemChunk;
- ChunkPos: pointer;
-begin
- if LongWord(Buff) = 0 then
- begin
- // null pointer? somebody is trying to fool us, get out...
- Exit;
- end;
- EnterCriticalSection(FCritSect);
- PrivSize := 0;
- Privpos := Buff;
- while FBuffers.Count > 0 do
- begin
- Chunk := PMemChunk(FBuffers[0]);
- ChunkPos := Chunk.data;
- Inc(LongWord(ChunkPos), Chunk.Read);
- // does the remaining part of the chunk fit into the buffer?
- if PrivSize + (Chunk.Filled - Chunk.read) < ReqSize then
- begin // yep, it fits
- Move(ChunkPos^, Privpos^, Chunk.Filled - Chunk.read);
- Inc(PrivSize, Chunk.Filled - Chunk.read);
- FreeMem(Chunk.Data);
- Dispose(Chunk);
- FBuffers.Delete(0);
- end
- else // remaining part didn't fit, get as much as we can and increment the
- // read attribute.
- begin
- Move(ChunkPos^, Privpos^, ReqSize - PrivSize);
- Inc(Chunk.read, ReqSize - PrivSize);
- Inc(PrivSize, ReqSize - PrivSize);
- // as we filled the buffer, we'll have to break here.
- break;
- end;
- end;
- FBytesInFifo := GetBytesInFifo;
- LeaveCriticalSection(FCritSect);
- ReqSize := PrivSize;
-end;
-
-// read Data from Stream without removing it from the Stream...
-
-procedure TFifo.PeekData(Buff: pointer; var ReqSize: LongWord);
-var
- PrivSize: Integer;
- Privpos: pointer;
- Chunk: PMemChunk;
- ChunkPos: pointer;
- ChunkNr: Integer;
-begin
- if LongWord(Buff) = 0 then
- begin
- // null pointer? somebody is trying to fool us, get out...
- Exit;
- end;
- EnterCriticalSection(FCritSect);
- PrivSize := 0;
- Privpos := Buff;
- ChunkNr := 0;
- while FBuffers.Count > ChunkNr do
- begin
- Chunk := PMemChunk(FBuffers[ChunkNr]);
- ChunkPos := Chunk.data;
- Inc(LongWord(ChunkPos), Chunk.Read);
- // does the remaining part of the chunk fit into the buffer?
- if PrivSize + (Chunk.Filled - Chunk.read) < ReqSize then
- begin // yep, it fits
- Move(ChunkPos^, Privpos^, Chunk.Filled - Chunk.read);
- Inc(PrivSize, Chunk.Filled - Chunk.read);
- Inc(ChunkNr);
- end
- else // remaining part didn't fit, get as much as we can and increment the
- // read attribute.
- begin
- Move(ChunkPos^, Privpos^, ReqSize - PrivSize);
- Inc(PrivSize, ReqSize - PrivSize);
- // as we filled the buffer, we'll have to break here.
- break;
- end;
- end;
- LeaveCriticalSection(FCritSect);
- ReqSize := PrivSize;
-end;
-
-end.
diff --git a/bench/example.html b/bench/example.html
deleted file mode 100644
index cef55da..0000000
--- a/bench/example.html
+++ /dev/null
@@ -1,169 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
-<head><title>Faszination Tolkien - Herr der Ringe &amp; Co.</title>
-<meta name="description" content="J.R.R. Tolkien und seine Werke (Schwerpunkt: Der Herr der Ringe). Anf&auml;ngerfreundlich gestaltet. Gro&szlig;e kommentierte Galerie, Downloads, Forum, Postkarten, etc." />
-<meta name="Author" content="Vladimir Simovic aka Perun" />
-<meta name="Keywords" content="J.R.R. Tolkien, Tolkien, Herr der Ringe, Der Herr der Ringe, HdR, hdr, herr ringe, Perun, Vladimir Simovic, Herr der Ringe Motive, Herr der Ringe Postkarten, kleiner hobbit, ringcon, ring*con" />
-<meta name="page-topic" content="J.R.R. Tolkien und seine Werke. Speziell Der Herr der Ringe" />
-<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
-<meta name="language" content="de" />
-<meta name="robots" content="index,follow" />
-<meta name="revisit-after" content="7 days" />
-<meta http-equiv="imagetoolbar" content="no" />
-<style type="text/css">
-<!--
-@import url("/css/perun.css");
--->
-</style>
-<link rel="shortcut icon" href="http://www.faszination-tolkien.de/favicon.ico" />
-<link rel="home" href="/" title="Startseite" />
-<link rel="author" href="mailto:perun@faszination-tolkien.de,faszination-tolkien@web.de" title="Mail" />
-<link rel="copyright" href="/kontakte/impressum" title="Impressum" />
-<link rel="index" href="/hilfe/sitemap" title="Inhaltsverzeichnis" />
-<link rel="help" href="/hilfe/faq" title="FAQ" />
-<link rel="search" href="/hilfe/suchen" />
-<link rel="download" href="/goodies/downloads" />
-<link rel="bookmark" href="http://www.faszination-tolkien.de" title="Faszination Tolkien" />
-<script type="text/javascript">
-<!--
-if(top.frames.length > 0)
-top.location.href=self.location;
-//-->
-</script>
-</head>
-<body>
-<div id="kopf" title="Anmerkungen zu den Bildern und &copy; in dem Styleswitch-Bereich">
-</div>
-<div id="inhalt">
-<div style="font:11px verdana, sans-serif; margin:3px 0 0 0;">
-<script type="text/javascript">
-<!-- start js_paths.js???
-var path = "";
-var href = document.location.href;
-var s = href.split("/");
-for (var i=2;i<(s.length-1);i++) {
-path+="<a href=\""+href.substring(0,href.indexOf(s[i])+s[i].length)+"/\">"+s[i]+"</a> / ";
-}
-i=s.length-1;
-path+="<a href=\""+href.substring(0,href.indexOf(s[i])+s[i].length)+"\">"+s[i]+"</a>";
-var url = /* window.location.protocol + "//" + */ path;
-document.writeln(url);
-// ende -->
-</script>
-
-</div>
-<h1>Faszination Tolkien - Herr der Ringe &amp; Co.</h1>
-
-<p>Diese Seite besch&auml;ftigt sich mit den &quot;Hauptwerken&quot; von J. R. R. Tolkien. Im Mittelpunkt steht <strong>Der Herr der Ringe</strong>, aber nach und nach werden immer mehr Details aus <strong>Der kleine Hobbit</strong> bzw. <strong>Der Hobbit</strong> und <strong>Silmarillion</strong> einflie&szlig;en.</p>
-<p>Auf der Seite gibt es, neben vielen selbstverfassten Infos, eine gro&szlig;e <a href="/galerie">Galerie</a> mit 'Herr der Ringe' Bildern (273 Bilder), eine <a href="goodies/downloads">Download</a> Sektion mit 13 <a href="goodies/downloads/winamp-skins">Winampskins</a> und einen <a href="http://www.guweb.com/cgi-bin/postcard?id=PERUN">eCard Versand</a> (digitale Postkarten) mit 'Herr der Ringe' Motiven.</p>
-<p><b>Anmerkung:</b> die Unterpunkte in der Navigation, einige Links im Text und viele Bilder haben Informationen (Titel), daher lohnt es sich den Cursor, &uuml;ber den Link ruhen zu lassen. Einige h&auml;ufige Fragen wurden schon in dem Bereich <a href="/hilfe/faq">FAQ</a> beantwortet.</p>
-
-<p>Immer auf dem laufenden bleiben? Mit <a href="goodies/newsletter">Newsletter</a>, <a href="javascript:sidebar.addPanel('Faszination-Tolkien','http://www.faszination-tolkien.de/goodies/sidebar/index.php','')">Sidebar</a> (Mozilla und Netscape ab 6.x) oder mit <a href="goodies/rss/index.xml">RSS</a>.</p>
-
-<p><strong><a href="goodies/styleswitcher">Styleswitcher</a></strong> - &auml;ndere das Aussehen dieser Seite.</p>
-
-<p><strong>Diese Website wird aus Zeitgründen nicht mehr aktualisiert.</strong></p>
-
-
-<div style="text-align:center; padding:5px;">
-<!-- Anfang Banner -->
-
-<img src="http://www.die-gefaehrten.net/banner.php?banner=minitolkien&amp;id=68" width="100" height="50" alt="Webring Banner (minitolkien)" border="0" usemap="#gef_banner_minitolkien" />
-<map name="gef_banner_minitolkien" id="gef_banner_minitolkien" style="display:inline;">
- <area shape="rect" href="http://www.die-gefaehrten.net/jump.php?action=next&amp;id=68" alt="N&auml;chste Seite" title="N&auml;chste Seite" coords="70,30,100,50" />
- <area shape="rect" href="http://www.die-gefaehrten.net/jump.php?action=prev&amp;id=68" alt="Vorherige Seite" title="Vorherige Seite" coords="0,30,30,50" />
- <area shape="rect" href="http://www.die-gefaehrten.net/jump.php?action=home&amp;id=68" alt="Die Gef&auml;hrten Homepage" title="Die Gef&auml;hrten Homepage" coords="0,0,100,25" />
-</map>
-
-<!--<img src="links/fremde-banner/minitolkien.jpg" width="100" height="50" alt="Webring &quot;Die Gef&auml;hrten&quot;" ismap="ismap" usemap="#minitolkien" />
-<map name="minitolkien" id="minitolkien" style="display:inline;"><area shape="rect" alt="N&auml;chste Seite" href="http://www.die-gefaehrten.net/jump.php?action=next&amp;id=Vladimir" coords="73,29,96,46" /><area shape="rect" alt="Vorherige Seite" href="http://www.die-gefaehrten.net/jump.php?action=prev&amp;id=Vladimir" coords="4,30,26,46" /><area shape="rect" alt="Die Gef&auml;hrten" href="http://www.die-gefaehrten.net/jump.php?action=home&amp;id=Vladimir" coords="5,5,95,23" /></map>-->
-<!-- Ende Banner -->
-
-<a href="http://pl15994.macbay.de/mozilla/bestviewedwithmozilla.htm" title="Best viewed with Mozilla or any other Browser"><img src="links/fremde-banner/bestviewedwithmozill.gif" width="169" height="29" alt="Best viewed with Mozilla or any other Browser" /></a>
-
-<!-- Anfang des Topsites Codes der Listinus-Toppages -->
-<a href="http://click.listinus.de/topsite.php?id=34908" title="Top 50 Herr der Ringe - stimme f&uuml;r diese Seite ab."><img src="http://icon.listinus.de/topicon.php?id=34908" alt="Top 50 Herr der Ringe - stimme f&uuml;r diese Seite ab." /></a>
-<!-- Ende des Topsites Codes der Listinus-Toppages -->
-</div>
-
-<div style="text-align:center; padding:5px;">
-<form method="post" action="http://www.drachenritter.de/webring.php3" style="display:inline;">
-<input type="hidden" name="id" value="585" />
-<input type="hidden" name="mini" value="on" />
-<input type="image" src="/links/fremde-banner/minidrachenritter.jpg" name="click" title="Webring der Drachenritter" />
-</form>
-
-<a href="http://www.schatzwaechter.de"><img src="links/fremde-banner/faszinationtolkien.gif" width="128" height="56" alt="Schatzw&auml;chter" /></a>
-</div>
-
-<p>
-Faszination Tolkien ist zudem noch bei folgenden gro&szlig;en <a href="/die-seite/awards#wichtige-linklisten">Linklisten</a> aufgenommen.
-</p>
-
-<p class="fussanker"><a href="#">nach oben</a></p>
-</div>
-
-<div id="linkenavi"><!--linke seite-->
-<a href="/kurzfassungen/" class="navilinks">Kurzfassungen <span class="hide">&raquo; <b>Tolkiens Welt:</b> Die Zusammenfassung von Herr der Ringe und Der Hobbit. &laquo;</span><br /></a>
-
-<a href="/ringe/" class="navilinks">Die Ringe <span class="hide">&raquo; <b>Tolkiens Welt:</b> Die Ringe der Macht. &laquo;</span><br /></a>
-
-<a href="/geschichte/" class="navilinks">Die Geschichte <span class="hide">&raquo; <b>Tolkiens Welt:</b> Die Geschichte von Arda bzw. Mittelerde. &laquo;</span><br /></a>
-
-<a href="/landeskunde/" class="navilinks">Landeskunde <span class="hide">&raquo; <b>Tolkiens Welt:</b> Geopolitische Informationen &uuml;ber Mittelerde. &laquo;</span><br /></a>
-
-<a href="/personen/" class="navilinks">Personen <span class="hide">&raquo; <b>Tolkiens Welt:</b> Wichtige Personen. &laquo;</span><br /></a>
-
-<a href="/volk/" class="navilinks" style="margin-bottom:10px;">V&ouml;lker/Wesen <span class="hide">&raquo; <b>Tolkiens Welt:</b> Verschiedene V&ouml;lker und Wesen von Arda bzw. Mittelerde. &laquo;</span><br /></a>
-<!---->
-<a href="/jrr-tolkien/" class="navilinks">J. R. R. Tolkien <span class="hide">&raquo; <b>Person Tolkien:</b> Eine kurze Biographie &uuml;ber Tolkien; B&uuml;cherliste mit Werken von Tolkien und Sekund&auml;rliteratur. &laquo;</span><br /></a>
-
-<a href="/galerie/" class="navilinks">Galerie <span class="hide">&raquo; <b>Bilder</b> von K&uuml;nstlern, die von Tolkiens Werken Inspiriert wurden. &laquo;</span><br /></a>
-<!---->
-<a href="/ueberlegungen/" class="navilinks" style="margin-bottom:10px;">&Uuml;berlegungen <span class="hide">&raquo; <b>Spekulation</b>, Gedanken zu diversen Ereignissen in Mittelerde. &laquo;</span><br /></a>
-<a href="/filme/" class="navilinks"> Film/e <span class="hide">&raquo; <b>Tolkien und Medien:</b> Infos zu den beiden Verfilmungen von Herr der Ringe. &laquo;</span>
-<br /></a>
-<a href="/spiele/" class="navilinks">Spiele <span class="hide">&raquo; <b>Tolkien und Medien:</b> Versch. Spiele rund um Tolkiens Werke: Brett- und Kartenspiele, PC Spiele, Online Spiele etc. &laquo;</span><br /></a>
-<a href="/fans/" class="navilinks">Fans <span class="hide">&raquo; <b>Fans und Ihre Aktivit&auml;ten:</b> Interviews, &quot;Dein erstes Mal&quot; etc. &laquo;</span><br /></a>
-</div><!--ende linker seite-->
-
-<div id="rechtenavi"><!--rechte seite-->
-<a href="/news/" class="navilinks">News <span class="hide2">&raquo; <b>Neuigkeiten:</b> &uuml;ber Tolkiens Werke, den Film, &uuml;ber die Seite etc. &laquo;</span><br /></a>
-
-<a href="/termine/" class="navilinks" style="margin-bottom:10px;">Termine <span class="hide2">&raquo; <b>Anstehende Veranstaltungen</b> zum Thema J. R. R. Tolkien und seine Werke. &laquo;</span><br /></a>
-<!---->
-<a href="/kontakte" class="navilinks">Kontakte <span class="hide2">&raquo; Impressum, Kontaktformular, Presseinfos &laquo;</span><br /></a>
-<a href="/interaktiv" class="navilinks">Interaktiv <span class="hide2">&raquo; <b>Forum, G&auml;stebuch,</b> Umfragen, Chat. &laquo;</span><br /></a>
-<a href="/hilfe" class="navilinks">Hilfe <span class="hide2">&raquo; Suche, FAQ, Sitemap. &laquo;</span><br /></a>
-<a href="/goodies" class="navilinks">Goodies <span class="hide2">&raquo; Newsletter, Sidebar, Styleswitcher, eCards, Winampskins, Downloads, Weiterempfehlen. &laquo;</span><br /></a>
-<a href="/die-seite" class="navilinks" style="margin-bottom:10px;">Die Seite <span class="hide2">&raquo; Ruhmeshalle bzw. Awards, Warum? etc. &laquo;</span><br /></a>
-
-<!---->
-<a href="/links/" class="navilinks">Links <span class="hide2">&raquo; Links zu anderen Tolkien Seiten und zu Webringen. Banner zum Bannertausch. &laquo;</span><br /></a>
-
-<a href="/empfehlungen/" class="navilinks">Empfehlungen <span class="hide2">&raquo; <b>Meine Empfehlungen:</b> B&uuml;cher, Spiele etc. &laquo;</span><br /></a>
-
-<a href="/wettbewerbe" class="navilinks">Wettbewerbe <span class="hide2">&raquo; Wettbewerbe und Gewinnspiele. &laquo;</span><br /></a>
-</div><!--ende rechter seite-->
-
-<div id="fuss">
-<div class="center">
-G&uuml;ltiges <a href="http://validator.w3.org/check/referer"
-
- title="Diese Seite h&auml;lt sich an die Webstandards">XHTML 1.0</a> und g&uuml;ltiges <a href="http://jigsaw.w3.org/css-validator/validator?uri=http://www.faszination-tolkien.de/css/perun.css"
-
- title="Diese Seite h&auml;lt sich an die Webstandards">CSS</a>
-<br />
-2002-2006 by <a href="/kontakte/impressum/" title="Kontakt mit dem Webmaster">Perun</a> - Letzte &Auml;nderung: 04.03.2006 01:56:23<br />
-<a href="http://www.faszination-tolkien.de">www.faszination-tolkien.de</a> || <a href="http://www.herr-der-ringe.ws">www.herr-der-ringe.ws</a> || <a href="http://www.perun.net">www.perun.net</a>
-<br />
-<span class="sehrklein">Webdesign by: <a href="http://www.vlad-design.de" title="Vlad-Design: Webdesign von Vladimir Simovic">Vlad-Design</a> || hosted by: <a href="http://www.all-inkl.com/index.php?partner=14435" title="Sehr gute und g&uuml;nstige Webhosting-Angebote">www.all-inkl.com</a></span>
-</div>
-<p class="unsichtbar">&rarr;Hinweis: Schon mal dar&uuml;ber nachgedacht deinen Browser upzudaten?<br />Auf z. B. Mozilla, oder Netscape 7.x, oder Opera 7.x oder zumindest auf Internet Explorer 6.</p>
-</div>
-<!-- PowerPhlogger Code START -->
-<script language="JavaScript" type="text/javascript" src="/pphlogger.js"></script>
-<noscript><img alt="" src="http://www.faszination-tolkien.de/statistik/pphlogger.php?id=Perun&amp;st=img" /></noscript>
-<!-- PowerPhlogger Code END -->
-</body>
-</html>
diff --git a/bench/example.json b/bench/example.json
deleted file mode 100644
index 953a193..0000000
--- a/bench/example.json
+++ /dev/null
@@ -1,655 +0,0 @@
-[
- {
- "import_url": "http:\/\/localhost:3000\/neighbourhoods\/Neighbourhoods::Storage\/import",
- "type": "Neighbourhood",
- "reflected": false,
- "selected": true,
- "export_url": "http:\/\/localhost:3000\/neighbourhoods\/Neighbourhoods::Storage\/export",
- "snapshots_url": "http:\/\/localhost:3000\/snapshots",
- "uri": "http:\/\/localhost:3000\/neighbourhoods\/Neighbourhoods::Storage\/lists",
- "print_url": "http:\/\/localhost:3000\/neighbourhoods\/Neighbourhoods::Storage\/print",
- "locked": false,
- "name": "Lager",
- "lists": [
- {
- "type": "List",
- "sort_keys": {
- "options": [
- {
- "name": "Standardsortierung",
- "id": null
- }
- ]
- },
- "uri": "http:\/\/localhost:3000\/lists\/Lists::Manufacturers\/elements.json",
- "sort_key_uri": "http:\/\/localhost:3000\/lists\/Lists::Manufacturers\/sort_key",
- "name": "Hersteller",
- "readable": true,
- "id": "Lists::Manufacturers",
- "element_types": [
- {
- "create_element_url": "http:\/\/localhost:3000\/elements?list=Lists%3A%3AManufacturers&type=Elements%3A%3AManufacturer",
- "essential_attributes": [
- ],
- "name": "Hersteller",
- "ask_for_email": false,
- "id": "Elements::Manufacturer"
- }
- ],
- "writable": true
- },
- {
- "type": "List",
- "sort_keys": {
- "options": [
- {
- "name": "Standardsortierung",
- "id": null
- }
- ]
- },
- "uri": "http:\/\/localhost:3000\/lists\/Lists::Categories\/elements.json",
- "sort_key_uri": "http:\/\/localhost:3000\/lists\/Lists::Categories\/sort_key",
- "name": "Rubriken",
- "readable": true,
- "id": "Lists::Categories",
- "element_types": [
- {
- "create_element_url": "http:\/\/localhost:3000\/elements?list=Lists%3A%3ACategories&type=Elements%3A%3ACategory",
- "essential_attributes": [
- ],
- "name": "Rubrik",
- "ask_for_email": false,
- "id": "Elements::Category"
- }
- ],
- "writable": true
- },
- {
- "type": "List",
- "sort_keys": {
- "options": [
- {
- "name": "Standardsortierung",
- "id": null
- }
- ]
- },
- "uri": "http:\/\/localhost:3000\/lists\/Lists::ArticlesList\/elements.json",
- "sort_key_uri": "http:\/\/localhost:3000\/lists\/Lists::ArticlesList\/sort_key",
- "name": "Artikel",
- "readable": true,
- "id": "Lists::ArticlesList",
- "element_types": [
- {
- "create_element_url": "http:\/\/localhost:3000\/elements?list=Lists%3A%3AArticlesList&type=Elements%3A%3AArticle",
- "essential_attributes": [
- ],
- "name": "Artikel",
- "ask_for_email": false,
- "id": "Elements::Article"
- }
- ],
- "writable": true
- },
- {
- "type": "List",
- "sort_keys": {
- "options": [
- {
- "name": "Standardsortierung",
- "id": null
- },
- {
- "name": "Bestelldatum",
- "id": "Date"
- },
- {
- "name": "bestellt von",
- "id": "OrderedBy"
- },
- {
- "name": "Summe",
- "id": "Total"
- }
- ]
- },
- "uri": "http:\/\/localhost:3000\/lists\/Lists::Orders\/elements.json",
- "sort_key_uri": "http:\/\/localhost:3000\/lists\/Lists::Orders\/sort_key",
- "name": "Bestellungen",
- "readable": true,
- "id": "Lists::Orders",
- "element_types": [
- {
- "create_element_url": "http:\/\/localhost:3000\/elements?list=Lists%3A%3AOrders&type=Elements%3A%3AOrder",
- "essential_attributes": [
- ],
- "name": "Bestellung",
- "ask_for_email": false,
- "id": "Elements::Order"
- }
- ],
- "writable": true
- }
- ],
- "release_export_lock_url": "http:\/\/localhost:3000\/neighbourhoods\/Neighbourhoods::Storage\/release_export_lock",
- "readable": true,
- "replay_latest_snapshot_url": "http:\/\/localhost:3000\/snapshots\/replay_latest",
- "id": "Neighbourhoods::Storage",
- "writable": true
- },
- {
- "import_url": "http:\/\/localhost:3000\/neighbourhoods\/Neighbourhoods::Administration\/import",
- "type": "Neighbourhood",
- "reflected": true,
- "selected": false,
- "export_url": "http:\/\/localhost:3000\/neighbourhoods\/Neighbourhoods::Administration\/export",
- "snapshots_url": "http:\/\/localhost:3000\/snapshots",
- "uri": "http:\/\/localhost:3000\/neighbourhoods\/Neighbourhoods::Administration\/lists",
- "print_url": "http:\/\/localhost:3000\/neighbourhoods\/Neighbourhoods::Administration\/print",
- "locked": false,
- "name": "Verwaltung",
- "lists": [
- {
- "type": "List",
- "sort_keys": {
- "options": [
- {
- "name": "Standardsortierung",
- "id": null
- }
- ]
- },
- "uri": "http:\/\/localhost:3000\/lists\/Lists::Employees\/elements.json",
- "sort_key_uri": "http:\/\/localhost:3000\/lists\/Lists::Employees\/sort_key",
- "name": "Mitarbeiter",
- "readable": true,
- "id": "Lists::Employees",
- "element_types": [
- {
- "create_element_url": "http:\/\/localhost:3000\/elements?list=Lists%3A%3AEmployees&type=Elements%3A%3APerson",
- "essential_attributes": [
- ],
- "name": "Person",
- "ask_for_email": true,
- "id": "Elements::Person"
- }
- ],
- "writable": true
- },
- {
- "type": "List",
- "sort_keys": {
- "options": [
- {
- "name": "Standardsortierung",
- "id": null
- }
- ]
- },
- "uri": "http:\/\/localhost:3000\/lists\/Lists::Departments\/elements.json",
- "sort_key_uri": "http:\/\/localhost:3000\/lists\/Lists::Departments\/sort_key",
- "name": "Abteilungen",
- "readable": true,
- "id": "Lists::Departments",
- "element_types": [
- {
- "create_element_url": "http:\/\/localhost:3000\/elements?list=Lists%3A%3ADepartments&type=Elements%3A%3ADepartment",
- "essential_attributes": [
- ],
- "name": "Abteilung",
- "ask_for_email": false,
- "id": "Elements::Department"
- }
- ],
- "writable": true
- },
- {
- "type": "List",
- "sort_keys": {
- "options": [
- {
- "name": "Standardsortierung",
- "id": null
- }
- ]
- },
- "uri": "http:\/\/localhost:3000\/lists\/Lists::Locations\/elements.json",
- "sort_key_uri": "http:\/\/localhost:3000\/lists\/Lists::Locations\/sort_key",
- "name": "Standorte",
- "readable": true,
- "id": "Lists::Locations",
- "element_types": [
- {
- "create_element_url": "http:\/\/localhost:3000\/elements?list=Lists%3A%3ALocations&type=Elements%3A%3ALocation",
- "essential_attributes": [
- ],
- "name": "Standort",
- "ask_for_email": false,
- "id": "Elements::Location"
- }
- ],
- "writable": true
- },
- {
- "type": "List",
- "sort_keys": {
- "options": [
- {
- "name": "Standardsortierung",
- "id": null
- }
- ]
- },
- "uri": "http:\/\/localhost:3000\/lists\/Lists::Stocktakings\/elements.json",
- "sort_key_uri": "http:\/\/localhost:3000\/lists\/Lists::Stocktakings\/sort_key",
- "name": "Inventuren",
- "readable": true,
- "id": "Lists::Stocktakings",
- "element_types": [
- {
- "create_element_url": "http:\/\/localhost:3000\/elements?list=Lists%3A%3AStocktakings&type=Elements%3A%3AStocktaking",
- "essential_attributes": [
- ],
- "name": "Inventur",
- "ask_for_email": false,
- "id": "Elements::Stocktaking"
- }
- ],
- "writable": true
- },
- {
- "type": "List",
- "sort_keys": {
- "options": [
- {
- "name": "Standardsortierung",
- "id": null
- }
- ]
- },
- "uri": "http:\/\/localhost:3000\/lists\/Lists::Invoices\/elements.json",
- "sort_key_uri": "http:\/\/localhost:3000\/lists\/Lists::Invoices\/sort_key",
- "name": "Abrechnungen",
- "readable": true,
- "id": "Lists::Invoices",
- "element_types": [
- {
- "create_element_url": "http:\/\/localhost:3000\/elements?list=Lists%3A%3AInvoices&type=Elements%3A%3AInvoice",
- "essential_attributes": [
- ],
- "name": "Abrechnung",
- "ask_for_email": false,
- "id": "Elements::Invoice"
- }
- ],
- "writable": true
- }
- ],
- "release_export_lock_url": "http:\/\/localhost:3000\/neighbourhoods\/Neighbourhoods::Administration\/release_export_lock",
- "readable": true,
- "replay_latest_snapshot_url": "http:\/\/localhost:3000\/snapshots\/replay_latest",
- "id": "Neighbourhoods::Administration",
- "writable": true
- }
-]{
- "url": "http:\/\/localhost:3000\/elements\/633\/attributes",
- "name": "Bestellung: 3 <strong>Clovis Schwenger<\/strong> (\u20ac 12.10, 2008-10-08)",
- "attributes": [
- {
- "color": "red",
- "type": "state",
- "uri": "http:\/\/localhost:3000\/elements\/633\/state",
- "options": [
- {
- "color": "red",
- "name": "neu",
- "id": "new"
- },
- {
- "color": "orange",
- "name": "abgeschlossen",
- "id": "closed"
- },
- {
- "color": "green",
- "name": "freigegeben",
- "id": "approved"
- },
- {
- "color": "",
- "name": "verschickt",
- "id": "shipped"
- }
- ],
- "name": "Zustand",
- "value": "new",
- "readable": true,
- "journals": [
- {
- "user": "CS",
- "timestamp": "17:05 10\/07\/08",
- "created": true
- }
- ],
- "writable": false
- },
- {
- "type": "boolean",
- "mandatory": false,
- "confirm": true,
- "uri": "http:\/\/localhost:3000\/attributes\/5217",
- "value": false,
- "name": "abgeschlossen",
- "readable": true,
- "id": 5217,
- "writable": true
- },
- {
- "type": "boolean",
- "mandatory": false,
- "confirm": true,
- "uri": "http:\/\/localhost:3000\/attributes\/5218",
- "value": false,
- "name": "freigegeben",
- "readable": true,
- "id": 5218,
- "writable": false
- },
- {
- "type": "boolean",
- "mandatory": false,
- "confirm": true,
- "uri": "http:\/\/localhost:3000\/attributes\/5219",
- "value": false,
- "name": "verschickt",
- "readable": true,
- "id": 5219,
- "writable": false
- },
- {
- "type": "date",
- "mandatory": true,
- "confirm": false,
- "uri": "http:\/\/localhost:3000\/attributes\/5220",
- "value": "2008-10-08",
- "name": "Bestelldatum",
- "readable": true,
- "id": 5220,
- "writable": false
- },
- {
- "type": "references",
- "create_options": [
- {
- "create_element_url": "http:\/\/localhost:3000\/elements?list=Lists%3A%3AEmployees&source_id=5221&type=Elements%3A%3APerson",
- "essential_attributes": [
- ],
- "names": {
- "type": "Person",
- "list": "Mitarbeiter"
- },
- "ask_for_email": true
- }
- ],
- "maximum_reached": true,
- "constraints": {
- "neighbourhood": null,
- "attribute": null,
- "maximum": 1,
- "element": [
- "Elements::Person"
- ],
- "list": null,
- "follow": null
- },
- "essential_attributes": [
- ],
- "mandatory": false,
- "confirm": false,
- "uri": "http:\/\/localhost:3000\/attributes\/5221",
- "value": {
- "elements": [
- {
- "color": null,
- "type": "Elements::Person",
- "has_predecessors": false,
- "successors": "http:\/\/localhost:3000\/elements\/582\/successors",
- "uri": "http:\/\/localhost:3000\/elements\/582",
- "name": "Clovis Schwenger",
- "attributes": "http:\/\/localhost:3000\/elements\/582\/attributes",
- "link_url": "http:\/\/localhost:3000\/inbound_references\/457",
- "state": null,
- "readable": true,
- "list": "Lists::Employees",
- "id": 582,
- "writable": true,
- "family": "http:\/\/localhost:3000\/elements\/582\/family"
- }
- ]
- },
- "name": "bestellt von",
- "candidates_uri": "http:\/\/localhost:3000\/attributes\/5221\/candidates",
- "create_reference_uri": "http:\/\/localhost:3000\/inbound_references",
- "readable": true,
- "id": 5221,
- "writable": false
- },
- {
- "type": "text",
- "mandatory": false,
- "confirm": false,
- "uri": "http:\/\/localhost:3000\/attributes\/5222",
- "value": {
- "language": null,
- "version": 0,
- "text": ""
- },
- "name": "Verwendungszweck",
- "multiline": true,
- "readable": true,
- "id": 5222,
- "languages": [
- ],
- "writable": true
- },
- {
- "type": "references",
- "create_options": [
- ],
- "maximum_reached": null,
- "constraints": {
- "neighbourhood": null,
- "attribute": null,
- "maximum": null,
- "element": [
- "Elements::Merchandise"
- ],
- "list": null,
- "follow": "Article"
- },
- "essential_attributes": [
- {
- "name": "Menge",
- "default": 1,
- "id": "Amount"
- }
- ],
- "mandatory": true,
- "confirm": false,
- "uri": "http:\/\/localhost:3000\/attributes\/5223",
- "value": {
- "elements": [
- {
- "color": null,
- "type": "Elements::Merchandise",
- "has_predecessors": true,
- "successors": "http:\/\/localhost:3000\/elements\/627\/successors",
- "uri": "http:\/\/localhost:3000\/elements\/627",
- "name": "8 x <div class=\"thumbnail\"><img src=\"http:\/\/localhost:3000\/files\/875\/thumbnail?attribute_id=5001\" \/><\/div>#005 Stressball",
- "attributes": "http:\/\/localhost:3000\/elements\/627\/attributes",
- "link_url": "http:\/\/localhost:3000\/inbound_references\/458",
- "state": null,
- "readable": true,
- "list": "Lists::OrderItems",
- "id": 627,
- "writable": true,
- "family": "http:\/\/localhost:3000\/elements\/627\/family"
- },
- {
- "color": null,
- "type": "Elements::Merchandise",
- "has_predecessors": true,
- "successors": "http:\/\/localhost:3000\/elements\/628\/successors",
- "uri": "http:\/\/localhost:3000\/elements\/628",
- "name": "3 x <div class=\"thumbnail\"><img src=\"http:\/\/localhost:3000\/files\/881\/thumbnail?attribute_id=5091\" \/><\/div>#011 Post-It Block",
- "attributes": "http:\/\/localhost:3000\/elements\/628\/attributes",
- "link_url": "http:\/\/localhost:3000\/inbound_references\/459",
- "state": null,
- "readable": true,
- "list": "Lists::OrderItems",
- "id": 628,
- "writable": true,
- "family": "http:\/\/localhost:3000\/elements\/628\/family"
- }
- ]
- },
- "name": "Bestellpositionen",
- "candidates_uri": "http:\/\/localhost:3000\/attributes\/5223\/candidates",
- "create_reference_uri": "http:\/\/localhost:3000\/inbound_references",
- "readable": true,
- "id": 5223,
- "writable": true
- },
- {
- "type": "float",
- "mandatory": false,
- "confirm": false,
- "uri": "http:\/\/localhost:3000\/attributes\/5224",
- "value": "12,10",
- "name": "Summe",
- "readable": true,
- "id": 5224,
- "writable": false
- },
- {
- "type": "document",
- "files": [
- ],
- "mandatory": false,
- "confirm": false,
- "uri": "http:\/\/localhost:3000\/attributes\/5225",
- "name": "Bestellschein",
- "readable": true,
- "id": 5225,
- "writable": false
- },
- {
- "type": "document",
- "files": [
- ],
- "mandatory": false,
- "confirm": false,
- "uri": "http:\/\/localhost:3000\/attributes\/5226",
- "name": "Empf\u00e4ngernachweis",
- "readable": true,
- "id": 5226,
- "writable": false
- }
- ],
- "writable": true
-}[
- {
- "precision": "zip",
- "Latitude": 37.7668,
- "Longitude": -122.3959,
- "Address": "",
- "City": "SAN FRANCISCO",
- "State": "CA",
- "Zip": "94107",
- "Country": "US"
- },
- {
- "precision": "zip",
- "Latitude": 37.371991,
- "Longitude": -122.026020,
- "Address": "",
- "City": "SUNNYVALE",
- "State": "CA",
- "Zip": "94085",
- "Country": "US"
- }
-]
-[
- "JSON Test Pattern pass1",
- {"object with 1 member":["array with 1 element"]},
- {},
- [],
- -42,
- true,
- false,
- null,
- {
- "integer": 1234567890,
- "real": -9876.543210,
- "e": 0.123456789e-12,
- "E": 1.234567890E+34,
- "": 23456789012E666,
- "zero": 0,
- "one": 1,
- "space": " ",
- "quote": "\"",
- "backslash": "\\",
- "controls": "\b\f\n\r\t",
- "slash": "/ & \/",
- "alpha": "abcdefghijklmnopqrstuvwyz",
- "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
- "digit": "0123456789",
- "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
- "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
- "true": true,
- "false": false,
- "null": null,
- "array":[ ],
- "object":{ },
- "address": "50 St. James Street",
- "url": "http://www.JSON.org/",
- "comment": "// /* <!-- --",
- "# -- --> */": " ",
- " s p a c e d " :[1,2 , 3
-
-,
-
-4 , 5 , 6 ,7 ],
- "compact": [1,2,3,4,5,6,7],
- "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
- "quotes": "&#34; \u0022 %22 0x22 034 &#x22;",
- "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
-: "A key can be any string"
- },
- 0.5 ,98.6
-,
-99.44
-,
-
-1066
-
-
-,"rosebud"]
-
-["Illegal backslash escape: \x15"]
-
-["Illegal backslash escape: \'"]
-
-["Illegal backslash escape: \017"]
-
-[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
-
-["tab\ character\ in\ string\ "]
-
-{
- "JSON Test Pattern pass3": {
- "The outermost value": "must be an object or array.",
- "In this test": "It is an object."
- }
-}
diff --git a/bench/example.plain b/bench/example.plain
deleted file mode 100644
index 9e9aefc..0000000
--- a/bench/example.plain
+++ /dev/null
@@ -1,201 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "codegen.h"
-#include "symboltable.h"
-#include "stringbuffer.h"
-
-extern void yyerror(char* msg);
-
-static stringBuffer* staticVariableBuffer;
-static stringBuffer* classInitBuffer;
-static stringBuffer* currentMethodBuffer;
-static stringBuffer* finishedMethodsBuffer;
-static stringBuffer* mainBuffer;
-
-static int currentMethodBufferIndex;
-static int currentMethodStackSize;
-static int currentMethodStackSizeMax;
-static int currentMethodNumberOfLocals;
-
-static int classInitBufferIndex;
-static int classInitStackSize;
-static int classInitStackSizeMax;
-
-static int labelCounter = 0;
-static int global = 1;
-
-char tempString[MAX_LENGTH_OF_COMMAND];
-
-extern char* className; /* from minako-syntax.y */
-
-/* forward declarations */
-static void increaseStackby(int stackdiff);
-char convertType(int type);
-
-void codegenInit() {
- staticVariableBuffer = newStringBuffer();
- classInitBuffer = newStringBuffer();
- currentMethodBuffer = 0;
- finishedMethodsBuffer = newStringBuffer();
- mainBuffer = newStringBuffer();
-
- stringBufferAppend(mainBuffer, "; ------- Header --------------------------------------------");
- sprintf(tempString, ".class public synchronized %s", className);
- stringBufferAppend(mainBuffer, tempString);
- stringBufferAppend(mainBuffer, ".super java/lang/Object");
- stringBufferAppend(mainBuffer, "; -----------------------------------------------------------");
- stringBufferAppend(mainBuffer, "");
-
- stringBufferAppend(finishedMethodsBuffer, "; ------- Constructor ---------------------------------------");
- stringBufferAppend(finishedMethodsBuffer, ".method public <init>()V");
- stringBufferAppend(finishedMethodsBuffer, "\t.limit stack 1");
- stringBufferAppend(finishedMethodsBuffer, "\t.limit locals 1");
- stringBufferAppend(finishedMethodsBuffer, "\taload_0");
- stringBufferAppend(finishedMethodsBuffer, "\tinvokenonvirtual java/lang/Object/<init>()V");
- stringBufferAppend(finishedMethodsBuffer, "\treturn");
- stringBufferAppend(finishedMethodsBuffer, ".end method");
- stringBufferAppend(finishedMethodsBuffer, "; -----------------------------------------------------------");
- stringBufferAppend(finishedMethodsBuffer, "");
-
- stringBufferAppend(staticVariableBuffer, "; ------- Class Variables -----------------------------------");
-
- stringBufferAppend(classInitBuffer, "; ------- Class Initializer ---------------------------------");
- stringBufferAppend(classInitBuffer, ".method static <clinit>()V");
- classInitBufferIndex = classInitBuffer->numberOfNextElement;
- stringBufferAppend(classInitBuffer, "\t.limit locals 0");
-
-}
-
-void codegenAppendCommand(char* cmd, int stackdiff) {
- char tempString[MAX_LENGTH_OF_COMMAND];
- sprintf(tempString, "\t%s", cmd);
- if (global) stringBufferAppend(classInitBuffer, tempString);
- else stringBufferAppend(currentMethodBuffer, tempString);
- increaseStackby(stackdiff);
-}
-
-void codegenInsertCommand(int address, char* cmd, int stackdiff) {
- char tempString[MAX_LENGTH_OF_COMMAND];
- sprintf(tempString, "\t%s", cmd);
- if (global) stringBufferInsert(classInitBuffer, address, tempString);
- else stringBufferInsert(currentMethodBuffer, address, tempString);
- increaseStackby(stackdiff);
-}
-
-void codegenAppendLabel(int label) {
- char tempString[MAX_LENGTH_OF_COMMAND];
- sprintf(tempString, "Label%d:", label);
- if (global) stringBufferAppend(classInitBuffer, tempString);
- else stringBufferAppend(currentMethodBuffer, tempString);
-}
-
-void codegenAddVariable(char* name, int type) {
- /*fprintf(stderr, "add variable %s(%d) global=%d ", name, convertType(type), global);*/
- if (global) {
- if (type == TYPE_INT) sprintf(tempString, ".field static %s %c", name, 'I');
- else if (type == TYPE_FLOAT) sprintf(tempString, ".field static %s %c", name, 'F');
- else if (type == TYPE_BOOLEAN) sprintf(tempString, ".field static %s %c", name, 'Z');
- else yyerror("compiler-intern error in codegenAddGlobalVariable().\n");
- stringBufferAppend(staticVariableBuffer, tempString);
- }
- else {
- currentMethodNumberOfLocals++;
- }
-}
-
-int codegenGetNextLabel() {
- return labelCounter++;
-}
-
-int codegenGetCurrentAddress() {
- if (global) return classInitBuffer->numberOfNextElement;
- else return currentMethodBuffer->numberOfNextElement;
-}
-
-void codegenEnterFunction(symtabEntry* entry) {
- currentMethodBuffer = newStringBuffer();
- currentMethodStackSize = 0;
- currentMethodStackSizeMax = 0;
- labelCounter = 1;
- global = 0;
-
- if (strcmp(entry->name, "main") == 0) {
- if (entry->idtype != TYPE_VOID) yyerror("main has to be void.\n");
- currentMethodNumberOfLocals = 1;
- symtabInsert(strdup("#main-param#"), TYPE_VOID, CLASS_FUNC);
- stringBufferAppend(currentMethodBuffer, "; ------- Methode ---- void main() --------------------------");
- stringBufferAppend(currentMethodBuffer, ".method public static main([Ljava/lang/String;)V");
- }
- else {
- int i;
- currentMethodNumberOfLocals = entry->paramIndex;
- stringBufferAppend(currentMethodBuffer, "; ------- Methode -------------------------------------------");
- sprintf(tempString, ".method public static %s(", entry->name);
- for (i=entry->paramIndex-1; i>=0; i--) {
- int type = entry->params[i]->idtype;
- tempString[strlen(tempString)+1] = 0;
- tempString[strlen(tempString)] = convertType(type);
- }
- tempString[strlen(tempString)+2] = 0;
- tempString[strlen(tempString)+1] = convertType(entry->idtype);
- tempString[strlen(tempString)] = ')';
- stringBufferAppend(currentMethodBuffer, tempString);
- }
- currentMethodBufferIndex = currentMethodBuffer->numberOfNextElement;
-}
-
-void codegenLeaveFunction() {
- global = 1;
- sprintf(tempString, "\t.limit locals %d", currentMethodNumberOfLocals);
- stringBufferInsert(currentMethodBuffer, currentMethodBufferIndex, tempString);
- sprintf(tempString, "\t.limit stack %d", currentMethodStackSizeMax);
- stringBufferInsert(currentMethodBuffer, currentMethodBufferIndex, tempString);
- stringBufferAppend(currentMethodBuffer, "\treturn");
- stringBufferAppend(currentMethodBuffer, ".end method");
- stringBufferAppend(currentMethodBuffer, "; -----------------------------------------------------------");
- stringBufferAppend(currentMethodBuffer, "");
-
- stringBufferConcatenate(finishedMethodsBuffer, currentMethodBuffer);
-}
-
-
-
-void codegenFinishCode() {
- stringBufferAppend(staticVariableBuffer, "; -----------------------------------------------------------");
- stringBufferAppend(staticVariableBuffer, "");
-
- sprintf(tempString, "\t.limit stack %d", classInitStackSizeMax);
- stringBufferInsert(classInitBuffer, classInitBufferIndex, tempString);
- stringBufferAppend(classInitBuffer, "\treturn");
- stringBufferAppend(classInitBuffer, ".end method");
- stringBufferAppend(classInitBuffer, "; -----------------------------------------------------------");
-
- stringBufferConcatenate(mainBuffer, staticVariableBuffer);
- stringBufferConcatenate(mainBuffer, finishedMethodsBuffer);
- stringBufferConcatenate(mainBuffer, classInitBuffer);
-
- stringBufferPrint(mainBuffer);
-}
-
-static void increaseStackby(int stackdiff) {
- if (global) {
- classInitStackSize += stackdiff;
- if (classInitStackSize > classInitStackSizeMax) classInitStackSizeMax = classInitStackSize;
- }
- else {
- currentMethodStackSize += stackdiff;
- if (currentMethodStackSize > currentMethodStackSizeMax) currentMethodStackSizeMax = currentMethodStackSize;
- }
-}
-
-char convertType(int type) {
- switch(type) {
- case TYPE_VOID: return 'V';
- case TYPE_INT: return 'I';
- case TYPE_FLOAT: return 'F';
- case TYPE_BOOLEAN: return 'Z';
- default: yyerror("compiler-intern error in convertType().\n");
- }
- return 0; /* to avoid compiler-warning */
-}
diff --git a/bench/example.rb b/bench/example.rb
deleted file mode 100644
index c89d3ab..0000000
--- a/bench/example.rb
+++ /dev/null
@@ -1,10070 +0,0 @@
-module CodeRay
- module Scanners
-
-class Ruby < Scanner
-
- RESERVED_WORDS = [
- 'and', 'def', 'end', 'in', 'or', 'unless', 'begin',
- 'defined?', 'ensure', 'module', 'redo', 'super', 'until',
- 'BEGIN', 'break', 'do', 'next', 'rescue', 'then',
- 'when', 'END', 'case', 'else', 'for', 'retry',
- 'while', 'alias', 'class', 'elsif', 'if', 'not', 'return',
- 'undef', 'yield',
- ]
-
- DEF_KEYWORDS = ['def']
- MODULE_KEYWORDS = ['class', 'module']
- DEF_NEW_STATE = WordList.new(:initial).
- add(DEF_KEYWORDS, :def_expected).
- add(MODULE_KEYWORDS, :module_expected)
-
- WORDS_ALLOWING_REGEXP = [
- 'and', 'or', 'not', 'while', 'until', 'unless', 'if', 'elsif', 'when'
- ]
- REGEXP_ALLOWED = WordList.new(false).
- add(WORDS_ALLOWING_REGEXP, :set)
-
- PREDEFINED_CONSTANTS = [
- 'nil', 'true', 'false', 'self',
- 'DATA', 'ARGV', 'ARGF', '__FILE__', '__LINE__',
- ]
-
- IDENT_KIND = WordList.new(:ident).
- add(RESERVED_WORDS, :reserved).
- add(PREDEFINED_CONSTANTS, :pre_constant)
-
- METHOD_NAME = / #{IDENT} [?!]? /xo
- METHOD_NAME_EX = /
- #{METHOD_NAME} # common methods: split, foo=, empty?, gsub!
- | \*\*? # multiplication and power
- | [-+~]@? # plus, minus
- | [\/%&|^`] # division, modulo or format strings, &and, |or, ^xor, `system`
- | \[\]=? # array getter and setter
- | <=?>? | >=? # comparison, rocket operator
- | << | >> # append or shift left, shift right
- | ===? # simple equality and case equality
- /ox
- GLOBAL_VARIABLE = / \$ (?: #{IDENT} | \d+ | [~&+`'=\/,;_.<>!@0$?*":F\\] | -[a-zA-Z_0-9] ) /ox
-
- DOUBLEQ = / " [^"\#\\]* (?: (?: \#\{.*?\} | \#(?:$")? | \\. ) [^"\#\\]* )* "? /ox
- SINGLEQ = / ' [^'\\]* (?: \\. [^'\\]* )* '? /ox
- STRING = / #{SINGLEQ} | #{DOUBLEQ} /ox
- SHELL = / ` [^`\#\\]* (?: (?: \#\{.*?\} | \#(?:$`)? | \\. ) [^`\#\\]* )* `? /ox
- REGEXP = / \/ [^\/\#\\]* (?: (?: \#\{.*?\} | \#(?:$\/)? | \\. ) [^\/\#\\]* )* \/? /ox
-
- DECIMAL = /\d+(?:_\d+)*/ # doesn't recognize 09 as octal error
- OCTAL = /0_?[0-7]+(?:_[0-7]+)*/
- HEXADECIMAL = /0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*/
- BINARY = /0b[01]+(?:_[01]+)*/
-
- EXPONENT = / [eE] [+-]? #{DECIMAL} /ox
- FLOAT = / #{DECIMAL} (?: #{EXPONENT} | \. #{DECIMAL} #{EXPONENT}? ) /
- INTEGER = /#{OCTAL}|#{HEXADECIMAL}|#{BINARY}|#{DECIMAL}/
-
- def reset
- super
- @regexp_allowed = false
- end
-
- def next_token
- return if @scanner.eos?
-
- kind = :error
- if @scanner.scan(/\s+/) # in every state
- kind = :space
- @regexp_allowed = :set if @regexp_allowed or @scanner.matched.index(?\n) # delayed flag setting
-
- elsif @state == :def_expected
- if @scanner.scan(/ (?: (?:#{IDENT}(?:\.|::))* | (?:@@?|$)? #{IDENT}(?:\.|::) ) #{METHOD_NAME_EX} /ox)
- kind = :method
- @state = :initial
- else
- @scanner.getch
- end
- @state = :initial
-
- elsif @state == :module_expected
- if @scanner.scan(/<</)
- kind = :operator
- else
- if @scanner.scan(/ (?: #{IDENT} (?:\.|::))* #{IDENT} /ox)
- kind = :method
- else
- @scanner.getch
- end
- @state = :initial
- end
-
- elsif # state == :initial
- # IDENTIFIERS, KEYWORDS
- if @scanner.scan(GLOBAL_VARIABLE)
- kind = :global_variable
- elsif @scanner.scan(/ @@ #{IDENT} /ox)
- kind = :class_variable
- elsif @scanner.scan(/ @ #{IDENT} /ox)
- kind = :instance_variable
- elsif @scanner.scan(/ __END__\n ( (?!\#CODE\#) .* )? | \#[^\n]* | =begin(?=\s).*? \n=end(?=\s|\z)(?:[^\n]*)? /mx)
- kind = :comment
- elsif @scanner.scan(METHOD_NAME)
- if @last_token_dot
- kind = :ident
- else
- matched = @scanner.matched
- kind = IDENT_KIND[matched]
- if kind == :ident and matched =~ /^[A-Z]/
- kind = :constant
- elsif kind == :reserved
- @state = DEF_NEW_STATE[matched]
- @regexp_allowed = REGEXP_ALLOWED[matched]
- end
- end
-
- elsif @scanner.scan(STRING)
- kind = :string
- elsif @scanner.scan(SHELL)
- kind = :shell
- elsif @scanner.scan(/<<
- (?:
- ([a-zA-Z_0-9]+)
- (?: .*? ^\1$ | .* )
- |
- -([a-zA-Z_0-9]+)
- (?: .*? ^\s*\2$ | .* )
- |
- (["\'`]) (.+?) \3
- (?: .*? ^\4$ | .* )
- |
- - (["\'`]) (.+?) \5
- (?: .*? ^\s*\6$ | .* )
- )
- /mxo)
- kind = :string
- elsif @scanner.scan(/\//) and @regexp_allowed
- @scanner.unscan
- @scanner.scan(REGEXP)
- kind = :regexp
-/%(?:[Qqxrw](?:\([^)#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^)#\\\\]*)*\)?|\[[^\]#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^\]#\\\\]*)*\]?|\{[^}#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^}#\\\\]*)*\}?|<[^>#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^>#\\\\]*)*>?|([^a-zA-Z\\\\])(?:(?!\1)[^#\\\\])*(?:(?:#\{.*?\}|#|\\\\.)(?:(?!\1)[^#\\\\])*)*\1?)|\([^)#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^)#\\\\]*)*\)?|\[[^\]#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^\]#\\\\]*)*\]?|\{[^}#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^}#\\\\]*)*\}?|<[^>#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^>#\\\\]*)*>?|([^a-zA-Z\s\\\\])(?:(?!\2)[^#\\\\])*(?:(?:#\{.*?\}|#|\\\\.)(?:(?!\2)[^#\\\\])*)*\2?|\\\\[^#\\\\]*(?:(?:#\{.*?\}|#)[^#\\\\]*)*\\\\?)/
- elsif @scanner.scan(/:(?:#{GLOBAL_VARIABLE}|#{METHOD_NAME_EX}|#{STRING})/ox)
- kind = :symbol
- elsif @scanner.scan(/
- \? (?:
- [^\s\\]
- |
- \\ (?:M-\\C-|C-\\M-|M-\\c|c\\M-|c|C-|M-))? (?: \\ (?: . | [0-7]{3} | x[0-9A-Fa-f][0-9A-Fa-f] )
- )
- /mox)
- kind = :integer
-
- elsif @scanner.scan(/ [-+*\/%=<>;,|&!()\[\]{}~?] | \.\.?\.? | ::? /x)
- kind = :operator
- @regexp_allowed = :set if @scanner.matched[-1,1] =~ /[~=!<>|&^,\(\[+\-\/\*%]\z/
- elsif @scanner.scan(FLOAT)
- kind = :float
- elsif @scanner.scan(INTEGER)
- kind = :integer
- else
- @scanner.getch
- end
- end
-
- token = Token.new @scanner.matched, kind
-
- if kind == :regexp
- token.text << @scanner.scan(/[eimnosux]*/)
- end
-
- @regexp_allowed = (@regexp_allowed == :set) # delayed flag setting
-
- token
- end
-end
-
-register Ruby, 'ruby', 'rb'
-
- end
-end
-class Set
- include Enumerable
-
- # Creates a new set containing the given objects.
- def self.[](*ary)
- new(ary)
- end
-
- # Creates a new set containing the elements of the given enumerable
- # object.
- #
- # If a block is given, the elements of enum are preprocessed by the
- # given block.
- def initialize(enum = nil, &block) # :yields: o
- @hash ||= Hash.new
-
- enum.nil? and return
-
- if block
- enum.each { |o| add(block[o]) }
- else
- merge(enum)
- end
- end
-
- # Copy internal hash.
- def initialize_copy(orig)
- @hash = orig.instance_eval{@hash}.dup
- end
-
- # Returns the number of elements.
- def size
- @hash.size
- end
- alias length size
-
- # Returns true if the set contains no elements.
- def empty?
- @hash.empty?
- end
-
- # Removes all elements and returns self.
- def clear
- @hash.clear
- self
- end
-
- # Replaces the contents of the set with the contents of the given
- # enumerable object and returns self.
- def replace(enum)
- if enum.class == self.class
- @hash.replace(enum.instance_eval { @hash })
- else
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- clear
- enum.each { |o| add(o) }
- end
-
- self
- end
-
- # Converts the set to an array. The order of elements is uncertain.
- def to_a
- @hash.keys
- end
-
- def flatten_merge(set, seen = Set.new)
- set.each { |e|
- if e.is_a?(Set)
- if seen.include?(e_id = e.object_id)
- raise ArgumentError, "tried to flatten recursive Set"
- end
-
- seen.add(e_id)
- flatten_merge(e, seen)
- seen.delete(e_id)
- else
- add(e)
- end
- }
-
- self
- end
- protected :flatten_merge
-
- # Returns a new set that is a copy of the set, flattening each
- # containing set recursively.
- def flatten
- self.class.new.flatten_merge(self)
- end
-
- # Equivalent to Set#flatten, but replaces the receiver with the
- # result in place. Returns nil if no modifications were made.
- def flatten!
- if detect { |e| e.is_a?(Set) }
- replace(flatten())
- else
- nil
- end
- end
-
- # Returns true if the set contains the given object.
- def include?(o)
- @hash.include?(o)
- end
- alias member? include?
-
- # Returns true if the set is a superset of the given set.
- def superset?(set)
- set.is_a?(Set) or raise ArgumentError, "value must be a set"
- return false if size < set.size
- set.all? { |o| include?(o) }
- end
-
- # Returns true if the set is a proper superset of the given set.
- def proper_superset?(set)
- set.is_a?(Set) or raise ArgumentError, "value must be a set"
- return false if size <= set.size
- set.all? { |o| include?(o) }
- end
-
- # Returns true if the set is a subset of the given set.
- def subset?(set)
- set.is_a?(Set) or raise ArgumentError, "value must be a set"
- return false if set.size < size
- all? { |o| set.include?(o) }
- end
-
- # Returns true if the set is a proper subset of the given set.
- def proper_subset?(set)
- set.is_a?(Set) or raise ArgumentError, "value must be a set"
- return false if set.size <= size
- all? { |o| set.include?(o) }
- end
-
- # Calls the given block once for each element in the set, passing
- # the element as parameter.
- def each
- @hash.each_key { |o| yield(o) }
- self
- end
-
- # Adds the given object to the set and returns self. Use +merge+ to
- # add several elements at once.
- def add(o)
- @hash[o] = true
- self
- end
- alias << add
-
- # Adds the given object to the set and returns self. If the
- # object is already in the set, returns nil.
- def add?(o)
- if include?(o)
- nil
- else
- add(o)
- end
- end
-
- # Deletes the given object from the set and returns self. Use +subtract+ to
- # delete several items at once.
- def delete(o)
- @hash.delete(o)
- self
- end
-
- # Deletes the given object from the set and returns self. If the
- # object is not in the set, returns nil.
- def delete?(o)
- if include?(o)
- delete(o)
- else
- nil
- end
- end
-
- # Deletes every element of the set for which block evaluates to
- # true, and returns self.
- def delete_if
- @hash.delete_if { |o,| yield(o) }
- self
- end
-
- # Do collect() destructively.
- def collect!
- set = self.class.new
- each { |o| set << yield(o) }
- replace(set)
- end
- alias map! collect!
-
- # Equivalent to Set#delete_if, but returns nil if no changes were
- # made.
- def reject!
- n = size
- delete_if { |o| yield(o) }
- size == n ? nil : self
- end
-
- # Merges the elements of the given enumerable object to the set and
- # returns self.
- def merge(enum)
- if enum.is_a?(Set)
- @hash.update(enum.instance_eval { @hash })
- else
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- enum.each { |o| add(o) }
- end
-
- self
- end
-
- # Deletes every element that appears in the given enumerable object
- # and returns self.
- def subtract(enum)
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- enum.each { |o| delete(o) }
- self
- end
-
- # Returns a new set built by merging the set and the elements of the
- # given enumerable object.
- def |(enum)
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- dup.merge(enum)
- end
- alias + | ##
- alias union | ##
-
- # Returns a new set built by duplicating the set, removing every
- # element that appears in the given enumerable object.
- def -(enum)
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- dup.subtract(enum)
- end
- alias difference - ##
-
- # Returns a new array containing elements common to the set and the
- # given enumerable object.
- def &(enum)
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- n = self.class.new
- enum.each { |o| n.add(o) if include?(o) }
- n
- end
- alias intersection & ##
-
- # Returns a new array containing elements exclusive between the set
- # and the given enumerable object. (set ^ enum) is equivalent to
- # ((set | enum) - (set & enum)).
- def ^(enum)
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- n = dup
- enum.each { |o| if n.include?(o) then n.delete(o) else n.add(o) end }
- n
- end
-
- # Returns true if two sets are equal. The equality of each couple
- # of elements is defined according to Object#eql?.
- def ==(set)
- equal?(set) and return true
-
- set.is_a?(Set) && size == set.size or return false
-
- hash = @hash.dup
- set.all? { |o| hash.include?(o) }
- end
-
- def hash # :nodoc:
- @hash.hash
- end
-
- def eql?(o) # :nodoc:
- return false unless o.is_a?(Set)
- @hash.eql?(o.instance_eval{@hash})
- end
-
- # Classifies the set by the return value of the given block and
- # returns a hash of {value => set of elements} pairs. The block is
- # called once for each element of the set, passing the element as
- # parameter.
- #
- # e.g.:
- #
- # require 'set'
- # files = Set.new(Dir.glob("*.rb"))
- # hash = files.classify { |f| File.mtime(f).year }
- # p hash # => {2000=>#<Set: {"a.rb", "b.rb"}>,
- # # 2001=>#<Set: {"c.rb", "d.rb", "e.rb"}>,
- # # 2002=>#<Set: {"f.rb"}>}
- def classify # :yields: o
- h = {}
-
- each { |i|
- x = yield(i)
- (h[x] ||= self.class.new).add(i)
- }
-
- h
- end
-
- # Divides the set into a set of subsets according to the commonality
- # defined by the given block.
- #
- # If the arity of the block is 2, elements o1 and o2 are in common
- # if block.call(o1, o2) is true. Otherwise, elements o1 and o2 are
- # in common if block.call(o1) == block.call(o2).
- #
- # e.g.:
- #
- # require 'set'
- # numbers = Set[1, 3, 4, 6, 9, 10, 11]
- # set = numbers.divide { |i,j| (i - j).abs == 1 }
- # p set # => #<Set: {#<Set: {1}>,
- # # #<Set: {11, 9, 10}>,
- # # #<Set: {3, 4}>,
- # # #<Set: {6}>}>
- def divide(&func)
- if func.arity == 2
- require 'tsort'
-
- class << dig = {} # :nodoc:
- include TSort
-
- alias tsort_each_node each_key
- def tsort_each_child(node, &block)
- fetch(node).each(&block)
- end
- end
-
- each { |u|
- dig[u] = a = []
- each{ |v| func.call(u, v) and a << v }
- }
-
- set = Set.new()
- dig.each_strongly_connected_component { |css|
- set.add(self.class.new(css))
- }
- set
- else
- Set.new(classify(&func).values)
- end
- end
-
- InspectKey = :__inspect_key__ # :nodoc:
-
- # Returns a string containing a human-readable representation of the
- # set. ("#<Set: {element1, element2, ...}>")
- def inspect
- ids = (Thread.current[InspectKey] ||= [])
-
- if ids.include?(object_id)
- return sprintf('#<%s: {...}>', self.class.name)
- end
-
- begin
- ids << object_id
- return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2])
- ensure
- ids.pop
- end
- end
-
- def pretty_print(pp) # :nodoc:
- pp.text sprintf('#<%s: {', self.class.name)
- pp.nest(1) {
- pp.seplist(self) { |o|
- pp.pp o
- }
- }
- pp.text "}>"
- end
-
- def pretty_print_cycle(pp) # :nodoc:
- pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...')
- end
-end
-
-# SortedSet implements a set which elements are sorted in order. See Set.
-class SortedSet < Set
- @@setup = false
-
- class << self
- def [](*ary) # :nodoc:
- new(ary)
- end
-
- def setup # :nodoc:
- @@setup and return
-
- begin
- require 'rbtree'
-
- module_eval %{
- def initialize(*args, &block)
- @hash = RBTree.new
- super
- end
- }
- rescue LoadError
- module_eval %{
- def initialize(*args, &block)
- @keys = nil
- super
- end
-
- def clear
- @keys = nil
- super
- end
-
- def replace(enum)
- @keys = nil
- super
- end
-
- def add(o)
- @keys = nil
- @hash[o] = true
- self
- end
- alias << add
-
- def delete(o)
- @keys = nil
- @hash.delete(o)
- self
- end
-
- def delete_if
- n = @hash.size
- @hash.delete_if { |o,| yield(o) }
- @keys = nil if @hash.size != n
- self
- end
-
- def merge(enum)
- @keys = nil
- super
- end
-
- def each
- to_a.each { |o| yield(o) }
- end
-
- def to_a
- (@keys = @hash.keys).sort! unless @keys
- @keys
- end
- }
- end
-
- @@setup = true
- end
- end
-
- def initialize(*args, &block) # :nodoc:
- SortedSet.setup
- initialize(*args, &block)
- end
-end
-
-module Enumerable
- # Makes a set from the enumerable object with given arguments.
- def to_set(klass = Set, *args, &block)
- klass.new(self, *args, &block)
- end
-end
-
-# =begin
-# == RestricedSet class
-# RestricedSet implements a set with restrictions defined by a given
-# block.
-#
-# === Super class
-# Set
-#
-# === Class Methods
-# --- RestricedSet::new(enum = nil) { |o| ... }
-# --- RestricedSet::new(enum = nil) { |rset, o| ... }
-# Creates a new restricted set containing the elements of the given
-# enumerable object. Restrictions are defined by the given block.
-#
-# If the block's arity is 2, it is called with the RestrictedSet
-# itself and an object to see if the object is allowed to be put in
-# the set.
-#
-# Otherwise, the block is called with an object to see if the object
-# is allowed to be put in the set.
-#
-# === Instance Methods
-# --- restriction_proc
-# Returns the restriction procedure of the set.
-#
-# =end
-#
-# class RestricedSet < Set
-# def initialize(*args, &block)
-# @proc = block or raise ArgumentError, "missing a block"
-#
-# if @proc.arity == 2
-# instance_eval %{
-# def add(o)
-# @hash[o] = true if @proc.call(self, o)
-# self
-# end
-# alias << add
-#
-# def add?(o)
-# if include?(o) || !@proc.call(self, o)
-# nil
-# else
-# @hash[o] = true
-# self
-# end
-# end
-#
-# def replace(enum)
-# enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
-# clear
-# enum.each { |o| add(o) }
-#
-# self
-# end
-#
-# def merge(enum)
-# enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
-# enum.each { |o| add(o) }
-#
-# self
-# end
-# }
-# else
-# instance_eval %{
-# def add(o)
-# if @proc.call(o)
-# @hash[o] = true
-# end
-# self
-# end
-# alias << add
-#
-# def add?(o)
-# if include?(o) || !@proc.call(o)
-# nil
-# else
-# @hash[o] = true
-# self
-# end
-# end
-# }
-# end
-#
-# super(*args)
-# end
-#
-# def restriction_proc
-# @proc
-# end
-# end
-
-if $0 == __FILE__
- eval DATA.read, nil, $0, __LINE__+4
-end
-
-# = rweb - CGI Support Library
-#
-# Author:: Johannes Barre (mailto:rweb@igels.net)
-# Copyright:: Copyright (c) 2003, 04 by Johannes Barre
-# License:: GNU Lesser General Public License (COPYING, http://www.gnu.org/copyleft/lesser.html)
-# Version:: 0.1.0
-# CVS-ID:: $Id: rweb.rb 6 2004-06-16 15:56:26Z igel $
-#
-# == What is Rweb?
-# Rweb is a replacement for the cgi class included in the ruby distribution.
-#
-# == How to use
-#
-# === Basics
-#
-# This class is made to be as easy as possible to use. An example:
-#
-# require "rweb"
-#
-# web = Rweb.new
-# web.out do
-# web.puts "Hello world!"
-# end
-#
-# The visitor will get a simple "Hello World!" in his browser. Please notice,
-# that won't set html-tags for you, so you should better do something like this:
-#
-# require "rweb"
-#
-# web = Rweb.new
-# web.out do
-# web.puts "<html><body>Hello world!</body></html>"
-# end
-#
-# === Set headers
-# Of course, it's also possible to tell the browser, that the content of this
-# page is plain text instead of html code:
-#
-# require "rweb"
-#
-# web = Rweb.new
-# web.out do
-# web.header("content-type: text/plain")
-# web.puts "Hello plain world!"
-# end
-#
-# Please remember, headers can't be set after the page content has been send.
-# You have to set all nessessary headers before the first puts oder print. It's
-# possible to cache the content until everything is complete. Doing it this
-# way, you can set headers everywhere.
-#
-# If you set a header twice, the second header will replace the first one. The
-# header name is not casesensitive, it will allways converted in to the
-# capitalised form suggested by the w3c (http://w3.org)
-#
-# === Set cookies
-# Setting cookies is quite easy:
-# include 'rweb'
-#
-# web = Rweb.new
-# Cookie.new("Visits", web.cookies['visits'].to_i +1)
-# web.out do
-# web.puts "Welcome back! You visited this page #{web.cookies['visits'].to_i +1} times"
-# end
-#
-# See the class Cookie for more details.
-#
-# === Get form and cookie values
-# There are four ways to submit data from the browser to the server and your
-# ruby script: via GET, POST, cookies and file upload. Rweb doesn't support
-# file upload by now.
-#
-# include 'rweb'
-#
-# web = Rweb.new
-# web.out do
-# web.print "action: #{web.get['action']} "
-# web.puts "The value of the cookie 'visits' is #{web.cookies['visits']}"
-# web.puts "The post parameter 'test['x']' is #{web.post['test']['x']}"
-# end
-
-RWEB_VERSION = "0.1.0"
-RWEB = "rweb/#{RWEB_VERSION}"
-
-#require 'rwebcookie' -> edit by bunny :-)
-
-class Rweb
- # All parameter submitted via the GET method are available in attribute
- # get. This is Hash, where every parameter is available as a key-value
- # pair.
- #
- # If your input tag has a name like this one, it's value will be available
- # as web.get["fieldname"]
- # <input name="fieldname">
- # You can submit values as a Hash
- # <input name="text['index']">
- # <input name="text['index2']">
- # will be available as
- # web.get["text"]["index"]
- # web.get["text"]["index2"]
- # Integers are also possible
- # <input name="int[2]">
- # <input name="int[3]['hi']>
- # will be available as
- # web.get["int"][2]
- # web.get["int"][3]["hi"]
- # If you specify no index, the lowest unused index will be used:
- # <input name="int[]"><!-- First Field -->
- # <input name="int[]"><!-- Second one -->
- # will be available as
- # web.get["int"][0] # First Field
- # web.get["int"][1] # Second one
- # Please notice, this doesn'd work like you might expect:
- # <input name="text[index]">
- # It will not be available as web.get["text"]["index"] but
- # web.get["text[index]"]
- attr_reader :get
-
- # All parameters submitted via POST are available in the attribute post. It
- # works like the get attribute.
- # <input name="text[0]">
- # will be available as
- # web.post["text"][0]
- attr_reader :post
-
- # All cookies submitted by the browser are available in cookies. This is a
- # Hash, where every cookie is a key-value pair.
- attr_reader :cookies
-
- # The name of the browser identification is submitted as USER_AGENT and
- # available in this attribute.
- attr_reader :user_agent
-
- # The IP address of the client.
- attr_reader :remote_addr
-
- # Creates a new Rweb object. This should only done once. You can set various
- # options via the settings hash.
- #
- # "cache" => true: Everything you script send to the client will be cached
- # until the end of the out block or until flush is called. This way, you
- # can modify headers and cookies even after printing something to the client.
- #
- # "safe" => level: Changes the $SAFE attribute. By default, $SAFE will be set
- # to 1. If $SAFE is already higher than this value, it won't be changed.
- #
- # "silend" => true: Normaly, Rweb adds automaticly a header like this
- # "X-Powered-By: Rweb/x.x.x (Ruby/y.y.y)". With the silend option you can
- # suppress this.
- def initialize (settings = {})
- # {{{
- @header = {}
- @cookies = {}
- @get = {}
- @post = {}
-
- # Internal attributes
- @status = nil
- @reasonPhrase = nil
- @setcookies = []
- @output_started = false;
- @output_allowed = false;
-
- @mod_ruby = false
- @env = ENV.to_hash
-
- if defined?(MOD_RUBY)
- @output_method = "mod_ruby"
- @mod_ruby = true
- elsif @env['SERVER_SOFTWARE'] =~ /^Microsoft-IIS/i
- @output_method = "nph"
- else
- @output_method = "ph"
- end
-
- unless settings.is_a?(Hash)
- raise TypeError, "settings must be a Hash"
- end
- @settings = settings
-
- unless @settings.has_key?("safe")
- @settings["safe"] = 1
- end
-
- if $SAFE < @settings["safe"]
- $SAFE = @settings["safe"]
- end
-
- unless @settings.has_key?("cache")
- @settings["cache"] = false
- end
-
- # mod_ruby sets no QUERY_STRING variable, if no GET-Parameters are given
- unless @env.has_key?("QUERY_STRING")
- @env["QUERY_STRING"] = ""
- end
-
- # Now we split the QUERY_STRING by the seperators & and ; or, if
- # specified, settings['get seperator']
- unless @settings.has_key?("get seperator")
- get_args = @env['QUERY_STRING'].split(/[&;]/)
- else
- get_args = @env['QUERY_STRING'].split(@settings['get seperator'])
- end
-
- get_args.each do | arg |
- arg_key, arg_val = arg.split(/=/, 2)
- arg_key = Rweb::unescape(arg_key)
- arg_val = Rweb::unescape(arg_val)
-
- # Parse names like name[0], name['text'] or name[]
- pattern = /^(.+)\[("[^\]]*"|'[^\]]*'|[0-9]*)\]$/
- keys = []
- while match = pattern.match(arg_key)
- arg_key = match[1]
- keys = [match[2]] + keys
- end
- keys = [arg_key] + keys
-
- akt = @get
- last = nil
- lastkey = nil
- keys.each do |key|
- if key == ""
- # No key specified (like in "test[]"), so we use the
- # lowerst unused Integer as key
- key = 0
- while akt.has_key?(key)
- key += 1
- end
- elsif /^[0-9]*$/ =~ key
- # If the index is numerical convert it to an Integer
- key = key.to_i
- elsif key[0].chr == "'" || key[0].chr == '"'
- key = key[1, key.length() -2]
- end
- if !akt.has_key?(key) || !akt[key].class == Hash
- # create an empty Hash if there isn't already one
- akt[key] = {}
- end
- last = akt
- lastkey = key
- akt = akt[key]
- end
- last[lastkey] = arg_val
- end
-
- if @env['REQUEST_METHOD'] == "POST"
- if @env.has_key?("CONTENT_TYPE") && @env['CONTENT_TYPE'] == "application/x-www-form-urlencoded" && @env.has_key?('CONTENT_LENGTH')
- unless @settings.has_key?("post seperator")
- post_args = $stdin.read(@env['CONTENT_LENGTH'].to_i).split(/[&;]/)
- else
- post_args = $stdin.read(@env['CONTENT_LENGTH'].to_i).split(@settings['post seperator'])
- end
- post_args.each do | arg |
- arg_key, arg_val = arg.split(/=/, 2)
- arg_key = Rweb::unescape(arg_key)
- arg_val = Rweb::unescape(arg_val)
-
- # Parse names like name[0], name['text'] or name[]
- pattern = /^(.+)\[("[^\]]*"|'[^\]]*'|[0-9]*)\]$/
- keys = []
- while match = pattern.match(arg_key)
- arg_key = match[1]
- keys = [match[2]] + keys
- end
- keys = [arg_key] + keys
-
- akt = @post
- last = nil
- lastkey = nil
- keys.each do |key|
- if key == ""
- # No key specified (like in "test[]"), so we use
- # the lowerst unused Integer as key
- key = 0
- while akt.has_key?(key)
- key += 1
- end
- elsif /^[0-9]*$/ =~ key
- # If the index is numerical convert it to an Integer
- key = key.to_i
- elsif key[0].chr == "'" || key[0].chr == '"'
- key = key[1, key.length() -2]
- end
- if !akt.has_key?(key) || !akt[key].class == Hash
- # create an empty Hash if there isn't already one
- akt[key] = {}
- end
- last = akt
- lastkey = key
- akt = akt[key]
- end
- last[lastkey] = arg_val
- end
- else
- # Maybe we should print a warning here?
- $stderr.print("Unidentified form data recived and discarded.")
- end
- end
-
- if @env.has_key?("HTTP_COOKIE")
- cookie = @env['HTTP_COOKIE'].split(/; ?/)
- cookie.each do | c |
- cookie_key, cookie_val = c.split(/=/, 2)
-
- @cookies [Rweb::unescape(cookie_key)] = Rweb::unescape(cookie_val)
- end
- end
-
- if defined?(@env['HTTP_USER_AGENT'])
- @user_agent = @env['HTTP_USER_AGENT']
- else
- @user_agent = nil;
- end
-
- if defined?(@env['REMOTE_ADDR'])
- @remote_addr = @env['REMOTE_ADDR']
- else
- @remote_addr = nil
- end
- # }}}
- end
-
- # Prints a String to the client. If caching is enabled, the String will
- # buffered until the end of the out block ends.
- def print(str = "")
- # {{{
- unless @output_allowed
- raise "You just can write to output inside of a Rweb::out-block"
- end
-
- if @settings["cache"]
- @buffer += [str.to_s]
- else
- unless @output_started
- sendHeaders
- end
- $stdout.print(str)
- end
- nil
- # }}}
- end
-
- # Prints a String to the client and adds a line break at the end. Please
- # remember, that a line break is not visible in HTML, use the <br> HTML-Tag
- # for this. If caching is enabled, the String will buffered until the end
- # of the out block ends.
- def puts(str = "")
- # {{{
- self.print(str + "\n")
- # }}}
- end
-
- # Alias to print.
- def write(str = "")
- # {{{
- self.print(str)
- # }}}
- end
-
- # If caching is enabled, all cached data are send to the cliend and the
- # cache emptied.
- def flush
- # {{{
- unless @output_allowed
- raise "You can't use flush outside of a Rweb::out-block"
- end
- buffer = @buffer.join
-
- unless @output_started
- sendHeaders
- end
- $stdout.print(buffer)
-
- @buffer = []
- # }}}
- end
-
- # Sends one or more header to the client. All headers are cached just
- # before body data are send to the client. If the same header are set
- # twice, only the last value is send.
- #
- # Example:
- # web.header("Last-Modified: Mon, 16 Feb 2004 20:15:41 GMT")
- # web.header("Location: http://www.ruby-lang.org")
- #
- # You can specify more than one header at the time by doing something like
- # this:
- # web.header("Content-Type: text/plain\nContent-Length: 383")
- # or
- # web.header(["Content-Type: text/plain", "Content-Length: 383"])
- def header(str)
- # {{{
- if @output_started
- raise "HTTP-Headers are already send. You can't change them after output has started!"
- end
- unless @output_allowed
- raise "You just can set headers inside of a Rweb::out-block"
- end
- if str.is_a?Array
- str.each do | value |
- self.header(value)
- end
-
- elsif str.split(/\n/).length > 1
- str.split(/\n/).each do | value |
- self.header(value)
- end
-
- elsif str.is_a? String
- str.gsub!(/\r/, "")
-
- if (str =~ /^HTTP\/1\.[01] [0-9]{3} ?.*$/) == 0
- pattern = /^HTTP\/1.[01] ([0-9]{3}) ?(.*)$/
-
- result = pattern.match(str)
- self.setstatus(result[0], result[1])
- elsif (str =~ /^status: [0-9]{3} ?.*$/i) == 0
- pattern = /^status: ([0-9]{3}) ?(.*)$/i
-
- result = pattern.match(str)
- self.setstatus(result[0], result[1])
- else
- a = str.split(/: ?/, 2)
-
- @header[a[0].downcase] = a[1]
- end
- end
- # }}}
- end
-
- # Changes the status of this page. There are several codes like "200 OK",
- # "302 Found", "404 Not Found" or "500 Internal Server Error". A list of
- # all codes is available at
- # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10
- #
- # You can just send the code number, the reason phrase will be added
- # automaticly with the recommendations from the w3c if not specified. If
- # you set the status twice or more, only the last status will be send.
- # Examples:
- # web.status("401 Unauthorized")
- # web.status("410 Sad but true, this lonely page is gone :(")
- # web.status(206)
- # web.status("400")
- #
- # The default status is "200 OK". If a "Location" header is set, the
- # default status is "302 Found".
- def status(str)
- # {{{
- if @output_started
- raise "HTTP-Headers are already send. You can't change them after output has started!"
- end
- unless @output_allowed
- raise "You just can set headers inside of a Rweb::out-block"
- end
- if str.is_a?Integer
- @status = str
- elsif str.is_a?String
- p1 = /^([0-9]{3}) ?(.*)$/
- p2 = /^HTTP\/1\.[01] ([0-9]{3}) ?(.*)$/
- p3 = /^status: ([0-9]{3}) ?(.*)$/i
-
- if (a = p1.match(str)) == nil
- if (a = p2.match(str)) == nil
- if (a = p3.match(str)) == nil
- raise ArgumentError, "Invalid argument", caller
- end
- end
- end
- @status = a[1].to_i
- if a[2] != ""
- @reasonPhrase = a[2]
- else
- @reasonPhrase = getReasonPhrase(@status)
- end
- else
- raise ArgumentError, "Argument of setstatus must be integer or string", caller
- end
- # }}}
- end
-
- # Handles the output of your content and rescues all exceptions. Send all
- # data in the block to this method. For example:
- # web.out do
- # web.header("Content-Type: text/plain")
- # web.puts("Hello, plain world!")
- # end
- def out
- # {{{
- @output_allowed = true
- @buffer = []; # We use an array as buffer, because it's more performant :)
-
- begin
- yield
- rescue Exception => exception
- $stderr.puts "Ruby exception rescued (#{exception.class}): #{exception.message}"
- $stderr.puts exception.backtrace.join("\n")
-
- unless @output_started
- self.setstatus(500)
- @header = {}
- end
-
- unless (@settings.has_key?("hide errors") and @settings["hide errors"] == true)
- unless @output_started
- self.header("Content-Type: text/html")
- self.puts "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Strict//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">"
- self.puts "<html>"
- self.puts "<head>"
- self.puts "<title>500 Internal Server Error</title>"
- self.puts "</head>"
- self.puts "<body>"
- end
- if @header.has_key?("content-type") and (@header["content-type"] =~ /^text\/html/i) == 0
- self.puts "<h1>Internal Server Error</h1>"
- self.puts "<p>The server encountered an exception and was unable to complete your request.</p>"
- self.puts "<p>The exception has provided the following information:</p>"
- self.puts "<pre style=\"background: #FFCCCC; border: black solid 2px; margin-left: 2cm; margin-right: 2cm; padding: 2mm;\"><b>#{exception.class}</b>: #{exception.message} <b>on</b>"
- self.puts
- self.puts "#{exception.backtrace.join("\n")}</pre>"
- self.puts "</body>"
- self.puts "</html>"
- else
- self.puts "The server encountered an exception and was unable to complete your request"
- self.puts "The exception has provided the following information:"
- self.puts "#{exception.class}: #{exception.message}"
- self.puts
- self.puts exception.backtrace.join("\n")
- end
- end
- end
-
- if @settings["cache"]
- buffer = @buffer.join
-
- unless @output_started
- unless @header.has_key?("content-length")
- self.header("content-length: #{buffer.length}")
- end
-
- sendHeaders
- end
- $stdout.print(buffer)
- elsif !@output_started
- sendHeaders
- end
- @output_allowed = false;
- # }}}
- end
-
- # Decodes URL encoded data, %20 for example stands for a space.
- def Rweb.unescape(str)
- # {{{
- if defined? str and str.is_a? String
- str.gsub!(/\+/, " ")
- str.gsub(/%.{2}/) do | s |
- s[1,2].hex.chr
- end
- end
- # }}}
- end
-
- protected
- def sendHeaders
- # {{{
-
- Cookie.disallow # no more cookies can be set or modified
- if !(@settings.has_key?("silent") and @settings["silent"] == true) and !@header.has_key?("x-powered-by")
- if @mod_ruby
- header("x-powered-by: #{RWEB} (Ruby/#{RUBY_VERSION}, #{MOD_RUBY})");
- else
- header("x-powered-by: #{RWEB} (Ruby/#{RUBY_VERSION})");
- end
- end
-
- if @output_method == "ph"
- if ((@status == nil or @status == 200) and !@header.has_key?("content-type") and !@header.has_key?("location"))
- header("content-type: text/html")
- end
-
- if @status != nil
- $stdout.print "Status: #{@status} #{@reasonPhrase}\r\n"
- end
-
- @header.each do |key, value|
- key = key *1 # "unfreeze" key :)
- key[0] = key[0,1].upcase![0]
-
- key = key.gsub(/-[a-z]/) do |char|
- "-" + char[1,1].upcase
- end
-
- $stdout.print "#{key}: #{value}\r\n"
- end
- cookies = Cookie.getHttpHeader # Get all cookies as an HTTP Header
- if cookies
- $stdout.print cookies
- end
-
- $stdout.print "\r\n"
-
- elsif @output_method == "nph"
- elsif @output_method == "mod_ruby"
- r = Apache.request
-
- if ((@status == nil or @status == 200) and !@header.has_key?("content-type") and !@header.has_key?("location"))
- header("text/html")
- end
-
- if @status != nil
- r.status_line = "#{@status} #{@reasonPhrase}"
- end
-
- r.send_http_header
- @header.each do |key, value|
- key = key *1 # "unfreeze" key :)
-
- key[0] = key[0,1].upcase![0]
- key = key.gsub(/-[a-z]/) do |char|
- "-" + char[1,1].upcase
- end
- puts "#{key}: #{value.class}"
- #r.headers_out[key] = value
- end
- end
- @output_started = true
- # }}}
- end
-
- def getReasonPhrase (status)
- # {{{
- if status == 100
- "Continue"
- elsif status == 101
- "Switching Protocols"
- elsif status == 200
- "OK"
- elsif status == 201
- "Created"
- elsif status == 202
- "Accepted"
- elsif status == 203
- "Non-Authoritative Information"
- elsif status == 204
- "No Content"
- elsif status == 205
- "Reset Content"
- elsif status == 206
- "Partial Content"
- elsif status == 300
- "Multiple Choices"
- elsif status == 301
- "Moved Permanently"
- elsif status == 302
- "Found"
- elsif status == 303
- "See Other"
- elsif status == 304
- "Not Modified"
- elsif status == 305
- "Use Proxy"
- elsif status == 307
- "Temporary Redirect"
- elsif status == 400
- "Bad Request"
- elsif status == 401
- "Unauthorized"
- elsif status == 402
- "Payment Required"
- elsif status == 403
- "Forbidden"
- elsif status == 404
- "Not Found"
- elsif status == 405
- "Method Not Allowed"
- elsif status == 406
- "Not Acceptable"
- elsif status == 407
- "Proxy Authentication Required"
- elsif status == 408
- "Request Time-out"
- elsif status == 409
- "Conflict"
- elsif status == 410
- "Gone"
- elsif status == 411
- "Length Required"
- elsif status == 412
- "Precondition Failed"
- elsif status == 413
- "Request Entity Too Large"
- elsif status == 414
- "Request-URI Too Large"
- elsif status == 415
- "Unsupported Media Type"
- elsif status == 416
- "Requested range not satisfiable"
- elsif status == 417
- "Expectation Failed"
- elsif status == 500
- "Internal Server Error"
- elsif status == 501
- "Not Implemented"
- elsif status == 502
- "Bad Gateway"
- elsif status == 503
- "Service Unavailable"
- elsif status == 504
- "Gateway Time-out"
- elsif status == 505
- "HTTP Version not supported"
- else
- raise "Unknown Statuscode. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1 for more information."
- end
- # }}}
- end
-end
-
-class Cookie
- attr_reader :name, :value, :maxage, :path, :domain, :secure, :comment
-
- # Sets a cookie. Please see below for details of the attributes.
- def initialize (name, value = nil, maxage = nil, path = nil, domain = nil, secure = false)
- # {{{
- # HTTP headers (Cookies are a HTTP header) can only set, while no content
- # is send. So an exception will be raised, when @@allowed is set to false
- # and a new cookie has set.
- unless defined?(@@allowed)
- @@allowed = true
- end
- unless @@allowed
- raise "You can't set cookies after the HTTP headers are send."
- end
-
- unless defined?(@@list)
- @@list = []
- end
- @@list += [self]
-
- unless defined?(@@type)
- @@type = "netscape"
- end
-
- unless name.class == String
- raise TypeError, "The name of a cookie must be a string", caller
- end
- if value.class.superclass == Integer || value.class == Float
- value = value.to_s
- elsif value.class != String && value != nil
- raise TypeError, "The value of a cookie must be a string, integer, float or nil", caller
- end
- if maxage.class == Time
- maxage = maxage - Time.now
- elsif !maxage.class.superclass == Integer || !maxage == nil
- raise TypeError, "The maxage date of a cookie must be an Integer or Time object or nil.", caller
- end
- unless path.class == String || path == nil
- raise TypeError, "The path of a cookie must be nil or a string", caller
- end
- unless domain.class == String || domain == nil
- raise TypeError, "The value of a cookie must be nil or a string", caller
- end
- unless secure == true || secure == false
- raise TypeError, "The secure field of a cookie must be true or false", caller
- end
-
- @name, @value, @maxage, @path, @domain, @secure = name, value, maxage, path, domain, secure
- @comment = nil
- # }}}
- end
-
- # Modifies the value of this cookie. The information you want to store. If the
- # value is nil, the cookie will be deleted by the client.
- #
- # This attribute can be a String, Integer or Float object or nil.
- def value=(value)
- # {{{
- if value.class.superclass == Integer || value.class == Float
- value = value.to_s
- elsif value.class != String && value != nil
- raise TypeError, "The value of a cookie must be a string, integer, float or nil", caller
- end
- @value = value
- # }}}
- end
-
- # Modifies the maxage of this cookie. This attribute defines the lifetime of
- # the cookie, in seconds. A value of 0 means the cookie should be discarded
- # imediatly. If it set to nil, the cookie will be deleted when the browser
- # will be closed.
- #
- # Attention: This is different from other implementations like PHP, where you
- # gives the seconds since 1/1/1970 0:00:00 GMT.
- #
- # This attribute must be an Integer or Time object or nil.
- def maxage=(maxage)
- # {{{
- if maxage.class == Time
- maxage = maxage - Time.now
- elsif maxage.class.superclass == Integer || !maxage == nil
- raise TypeError, "The maxage of a cookie must be an Interger or Time object or nil.", caller
- end
- @maxage = maxage
- # }}}
- end
-
- # Modifies the path value of this cookie. The client will send this cookie
- # only, if the requested document is this directory or a subdirectory of it.
- #
- # The value of the attribute must be a String object or nil.
- def path=(path)
- # {{{
- unless path.class == String || path == nil
- raise TypeError, "The path of a cookie must be nil or a string", caller
- end
- @path = path
- # }}}
- end
-
- # Modifies the domain value of this cookie. The client will send this cookie
- # only if it's connected with this domain (or a subdomain, if the first
- # character is a dot like in ".ruby-lang.org")
- #
- # The value of this attribute must be a String or nil.
- def domain=(domain)
- # {{{
- unless domain.class == String || domain == nil
- raise TypeError, "The domain of a cookie must be a String or nil.", caller
- end
- @domain = domain
- # }}}
- end
-
- # Modifies the secure flag of this cookie. If it's true, the client will only
- # send this cookie if it is secured connected with us.
- #
- # The value od this attribute has to be true or false.
- def secure=(secure)
- # {{{
- unless secure == true || secure == false
- raise TypeError, "The secure field of a cookie must be true or false", caller
- end
- @secure = secure
- # }}}
- end
-
- # Modifies the comment value of this cookie. The comment won't be send, if
- # type is "netscape".
- def comment=(comment)
- # {{{
- unless comment.class == String || comment == nil
- raise TypeError, "The comment of a cookie must be a string or nil", caller
- end
- @comment = comment
- # }}}
- end
-
- # Changes the type of all cookies.
- # Allowed values are RFC2109 and netscape (default).
- def Cookie.type=(type)
- # {{{
- unless @@allowed
- raise "The cookies are allready send, so you can't change the type anymore."
- end
- unless type.downcase == "rfc2109" && type.downcase == "netscape"
- raise "The type of the cookies must be \"RFC2109\" or \"netscape\"."
- end
- @@type = type;
- # }}}
- end
-
- # After sending this message, no cookies can be set or modified. Use it, when
- # HTTP-Headers are send. Rweb does this for you.
- def Cookie.disallow
- # {{{
- @@allowed = false
- true
- # }}}
- end
-
- # Returns a HTTP header (type String) with all cookies. Rweb does this for
- # you.
- def Cookie.getHttpHeader
- # {{{
- if defined?(@@list)
- if @@type == "netscape"
- str = ""
- @@list.each do |cookie|
- if cookie.value == nil
- cookie.maxage = 0
- cookie.value = ""
- end
- # TODO: Name and value should be escaped!
- str += "Set-Cookie: #{cookie.name}=#{cookie.value}"
- unless cookie.maxage == nil
- expire = Time.now + cookie.maxage
- expire.gmtime
- str += "; Expire=#{expire.strftime("%a, %d-%b-%Y %H:%M:%S %Z")}"
- end
- unless cookie.domain == nil
- str += "; Domain=#{cookie.domain}"
- end
- unless cookie.path == nil
- str += "; Path=#{cookie.path}"
- end
- if cookie.secure
- str += "; Secure"
- end
- str += "\r\n"
- end
- return str
- else # type == "RFC2109"
- str = "Set-Cookie: "
- comma = false;
-
- @@list.each do |cookie|
- if cookie.value == nil
- cookie.maxage = 0
- cookie.value = ""
- end
- if comma
- str += ","
- end
- comma = true
-
- str += "#{cookie.name}=\"#{cookie.value}\""
- unless cookie.maxage == nil
- str += "; Max-Age=\"#{cookie.maxage}\""
- end
- unless cookie.domain == nil
- str += "; Domain=\"#{cookie.domain}\""
- end
- unless cookie.path == nil
- str += "; Path=\"#{cookie.path}\""
- end
- if cookie.secure
- str += "; Secure"
- end
- unless cookie.comment == nil
- str += "; Comment=\"#{cookie.comment}\""
- end
- str += "; Version=\"1\""
- end
- str
- end
- else
- false
- end
- # }}}
- end
-end
-
-require 'strscan'
-
-module BBCode
- DEBUG = true
-
- use 'encoder', 'tags', 'tagstack', 'smileys'
-
-=begin
- The Parser class takes care of the encoding.
- It scans the given BBCode (as plain text), finds tags
- and smilies and also makes links of urls in text.
-
- Normal text is send directly to the encoder.
-
- If a tag was found, an instance of a Tag subclass is created
- to handle the case.
-
- The @tagstack manages tag nesting and ensures valid HTML.
-=end
-
- class Parser
- class Attribute
- # flatten and use only one empty_arg
- def self.create attr
- attr = flatten attr
- return @@empty_attr if attr.empty?
- new attr
- end
-
- private_class_method :new
-
- # remove leading and trailing whitespace; concat lines
- def self.flatten attr
- attr.strip.gsub(/\n/, ' ')
- # -> ^ and $ can only match at begin and end now
- end
-
- ATTRIBUTE_SCAN = /
- (?!$) # don't match at end
- \s*
- ( # $1 = key
- [^=\s\]"\\]*
- (?:
- (?: \\. | "[^"\\]*(?:\\.[^"\\]*)*"? )
- [^=\s\]"\\]*
- )*
- )
- (?:
- =
- ( # $2 = value
- [^\s\]"\\]*
- (?:
- (?: \\. | "[^"\\]*(?:\\.[^"\\]*)*"? )
- [^\s\]"\\]*
- )*
- )?
- )?
- \s*
- /x
-
- def self.parse source
- source = source.dup
- # empty_tag: the tag looks like [... /]
- # slice!: this deletes the \s*/] at the end
- # \s+ because [url=http://rubybb.org/forum/] is NOT an empty tag.
- # In RubyBBCode, you can use [url=http://rubybb.org/forum/ /], and this has to be
- # interpreted correctly.
- empty_tag = source.sub!(/^:/, '=') or source.slice!(/\/$/)
- debug 'PARSE: ' + source.inspect + ' => ' + empty_tag.inspect
- #-> we have now an attr that's EITHER empty OR begins and ends with non-whitespace.
-
- attr = Hash.new
- attr[:flags] = []
- source.scan(ATTRIBUTE_SCAN) { |key, value|
- if not value
- attr[:flags] << unescape(key)
- else
- next if value.empty? and key.empty?
- attr[unescape(key)] = unescape(value)
- end
- }
- debug attr.inspect
-
- return empty_tag, attr
- end
-
- def self.unescape_char esc
- esc[1]
- end
-
- def self.unquote qt
- qt[1..-1].chomp('"').gsub(/\\./) { |esc| unescape_char esc }
- end
-
- def self.unescape str
- str.gsub(/ (\\.) | (" [^"\\]* (?:\\.[^"\\]*)* "?) /x) {
- if $1
- unescape_char $1
- else
- unquote $2
- end
- }
- end
-
- include Enumerable
- def each &block
- @args.each(&block)
- end
-
- attr_reader :source, :args, :value
-
- def initialize source
- @source = source
- debug 'Attribute#new(%p)' % source
- @empty_tag, @attr = Attribute.parse source
- @value = @attr[''].to_s
- end
-
- def empty?
- self == @@empty_attr
- end
-
- def empty_tag?
- @empty_tag
- end
-
- def [] *keys
- res = @attr[*keys]
- end
-
- def flags
- attr[:flags]
- end
-
- def to_s
- @attr
- end
-
- def inspect
- 'ATTR[' + @attr.inspect + (@empty_tag ? ' | empty tag' : '') + ']'
- end
- end
- class Attribute
- @@empty_attr = new ''
- end
- end
-
- class Parser
- def Parser.flatten str
- # replace mac & dos newlines with unix style
- str.gsub(/\r\n?/, "\n")
- end
-
- def initialize input = ''
- # input manager
- @scanner = StringScanner.new ''
- # output manager
- @encoder = Encoder.new
- @output = ''
- # tag manager
- @tagstack = TagStack.new(@encoder)
-
- @do_magic = true
- # set the input
- feed input
- end
-
- # if you want, you can feed a parser instance after creating,
- # or even feed it repeatedly.
- def feed food
- @scanner.string = Parser.flatten food
- end
-
- # parse through the string using parse_token
- def parse
- parse_token until @scanner.eos?
- @tagstack.close_all
- @output = parse_magic @encoder.output
- end
-
- def output
- @output
- end
-
- # ok, internals start here
- private
- # the default output functions. everything should use them or the tags.
- def add_text text = @scanner.matched
- @encoder.add_text text
- end
-
- # use this carefully
- def add_html html
- @encoder.add_html html
- end
-
- # highlights the text as error
- def add_garbage garbage
- add_html '<span class="error">' if DEBUG
- add_text garbage
- add_html '</span>' if DEBUG
- end
-
- # unknown and incorrectly nested tags are ignored and
- # sent as plaintext (garbage in - garbage out).
- # in debug mode, garbage is marked with lime background.
- def garbage_out start
- @scanner.pos = start
- garbage = @scanner.scan(/./m)
- debug 'GARBAGE: ' + garbage
- add_garbage garbage
- end
-
- # simple text; everything but [, \[ allowed
- SIMPLE_TEXT_SCAN_ = /
- [^\[\\]* # normal*
- (?: # (
- \\.? # special
- [^\[\\]* # normal*
- )* # )*
- /mx
- SIMPLE_TEXT_SCAN = /[^\[]+/
-
-=begin
-
- WHAT IS A TAG?
- ==============
-
- Tags in BBCode can be much more than just a simple [b].
- I use many terms here to differ the parts of each tag.
-
- Basic scheme:
- [ code ]
- TAG START TAG INFO TAG END
-
- Most tags need a second tag to close the range it opened.
- This is done with CLOSING TAGS:
- [/code]
- or by using empty tags that have no content and close themselfes:
- [url=winamp.com /]
- You surely know this from HTML.
- These slashes define the TAG KIND = normal|closing|empty and
- cannot be used together.
-
- Everything between [ and ] and expluding the slashes is called the
- TAG INFO. This info may contain:
- - TAG ID
- - TAG NAME including the tag id
- - attributes
-
- The TAG ID is the first char of the info:
-
- TAG | ID
- ----------+----
- [quote] | q
- [&plusmn] | &
- ["[b]"] | "
- [/url] | u
- [---] | -
-
- As you can see, the tag id shows the TAG TYPE, it can be a
- normal tag, a formatting tag or an entity.
- Therefor, the parser first scans the id to decide how to go
- on with parsing.
-=end
- # tag
- # TODO more complex expression allowing
- # [quote="[ladico]"] and [quote=\[ladico\]] to be correct tags
- TAG_BEGIN_SCAN = /
- \[ # tag start
- ( \/ )? # $1 = closing tag?
- ( [^\]] ) # $2 = tag id
- /x
- TAG_END_SCAN = /
- [^\]]* # rest that was not handled
- \]? # tag end
- /x
- CLOSE_TAG_SCAN = /
- ( [^\]]* ) # $1 = the rest of the tag info
- ( \/ )? # $2 = empty tag?
- \]? # tag end
- /x
- UNCLOSED_TAG_SCAN = / \[ /x
-
- CLASSIC_TAG_SCAN = / [a-z]* /ix
-
- SEPARATOR_TAG_SCAN = / \** /x
-
- FORMAT_TAG_SCAN = / -- -* /x
-
- QUOTED_SCAN = /
- ( # $1 = quoted text
- [^"\\]* # normal*
- (?: # (
- \\. # special
- [^"\\]* # normal*
- )* # )*
- )
- "? # end quote "
- /mx
-
- ENTITY_SCAN = /
- ( [^;\]]+ ) # $1 = entity code
- ;? # optional ending semicolon
- /ix
-
- SMILEY_SCAN = Smileys::SMILEY_PATTERN
-
- # this is the main parser loop that separates
- # text - everything until "["
- # from
- # tags - starting with "[", ending with "]"
- def parse_token
- if @scanner.scan(SIMPLE_TEXT_SCAN)
- add_text
- else
- handle_tag
- end
- end
-
- def handle_tag
- tag_start = @scanner.pos
-
- unless @scanner.scan TAG_BEGIN_SCAN
- garbage_out tag_start
- return
- end
-
- closing, id = @scanner[1], @scanner[2]
- #debug 'handle_tag(%p)' % @scanner.matched
-
- handled =
- case id
-
- when /[a-z]/i
- if @scanner.scan(CLASSIC_TAG_SCAN)
- if handle_classic_tag(id + @scanner.matched, closing)
- already_closed = true
- end
- end
-
- when '*'
- if @scanner.scan(SEPARATOR_TAG_SCAN)
- handle_asterisk tag_start, id + @scanner.matched
- true
- end
-
- when '-'
- if @scanner.scan(FORMAT_TAG_SCAN)
- #format = id + @scanner.matched
- @encoder.add_html "\n<hr>\n"
- true
- end
-
- when '"'
- if @scanner.scan(QUOTED_SCAN)
- @encoder.add_text unescape(@scanner[1])
- true
- end
-
- when '&'
- if @scanner.scan(ENTITY_SCAN)
- @encoder.add_entity @scanner[1]
- true
- end
-
- when Smileys::SMILEY_START_CHARSET
- @scanner.pos = @scanner.pos - 1 # (ungetch)
- if @scanner.scan(SMILEY_SCAN)
- @encoder.add_html Smileys.smiley_to_image(@scanner.matched)
- true
- end
-
- end # case
-
- return garbage_out(tag_start) unless handled
-
- @scanner.scan(TAG_END_SCAN) unless already_closed
- end
-
- ATTRIBUTES_SCAN = /
- (
- [^\]"\\]*
- (?:
- (?:
- \\.
- |
- "
- [^"\\]*
- (?:
- \\.
- [^"\\]*
- )*
- "?
- )
- [^\]"\\]*
- )*
- )
- \]?
- /x
-
- def handle_classic_tag name, closing
- debug 'TAG: ' + (closing ? '/' : '') + name
- # flatten
- name.downcase!
- tag_class = TAG_LIST[name]
- return unless tag_class
-
- #debug((opening ? 'OPEN ' : 'CLOSE ') + tag_class.name)
-
- # create an attribute object to handle it
- @scanner.scan(ATTRIBUTES_SCAN)
- #debug name + ':' + @scanner[1]
- attr = Attribute.create @scanner[1]
- #debug 'ATTRIBUTES %p ' % attr #unless attr.empty?
-
- #debug 'closing: %p; name=%s, attr=%p' % [closing, name, attr]
-
- # OPEN
- if not closing and tag = @tagstack.try_open_class(tag_class, attr)
- #debug 'opening'
- tag.do_open @scanner
- # this should be done by the tag itself.
- if attr.empty_tag?
- tag.handle_empty
- @tagstack.close_tag
- elsif tag.special_content?
- handle_special_content(tag)
- @tagstack.close_tag
- # # ignore asterisks directly after the opening; these are phpBBCode
- # elsif tag.respond_to? :asterisk
- # debug 'SKIP ASTERISKS: ' if @scanner.skip(ASTERISK_TAGS_SCAN)
- end
-
- # CLOSE
- elsif @tagstack.try_close_class(tag_class)
- #debug 'closing'
- # GARBAGE
- else
- return
- end
-
- true
- end
-
- def handle_asterisk tag_start, stars
- #debug 'ASTERISK: ' + stars.to_s
- # rule for asterisk tags: they belong to the last tag
- # that handles them. tags opened after this tag are closed.
- # if no open tag uses them, all are closed.
- tag = @tagstack.close_all_until { |tag| tag.respond_to? :asterisk }
- unless tag and tag.asterisk stars, @scanner
- garbage_out tag_start
- end
- end
-
- def handle_special_content tag
- scanned = @scanner.scan_until(tag.closing_tag)
- if scanned
- scanned.slice!(-(@scanner.matched.size)..-1)
- else
- scanned = @scanner.scan(/.*/m).to_s
- end
- #debug 'SPECIAL CONTENT: ' + scanned
- tag.handle_content(scanned)
- end
-
- def unescape text
- # input: correctly formatted quoted string (without the quotes)
- text.gsub(/\\(?:(["\\])|.)/) { $1 or $& }
- end
-
-
- # MAGIC FEAUTURES
-
- URL_PATTERN = /(?:(?:www|ftp)\.|(?>\w{3,}):\/\/)\S+/
- EMAIL_PATTERN = /(?>[\w\-_.]+)@[\w\-\.]+\.\w+/
-
- HAS_MAGIC = /[&@#{Smileys::SMILEY_START_CHARS}]|(?i:www|ftp)/
-
- MAGIC_PATTERN = Regexp.new('(\W|^)(%s)' %
- [Smileys::MAGIC_SMILEY_PATTERN, URL_PATTERN, EMAIL_PATTERN].map { |pattern|
- pattern.to_s
- }.join('|') )
-
- IS_SMILEY_PATTERN = Regexp.new('^%s' % Smileys::SMILEY_START_CHARSET.to_s )
- IS_URL_PATTERN = /^(?:(?i:www|ftp)\.|(?>\w+):\/\/)/
- URL_STARTS_WITH_PROTOCOL = /^\w+:\/\//
- IS_EMAIL_PATTERN = /^[\w\-_.]+@/
-
- def to_magic text
- # debug MAGIC_PATTERN.to_s
- text.gsub!(MAGIC_PATTERN) {
- magic = $2
- $1 + case magic
- when IS_SMILEY_PATTERN
- Smileys.smiley_to_img magic
- when IS_URL_PATTERN
- last = magic.slice_punctation! # no punctation in my URL
- href = magic
- href.insert(0, 'http://') unless magic =~ URL_STARTS_WITH_PROTOCOL
- '<a href="' + href + '">' + magic + '</a>' + last
- when IS_EMAIL_PATTERN
- last = magic.slice_punctation!
- '<a href="mailto:' + magic + '">' + magic + '</a>' + last
- else
- raise '{{{' + magic + '}}}'
- end
- }
- text
- end
-
- # handles smileys and urls
- def parse_magic html
- return html unless @do_magic
- scanner = StringScanner.new html
- out = ''
- while scanner.rest?
- if scanner.scan(/ < (?: a\s .*? <\/a> | pre\W .*? <\/pre> | [^>]* > ) /mx)
- out << scanner.matched
- elsif scanner.scan(/ [^<]+ /x)
- out << to_magic(scanner.matched)
-
- # this should never happen
- elsif scanner.scan(/./m)
- raise 'ERROR: else case reached'
- end
- end
- out
- end
- end # Parser
-end
-
-class String
- def slice_punctation!
- slice!(/[.:,!\?]+$/).to_s # return '' instead of nil
- end
-end
-
-#
-# = Grammar
-#
-# An implementation of common algorithms on grammars.
-#
-# This is used by Shinobu, a visualization tool for educating compiler-building.
-#
-# Thanks to Andreas Kunert for his wonderful LR(k) Pamphlet (German, see http://www.informatik.hu-berlin.de/~kunert/papers/lr-analyse), and Aho/Sethi/Ullman for their Dragon Book.
-#
-# Homepage:: http://shinobu.cYcnus.de (not existing yet)
-# Author:: murphy (Kornelius Kalnbach)
-# Copyright:: (cc) 2005 cYcnus
-# License:: GPL
-# Version:: 0.2.0 (2005-03-27)
-
-require 'set_hash'
-require 'ctype'
-require 'tools'
-require 'rules'
-require 'trace'
-
-require 'first'
-require 'follow'
-
-# = Grammar
-#
-# == Syntax
-#
-# === Rules
-#
-# Each line is a rule.
-# The syntax is
-#
-# left - right
-#
-# where +left+ and +right+ can be uppercase and lowercase letters,
-# and <code>-</code> can be any combination of <, >, - or whitespace.
-#
-# === Symbols
-#
-# Uppercase letters stand for meta symbols, lowercase for terminals.
-#
-# You can make epsilon-derivations by leaving <code><right></code> empty.
-#
-# === Example
-# S - Ac
-# A - Sc
-# A - b
-# A -
-class Grammar
-
- attr_reader :tracer
- # Creates a new Grammar.
- # If $trace is true, the algorithms explain (textual) what they do to $stdout.
- def initialize data, tracer = Tracer.new
- @tracer = tracer
- @rules = Rules.new
- @terminals, @meta_symbols = SortedSet.new, Array.new
- @start_symbol = nil
- add_rules data
- end
-
- attr_reader :meta_symbols, :terminals, :rules, :start_symbol
-
- alias_method :sigma, :terminals
- alias_method :alphabet, :terminals
- alias_method :variables, :meta_symbols
- alias_method :nonterminals, :meta_symbols
-
- # A string representation of the grammar for debugging.
- def inspect productions_too = false
- 'Grammar(meta symbols: %s; alphabet: %s; productions: [%s]; start symbol: %s)' %
- [
- meta_symbols.join(', '),
- terminals.join(', '),
- if productions_too
- @rules.inspect
- else
- @rules.size
- end,
- start_symbol
- ]
- end
-
- # Add rules to the grammar. +rules+ should be a String or respond to +scan+ in a similar way.
- #
- # Syntax: see Grammar.
- def add_rules grammar
- @rules = Rules.parse grammar do |rule|
- @start_symbol ||= rule.left
- @meta_symbols << rule.left
- @terminals.merge rule.right.split('').select { |s| terminal? s }
- end
- @meta_symbols.uniq!
- update
- end
-
- # Returns a hash acting as FIRST operator, so that
- # <code>first["ABC"]</code> is FIRST(ABC).
- # See http://en.wikipedia.org/wiki/LL_parser "Constructing an LL(1) parsing table" for details.
- def first
- first_operator
- end
-
- # Returns a hash acting as FOLLOW operator, so that
- # <code>first["A"]</code> is FOLLOW(A).
- # See http://en.wikipedia.org/wiki/LL_parser "Constructing an LL(1) parsing table" for details.
- def follow
- follow_operator
- end
-
- LLError = Class.new(Exception)
- LLErrorType1 = Class.new(LLError)
- LLErrorType2 = Class.new(LLError)
-
- # Tests if the grammar is LL(1).
- def ll1?
- begin
- for meta in @meta_symbols
- first_sets = @rules[meta].map { |alpha| first[alpha] }
- first_sets.inject(Set[]) do |already_used, another_first_set|
- unless already_used.disjoint? another_first_set
- raise LLErrorType1
- end
- already_used.merge another_first_set
- end
-
- if first[meta].include? EPSILON and not first[meta].disjoint? follow[meta]
- raise LLErrorType2
- end
- end
- rescue LLError
- false
- else
- true
- end
- end
-
-private
-
- def first_operator
- @first ||= FirstOperator.new self
- end
-
- def follow_operator
- @follow ||= FollowOperator.new self
- end
-
- def update
- @first = @follow = nil
- end
-
-end
-
-if $0 == __FILE__
- eval DATA.read, nil, $0, __LINE__+4
-end
-
-require 'test/unit'
-
-class TestCaseGrammar < Test::Unit::TestCase
-
- include Grammar::Symbols
-
- def fifo s
- Set[*s.split('')]
- end
-
- def test_fifo
- assert_equal Set[], fifo('')
- assert_equal Set[EPSILON, END_OF_INPUT, 'x', 'Y'], fifo('?xY$')
- end
-
- TEST_GRAMMAR_1 = <<-EOG
-S - ABCD
-A - a
-A -
-B - b
-B -
-C - c
-C -
-D - S
-D -
- EOG
-
- def test_symbols
- assert EPSILON
- assert END_OF_INPUT
- end
-
- def test_first_1
- g = Grammar.new TEST_GRAMMAR_1
-
- f = nil
- assert_nothing_raised { f = g.first }
- assert_equal(Set['a', EPSILON], f['A'])
- assert_equal(Set['b', EPSILON], f['B'])
- assert_equal(Set['c', EPSILON], f['C'])
- assert_equal(Set['a', 'b', 'c', EPSILON], f['D'])
- assert_equal(f['D'], f['S'])
- end
-
- def test_follow_1
- g = Grammar.new TEST_GRAMMAR_1
-
- f = nil
- assert_nothing_raised { f = g.follow }
- assert_equal(Set['a', 'b', 'c', END_OF_INPUT], f['A'])
- assert_equal(Set['a', 'b', 'c', END_OF_INPUT], f['B'])
- assert_equal(Set['a', 'b', 'c', END_OF_INPUT], f['C'])
- assert_equal(Set[END_OF_INPUT], f['D'])
- assert_equal(Set[END_OF_INPUT], f['S'])
- end
-
-
- TEST_GRAMMAR_2 = <<-EOG
-S - Ed
-E - EpT
-E - EmT
-E - T
-T - TuF
-T - TdF
-T - F
-F - i
-F - n
-F - aEz
- EOG
-
- def test_first_2
- g = Grammar.new TEST_GRAMMAR_2
-
- f = nil
- assert_nothing_raised { f = g.first }
- assert_equal(Set['a', 'n', 'i'], f['E'])
- assert_equal(Set['a', 'n', 'i'], f['F'])
- assert_equal(Set['a', 'n', 'i'], f['T'])
- assert_equal(Set['a', 'n', 'i'], f['S'])
- end
-
- def test_follow_2
- g = Grammar.new TEST_GRAMMAR_2
-
- f = nil
- assert_nothing_raised { f = g.follow }
- assert_equal(Set['m', 'd', 'z', 'p'], f['E'])
- assert_equal(Set['m', 'd', 'z', 'p', 'u'], f['F'])
- assert_equal(Set['m', 'd', 'z', 'p', 'u'], f['T'])
- assert_equal(Set[END_OF_INPUT], f['S'])
- end
-
- LLError = Grammar::LLError
-
- TEST_GRAMMAR_3 = <<-EOG
-E - TD
-D - pTD
-D -
-T - FS
-S - uFS
-S -
-S - p
-F - aEz
-F - i
- EOG
-
- NoError = Class.new(Exception)
-
- def test_first_3
- g = Grammar.new TEST_GRAMMAR_3
-
- # Grammar 3 is LL(1), so all first-sets must be disjoint.
- f = nil
- assert_nothing_raised { f = g.first }
- assert_equal(Set['a', 'i'], f['E'])
- assert_equal(Set[EPSILON, 'p'], f['D'])
- assert_equal(Set['a', 'i'], f['F'])
- assert_equal(Set['a', 'i'], f['T'])
- assert_equal(Set[EPSILON, 'u', 'p'], f['S'])
- for m in g.meta_symbols
- r = g.rules[m]
- firsts = r.map { |x| f[x] }.to_set
- assert_nothing_raised do
- firsts.inject(Set.new) do |already_used, another_first_set|
- raise LLError, 'not disjoint!' unless already_used.disjoint? another_first_set
- already_used.merge another_first_set
- end
- end
- end
- end
-
- def test_follow_3
- g = Grammar.new TEST_GRAMMAR_3
-
- # Grammar 3 is not LL(1), because epsilon is in FIRST(S),
- # but FIRST(S) and FOLLOW(S) are not disjoint.
- f = nil
- assert_nothing_raised { f = g.follow }
- assert_equal(Set['z', END_OF_INPUT], f['E'])
- assert_equal(Set['z', END_OF_INPUT], f['D'])
- assert_equal(Set['z', 'p', 'u', END_OF_INPUT], f['F'])
- assert_equal(Set['p', 'z', END_OF_INPUT], f['T'])
- assert_equal(Set['p', 'z', END_OF_INPUT], f['S'])
- for m in g.meta_symbols
- first_m = g.first[m]
- next unless first_m.include? EPSILON
- assert_raise(m == 'S' ? LLError : NoError) do
- if first_m.disjoint? f[m]
- raise NoError # this is fun :D
- else
- raise LLError
- end
- end
- end
- end
-
- TEST_GRAMMAR_3b = <<-EOG
-E - TD
-D - pTD
-D - PTD
-D -
-T - FS
-S - uFS
-S -
-F - aEz
-F - i
-P - p
- EOG
-
- def test_first_3b
- g = Grammar.new TEST_GRAMMAR_3b
-
- # Grammar 3b is NOT LL(1), since not all first-sets are disjoint.
- f = nil
- assert_nothing_raised { f = g.first }
- assert_equal(Set['a', 'i'], f['E'])
- assert_equal(Set[EPSILON, 'p'], f['D'])
- assert_equal(Set['p'], f['P'])
- assert_equal(Set['a', 'i'], f['F'])
- assert_equal(Set['a', 'i'], f['T'])
- assert_equal(Set[EPSILON, 'u'], f['S'])
- for m in g.meta_symbols
- r = g.rules[m]
- firsts = r.map { |x| f[x] }
- assert_raise(m == 'D' ? LLError : NoError) do
- firsts.inject(Set.new) do |already_used, another_first_set|
- raise LLError, 'not disjoint!' unless already_used.disjoint? another_first_set
- already_used.merge another_first_set
- end
- raise NoError
- end
- end
- end
-
- def test_follow_3b
- g = Grammar.new TEST_GRAMMAR_3b
-
- # Although Grammar 3b is NOT LL(1), the FOLLOW-condition is satisfied.
- f = nil
- assert_nothing_raised { f = g.follow }
- assert_equal(fifo('z$'), f['E'], 'E')
- assert_equal(fifo('z$'), f['D'], 'D')
- assert_equal(fifo('ai'), f['P'], 'P')
- assert_equal(fifo('z$pu'), f['F'], 'F')
- assert_equal(fifo('z$p'), f['T'], 'T')
- assert_equal(fifo('z$p'), f['S'], 'S')
- for m in g.meta_symbols
- first_m = g.first[m]
- next unless first_m.include? EPSILON
- assert_raise(NoError) do
- if first_m.disjoint? f[m]
- raise NoError # this is fun :D
- else
- raise LLError
- end
- end
- end
- end
-
- def test_ll1?
- assert_equal false, Grammar.new(TEST_GRAMMAR_3).ll1?, 'Grammar 3'
- assert_equal false, Grammar.new(TEST_GRAMMAR_3b).ll1?, 'Grammar 3b'
- end
-
- def test_new
- assert_nothing_raised { Grammar.new '' }
- assert_nothing_raised { Grammar.new TEST_GRAMMAR_1 }
- assert_nothing_raised { Grammar.new TEST_GRAMMAR_2 }
- assert_nothing_raised { Grammar.new TEST_GRAMMAR_3 }
- assert_nothing_raised { Grammar.new TEST_GRAMMAR_1 + TEST_GRAMMAR_2 + TEST_GRAMMAR_3 }
- assert_raise(ArgumentError) { Grammar.new 'S - ?' }
- end
-end
-
-# vim:foldmethod=syntax
-
-#!/usr/bin/env ruby
-
-require 'fox12'
-
-include Fox
-
-class Window < FXMainWindow
- def initialize(app)
- super(app, app.appName + ": First Set Calculation", nil, nil, DECOR_ALL, 0, 0, 800, 600, 0, 0)
-
- # {{{ menubar
- menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
-
- filemenu = FXMenuPane.new(self)
-
- FXMenuCommand.new(filemenu, "&Start\tCtl-S\tStart the application.", nil, getApp()).connect(SEL_COMMAND, method(:start))
- FXMenuCommand.new(filemenu, "&Quit\tAlt-F4\tQuit the application.", nil, getApp(), FXApp::ID_QUIT)
- FXMenuTitle.new(menubar, "&File", nil, filemenu)
- # }}} menubar
-
- # {{{ statusbar
- @statusbar = FXStatusBar.new(self, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|STATUSBAR_WITH_DRAGCORNER)
- # }}} statusbar
-
- # {{{ window content
- horizontalsplitt = FXSplitter.new(self, SPLITTER_VERTICAL|LAYOUT_SIDE_TOP|LAYOUT_FILL)
-
-
- @productions = FXList.new(horizontalsplitt, nil, 0, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FIX_HEIGHT|LIST_SINGLESELECT)
- @productions.height = 100
-
- @result = FXTable.new(horizontalsplitt, nil, 0, LAYOUT_FILL)
- @result.height = 200
- @result.setTableSize(2, 2, false)
- @result.rowHeaderWidth = 0
-
- header = @result.columnHeader
- header.setItemText 0, 'X'
- header.setItemText 1, 'FIRST(X)'
- for item in header
- item.justification = FXHeaderItem::CENTER_X
- end
-
- @debug = FXText.new(horizontalsplitt, nil, 0, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|LAYOUT_FIX_HEIGHT)
- @debug.height = 200
-
- # }}} window content
- end
-
- def load_grammar grammar
- @tracer = FirstTracer.new(self)
- @grammar = Grammar.new grammar, @tracer
- @rules_indexes = Hash.new
- @grammar.rules.each_with_index do |rule, i|
- @productions.appendItem rule.inspect
- @rules_indexes[rule] = i
- end
- end
-
- def create
- super
- show(PLACEMENT_SCREEN)
- end
-
- def rule rule
- @productions.selectItem @rules_indexes[rule]
- sleep 0.1
- end
-
- def iterate i
- setTitle i.to_s
- sleep 0.1
- end
-
- def missing what
- @debug.appendText what + "\n"
- sleep 0.1
- end
-
- def start sender, sel, pointer
- Thread.new do
- begin
- @grammar.first
- rescue => boom
- @debug.appendText [boom.to_s, *boom.backtrace].join("\n")
- end
- end
- end
-
-end
-
-$: << 'grammar'
-require 'grammar'
-
-require 'first_tracer'
-
-app = FXApp.new("Shinobu", "cYcnus")
-
-# fenster erzeugen
-window = Window.new app
-
-unless ARGV.empty?
- grammar = File.read(ARGV.first)
-else
- grammar = <<-EOG1
-Z --> S
-S --> Sb
-S --> bAa
-A --> aSc
-A --> a
-A --> aSb
- EOG1
-end
-
-window.load_grammar grammar
-
-app.create
-app.run
-
-require 'erb'
-require 'ftools'
-require 'yaml'
-require 'redcloth'
-
-module WhyTheLuckyStiff
- class Book
- attr_accessor :author, :title, :terms, :image, :teaser,
- :chapters, :expansion_paks, :encoding, :credits
- def [] x
- @lang.fetch(x) do
- warn warning = "[not translated: '#{x}'!]"
- warning
- end
- end
- end
-
- def Book::load( file_name )
- YAML::load( File.open( file_name ) )
- end
-
- class Section
- attr_accessor :index, :header, :content
- def initialize( i, h, c )
- @index, @header, @content = i, h, RedCloth::new( c.to_s )
- end
- end
-
- class Sidebar
- attr_accessor :title, :content
- end
-
- YAML::add_domain_type( 'whytheluckystiff.net,2003', 'sidebar' ) do |taguri, val|
- YAML::object_maker( Sidebar, 'title' => val.keys.first, 'content' => RedCloth::new( val.values.first ) )
- end
- class Chapter
- attr_accessor :index, :title, :sections
- def initialize( i, t, sects )
- @index = i
- @title = t
- i = 0
- @sections = sects.collect do |s|
- if s.respond_to?( :keys )
- i += 1
- Section.new( i, s.keys.first, s.values.first )
- else
- s
- end
- end
- end
- end
-
- YAML::add_domain_type( 'whytheluckystiff.net,2003', 'book' ) do |taguri, val|
- ['chapters', 'expansion_paks'].each do |chaptype|
- i = 0
- val[chaptype].collect! do |c|
- i += 1
- Chapter::new( i, c.keys.first, c.values.first )
- end
- end
- val['teaser'].collect! do |t|
- Section::new( 1, t.keys.first, t.values.first )
- end
- val['terms'] = RedCloth::new( val['terms'] )
- YAML::object_maker( Book, val )
- end
-
- class Image
- attr_accessor :file_name
- end
-
- YAML::add_domain_type( 'whytheluckystiff.net,2003', 'img' ) do |taguri, val|
- YAML::object_maker( Image, 'file_name' => "i/" + val )
- end
-end
-
-#
-# Convert the book to HTML
-#
-if __FILE__ == $0
- unless ARGV[0]
- puts "Usage: #{$0} [/path/to/save/html]"
- exit
- end
-
- site_path = ARGV[0]
- book = WhyTheLuckyStiff::Book::load( 'poignant.yml' )
- chapter = nil
-
- # Write index page
- index_tpl = ERB::new( File.open( 'index.erb' ).read )
- File.open( File.join( site_path, 'index.html' ), 'w' ) do |out|
- out << index_tpl.result
- end
-
- book.chapters = book.chapters[0,3] if ARGV.include? '-fast'
-
- # Write chapter pages
- chapter_tpl = ERB::new( File.open( 'chapter.erb' ).read )
- book.chapters.each do |chapter|
- File.open( File.join( site_path, "chapter-#{ chapter.index }.html" ), 'w' ) do |out|
- out << chapter_tpl.result
- end
- end
- exit if ARGV.include? '-fast'
-
- # Write expansion pak pages
- expak_tpl = ERB::new( File.open( 'expansion-pak.erb' ).read )
- book.expansion_paks.each do |pak|
- File.open( File.join( site_path, "expansion-pak-#{ pak.index }.html" ), 'w' ) do |out|
- out << expak_tpl.result( binding )
- end
- end
-
- # Write printable version
- print_tpl = ERB::new( File.open( 'print.erb' ).read )
- File.open( File.join( site_path, "print.html" ), 'w' ) do |out|
- out << print_tpl.result
- end
-
- # Copy css + images into site
- copy_list = ["guide.css"] +
- Dir["i/*"].find_all { |image| image =~ /\.(gif|jpg|png)$/ }
-
- File.makedirs( File.join( site_path, "i" ) )
- copy_list.each do |copy_file|
- File.copy( copy_file, File.join( site_path, copy_file ) )
- end
-end
-
-#!/usr/bin/env ruby
-
-require 'fox'
-begin
- require 'opengl'
-rescue LoadError
- require 'fox/missingdep'
- MSG = <<EOM
- Sorry, this example depends on the OpenGL extension. Please
- check the Ruby Application Archives for an appropriate
- download site.
-EOM
- missingDependency(MSG)
-end
-
-
-include Fox
-include Math
-
-Deg2Rad = Math::PI / 180
-
-D_MAX = 6
-SQUARE_SIZE = 2.0 / D_MAX
-SQUARE_DISTANCE = 4.0 / D_MAX
-AMPLITUDE = SQUARE_SIZE
-LAMBDA = D_MAX.to_f / 2
-
-class GLTestWindow < FXMainWindow
-
- # How often our timer will fire (in milliseconds)
- TIMER_INTERVAL = 500
-
- # Rotate the boxes when a timer message is received
- def onTimeout(sender, sel, ptr)
- @angle += 10.0
-# @size = 0.5 + 0.2 * Math.cos(Deg2Rad * @angle)
- drawScene()
- @timer = getApp().addTimeout(TIMER_INTERVAL, method(:onTimeout))
- end
-
- # Rotate the boxes when a chore message is received
- def onChore(sender, sel, ptr)
- @angle += 10.0
-# @angle %= 360.0
-# @size = 0.5 + 0.2 * Math.cos(Deg2Rad * @angle)
- drawScene()
- @chore = getApp().addChore(method(:onChore))
- end
-
- # Draw the GL scene
- def drawScene
- lightPosition = [15.0, 10.0, 5.0, 1.0]
- lightAmbient = [ 0.1, 0.1, 0.1, 1.0]
- lightDiffuse = [ 0.9, 0.9, 0.9, 1.0]
- redMaterial = [ 0.0, 0.0, 1.0, 1.0]
- blueMaterial = [ 0.0, 1.0, 0.0, 1.0]
-
- width = @glcanvas.width.to_f
- height = @glcanvas.height.to_f
- aspect = width/height
-
- # Make context current
- @glcanvas.makeCurrent()
-
- GL.Viewport(0, 0, @glcanvas.width, @glcanvas.height)
-
- GL.ClearColor(1.0/256, 0.0, 5.0/256, 1.0)
- GL.Clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT)
- GL.Enable(GL::DEPTH_TEST)
-
- GL.Disable(GL::DITHER)
-
- GL.MatrixMode(GL::PROJECTION)
- GL.LoadIdentity()
- GLU.Perspective(30.0, aspect, 1.0, 100.0)
-
- GL.MatrixMode(GL::MODELVIEW)
- GL.LoadIdentity()
- GLU.LookAt(5.0, 10.0, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
-
- GL.ShadeModel(GL::SMOOTH)
- GL.Light(GL::LIGHT0, GL::POSITION, lightPosition)
- GL.Light(GL::LIGHT0, GL::AMBIENT, lightAmbient)
- GL.Light(GL::LIGHT0, GL::DIFFUSE, lightDiffuse)
- GL.Enable(GL::LIGHT0)
- GL.Enable(GL::LIGHTING)
-
- GL.Rotated(0.1*@angle, 0.0, 1.0, 0.0)
- for x in -D_MAX..D_MAX
- for y in -D_MAX..D_MAX
- h1 = (x + y - 2).abs
- h2 = (y - x + 1).abs
- GL.PushMatrix
- c = [1, 0, 0, 1]
- GL.Material(GL::FRONT, GL::AMBIENT, c)
- GL.Material(GL::FRONT, GL::DIFFUSE, c)
-
- GL.Translated(
- y * SQUARE_DISTANCE,
- AMPLITUDE * h1,
- x * SQUARE_DISTANCE
- )
-
- GL.Begin(GL::TRIANGLE_STRIP)
- GL.Normal(1.0, 0.0, 0.0)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.End
-
- GL.PopMatrix
-
- GL.PushMatrix
- c = [0, 0, 1, 1]
- GL.Material(GL::FRONT, GL::AMBIENT, c)
- GL.Material(GL::FRONT, GL::DIFFUSE, c)
-
- GL.Translated(
- y * SQUARE_DISTANCE,
- AMPLITUDE * h2,
- x * SQUARE_DISTANCE
- )
-
- GL.Begin(GL::TRIANGLE_STRIP)
- GL.Normal(1.0, 0.0, 0.0)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.End
-
- GL.PopMatrix
-
- GL.PushMatrix
- c = [0.0 + (x/10.0), 0.0 + (y/10.0), 0, 1]
- GL.Material(GL::FRONT, GL::AMBIENT, c)
- GL.Material(GL::FRONT, GL::DIFFUSE, c)
-
- GL.Translated(
- y * SQUARE_DISTANCE,
- 0,
- x * SQUARE_DISTANCE
- )
-
- GL.Begin(GL::TRIANGLE_STRIP)
- GL.Normal(1.0, 0.0, 0.0)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.End
-
- GL.PopMatrix
- end
- end
-
- # Swap if it is double-buffered
- if @glvisual.isDoubleBuffer
- @glcanvas.swapBuffers
- end
-
- # Make context non-current
- @glcanvas.makeNonCurrent
- end
-
- def initialize(app)
- # Invoke the base class initializer
- super(app, "OpenGL Test Application", nil, nil, DECOR_ALL, 0, 0, 1024, 768)
-
- # Construct the main window elements
- frame = FXHorizontalFrame.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y)
- frame.padLeft, frame.padRight = 0, 0
- frame.padTop, frame.padBottom = 0, 0
-
- # Left pane to contain the glcanvas
- glcanvasFrame = FXVerticalFrame.new(frame,
- LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
- glcanvasFrame.padLeft, glcanvasFrame.padRight = 10, 10
- glcanvasFrame.padTop, glcanvasFrame.padBottom = 10, 10
-
- # Label above the glcanvas
- FXLabel.new(glcanvasFrame, "OpenGL Canvas Frame", nil,
- JUSTIFY_CENTER_X|LAYOUT_FILL_X)
-
- # Horizontal divider line
- FXHorizontalSeparator.new(glcanvasFrame, SEPARATOR_GROOVE|LAYOUT_FILL_X)
-
- # Drawing glcanvas
- glpanel = FXVerticalFrame.new(glcanvasFrame, (FRAME_SUNKEN|FRAME_THICK|
- LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT))
- glpanel.padLeft, glpanel.padRight = 0, 0
- glpanel.padTop, glpanel.padBottom = 0, 0
-
- # A visual to draw OpenGL
- @glvisual = FXGLVisual.new(getApp(), VISUAL_DOUBLEBUFFER)
-
- # Drawing glcanvas
- @glcanvas = FXGLCanvas.new(glpanel, @glvisual, nil, 0,
- LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
- @glcanvas.connect(SEL_PAINT) {
- drawScene
- }
- @glcanvas.connect(SEL_CONFIGURE) {
- if @glcanvas.makeCurrent
- GL.Viewport(0, 0, @glcanvas.width, @glcanvas.height)
- @glcanvas.makeNonCurrent
- end
- }
-
- # Right pane for the buttons
- buttonFrame = FXVerticalFrame.new(frame, LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
- buttonFrame.padLeft, buttonFrame.padRight = 10, 10
- buttonFrame.padTop, buttonFrame.padBottom = 10, 10
-
- # Label above the buttons
- FXLabel.new(buttonFrame, "Button Frame", nil,
- JUSTIFY_CENTER_X|LAYOUT_FILL_X)
-
- # Horizontal divider line
- FXHorizontalSeparator.new(buttonFrame, SEPARATOR_RIDGE|LAYOUT_FILL_X)
-
- # Spin according to timer
- spinTimerBtn = FXButton.new(buttonFrame,
- "Spin &Timer\tSpin using interval timers\nNote the app
- blocks until the interal has elapsed...", nil,
- nil, 0, FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
- spinTimerBtn.padLeft, spinTimerBtn.padRight = 10, 10
- spinTimerBtn.padTop, spinTimerBtn.padBottom = 5, 5
- spinTimerBtn.connect(SEL_COMMAND) {
- @spinning = true
- @timer = getApp().addTimeout(TIMER_INTERVAL, method(:onTimeout))
- }
- spinTimerBtn.connect(SEL_UPDATE) { |sender, sel, ptr|
- @spinning ? sender.disable : sender.enable
- }
-
- # Spin according to chore
- spinChoreBtn = FXButton.new(buttonFrame,
- "Spin &Chore\tSpin as fast as possible using chores\nNote even though the
- app is very responsive, it never blocks;\nthere is always something to
- do...", nil,
- nil, 0, FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
- spinChoreBtn.padLeft, spinChoreBtn.padRight = 10, 10
- spinChoreBtn.padTop, spinChoreBtn.padBottom = 5, 5
- spinChoreBtn.connect(SEL_COMMAND) {
- @spinning = true
- @chore = getApp().addChore(method(:onChore))
- }
- spinChoreBtn.connect(SEL_UPDATE) { |sender, sel, ptr|
- @spinning ? sender.disable : sender.enable
- }
-
- # Stop spinning
- stopBtn = FXButton.new(buttonFrame,
- "&Stop Spin\tStop this mad spinning, I'm getting dizzy", nil,
- nil, 0, FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
- stopBtn.padLeft, stopBtn.padRight = 10, 10
- stopBtn.padTop, stopBtn.padBottom = 5, 5
- stopBtn.connect(SEL_COMMAND) {
- @spinning = false
- if @timer
- getApp().removeTimeout(@timer)
- @timer = nil
- end
- if @chore
- getApp().removeChore(@chore)
- @chore = nil
- end
- }
- stopBtn.connect(SEL_UPDATE) { |sender, sel, ptr|
- @spinning ? sender.enable : sender.disable
- }
-
- # Exit button
- exitBtn = FXButton.new(buttonFrame, "&Exit\tExit the application", nil,
- getApp(), FXApp::ID_QUIT,
- FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
- exitBtn.padLeft, exitBtn.padRight = 10, 10
- exitBtn.padTop, exitBtn.padBottom = 5, 5
-
- # Make a tooltip
- FXTooltip.new(getApp())
-
- # Initialize private variables
- @spinning = false
- @chore = nil
- @timer = nil
- @angle = 0.0
- @size = 0.5
- end
-
- # Create and initialize
- def create
- super
- show(PLACEMENT_SCREEN)
- end
-end
-
-if __FILE__ == $0
- # Construct the application
- application = FXApp.new("GLTest", "FoxTest")
-
- # To ensure that the chores-based spin will run as fast as possible,
- # we can disable the chore in FXRuby's event loop that tries to schedule
- # other threads. This is OK for this program because there aren't any
- # other Ruby threads running.
-
- #application.disableThreads
-
- # Construct the main window
- GLTestWindow.new(application)
-
- # Create the app's windows
- application.create
-
- # Run the application
- application.run
-end
-
-class Facelet
- attr_accessor :color
- def initialize(color)
- @color = color
- end
-
- def to_s
- @color
- end
-end
-
-class Edge
- attr_accessor :facelets, :colors
-
- def initialize(facelets)
- @facelets = facelets
- @colors = @facelets.map { |fl| fl.color }
- end
-
- def apply(edge)
- @facelets.each_with_index { |fl, i|
- fl.color = edge.colors[i]
- }
- end
-
- def inspect
- "\n%s %s\n%s %s %s" % facelets
- end
-end
-
-class Side
- attr_reader :num, :facelets
- attr_accessor :sides
-
- def initialize(num)
- @num = num
- @sides = []
- @facelets = []
- @fl_by_side = {}
- end
-
- # facelets & sides
- # 0
- # 0 1 2
- # 3 3 4 5 1
- # 6 7 8
- # 2
-
- def facelets=(facelets)
- @facelets = facelets.map { |c| Facelet.new(c) }
- init_facelet 0, 3,0
- init_facelet 1, 0
- init_facelet 2, 0,1
- init_facelet 3, 3
- init_facelet 5, 1
- init_facelet 6, 2,3
- init_facelet 7, 2
- init_facelet 8, 1,2
- end
-
- def <=>(side)
- self.num <=> side.num
- end
-
- def init_facelet(pos, *side_nums)
- sides = side_nums.map { |num| @sides[num] }.sort
- @fl_by_side[sides] = pos
- end
-
- def []=(color, *sides)
- @facelets[@fl_by_side[sides.sort]].color = color
- end
-
- def values_at(*sides)
- sides.map { |sides| @facelets[@fl_by_side[sides.sort]] }
- end
-
- def inspect(range=nil)
- if range
- @facelets.values_at(*(range.to_a)).join(' ')
- else
- <<-EOS.gsub(/\d/) { |num| @facelets[num.to_i] }.gsub(/[ABCD]/) { |side| @sides[side[0]-?A].num.to_s }
- A
- 0 1 2
- D 3 4 5 B
- 6 7 8
- C
- EOS
- end
- end
-
- def get_edge(side)
- trio = (-1..1).map { |x| (side + x) % 4 }
- prev_side, this_side, next_side = @sides.values_at(*trio)
- e = Edge.new(
- self .values_at( [this_side], [this_side, next_side] ) +
- this_side.values_at( [self, prev_side], [self ], [self, next_side] )
- )
- #puts 'Edge created for side %d: ' % side + e.inspect
- e
- end
-
- def turn(dir)
- #p 'turn side %d in %d' % [num, dir]
- edges = (0..3).map { |n| get_edge n }
- for i in 0..3
- edges[i].apply edges[(i-dir) % 4]
- end
- end
-end
-
-class Cube
- def initialize
- @sides = []
- %w(left front right back top bottom).each_with_index { |side, i|
- eval("@sides[#{i}] = @#{side} = Side.new(#{i})")
- }
- @left.sides = [@top, @front, @bottom, @back]
- @front.sides = [@top, @right, @bottom, @left]
- @right.sides = [@top, @back, @bottom, @front]
- @back.sides = [@top, @left, @bottom, @right]
- @top.sides = [@back, @right, @front, @left]
- @bottom.sides = [@front, @right, @back, @left]
- end
-
- def read_facelets(fs)
- pattern = Regexp.new(<<-EOP.gsub(/\w/, '\w').gsub(/\s+/, '\s*'))
- (w w w)
- (w w w)
- (w w w)
-(r r r) (g g g) (b b b) (o o o)
-(r r r) (g g g) (b b b) (o o o)
-(r r r) (g g g) (b b b) (o o o)
- (y y y)
- (y y y)
- (y y y)
- EOP
- md = pattern.match(fs).to_a
-
- @top.facelets = parse_facelets(md.values_at(1,2,3))
- @left.facelets = parse_facelets(md.values_at(4,8,12))
- @front.facelets = parse_facelets(md.values_at(5,9,13))
- @right.facelets = parse_facelets(md.values_at(6,10,14))
- @back.facelets = parse_facelets(md.values_at(7,11,15))
- @bottom.facelets = parse_facelets(md.values_at(16,17,18))
- end
-
- def turn(side, dir)
- #p 'turn %d in %d' % [side, dir]
- @sides[side].turn(dir)
- #puts inspect
- end
-
- def inspect
- <<-EOF.gsub(/(\d):(\d)-(\d)/) { @sides[$1.to_i].inspect(Range.new($2.to_i, $3.to_i)) }
- 4:0-2
- 4:3-5
- 4:6-8
-0:0-2 1:0-2 2:0-2 3:0-2
-0:3-5 1:3-5 2:3-5 3:3-5
-0:6-8 1:6-8 2:6-8 3:6-8
- 5:0-2
- 5:3-5
- 5:6-8
- EOF
- end
-
-private
- def parse_facelets(rows)
- rows.join.delete(' ').split(//)
- end
-end
-
-#$stdin = DATA
-
-gets.to_i.times do |i|
- puts "Scenario ##{i+1}:"
- fs = ''
- 9.times { fs << gets }
- cube = Cube.new
- cube.read_facelets fs
- gets.to_i.times do |t|
- side, dir = gets.split.map {|s| s.to_i}
- cube.turn(side, dir)
- end
- puts cube.inspect
- puts
-end
-
-# 2004 by murphy <korny@cYcnus.de>
-# GPL
-class Scenario
- class TimePoint
- attr_reader :data
- def initialize *data
- @data = data
- end
-
- def [] i
- @data[i] or 0
- end
-
- include Comparable
- def <=> tp
- r = 0
- [@data.size, tp.data.size].max.times do |i|
- r = self[i] <=> tp[i]
- return r if r.nonzero?
- end
- 0
- end
-
- def - tp
- r = []
- [@data.size, tp.data.size].max.times do |i|
- r << self[i] - tp[i]
- end
- r
- end
-
- def inspect
- # 01/01/1800 00:00:00
- '%02d/%02d/%04d %02d:%02d:%02d' % @data.values_at(1, 2, 0, 3, 4, 5)
- end
- end
-
- ONE_HOUR = TimePoint.new 0, 0, 0, 1, 0, 0
-
- APPOINTMENT_PATTERN = /
- ( \d{4} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s
- ( \d{4} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} )
- /x
-
- def initialize io
- @team_size = io.gets.to_i
- @data = [ [TimePoint.new(1800, 01, 01, 00, 00, 00), @team_size] ]
- @team_size.times do # each team member
- io.gets.to_i.times do # each appointment
- m = APPOINTMENT_PATTERN.match io.gets
- @data << [TimePoint.new(*m.captures[0,6].map { |x| x.to_i }), -1]
- @data << [TimePoint.new(*m.captures[6,6].map { |x| x.to_i }), +1]
- end
- end
- @data << [TimePoint.new(2200, 01, 01, 00, 00, 00), -@team_size]
- end
-
- def print_time_plan
- n = 0
- appointment = nil
- no_appointment = true
- @data.sort_by { |x| x[0] }.each do |x|
- tp, action = *x
- n += action
- # at any time during the meeting, at least two team members need to be there
- # and at most one team member is allowed to be absent
- if n >= 2 and (@team_size - n) <= 1
- appointment ||= tp
- else
- if appointment
- # the meeting should be at least one hour in length
- if TimePoint.new(*(tp - appointment)) >= ONE_HOUR
- puts 'appointment possible from %p to %p' % [appointment, tp]
- no_appointment = false
- end
- appointment = false
- end
- end
- end
- puts 'no appointment possible' if no_appointment
- end
-end
-
-# read the data
-DATA.gets.to_i.times do |si| # each scenario
- puts 'Scenario #%d:' % (si + 1)
- sc = Scenario.new DATA
- sc.print_time_plan
- puts
-end
-
-#__END__
-2
-3
-3
-2002 06 28 15 00 00 2002 06 28 18 00 00 TUD Contest Practice Session
-2002 06 29 10 00 00 2002 06 29 15 00 00 TUD Contest
-2002 11 15 15 00 00 2002 11 17 23 00 00 NWERC Delft
-4
-2002 06 25 13 30 00 2002 06 25 15 30 00 FIFA World Cup Semifinal I
-2002 06 26 13 30 00 2002 06 26 15 30 00 FIFA World Cup Semifinal II
-2002 06 29 13 00 00 2002 06 29 15 00 00 FIFA World Cup Third Place
-2002 06 30 13 00 00 2002 06 30 15 00 00 FIFA World Cup Final
-1
-2002 06 01 00 00 00 2002 06 29 18 00 00 Preparation of Problem Set
-2
-1
-1800 01 01 00 00 00 2200 01 01 00 00 00 Solving Problem 8
-0
-
-require 'token_consts'
-require 'symbol'
-require 'ctype'
-require 'error'
-
-class Fixnum
- # Treat char as a digit and return it's value as Fixnum.
- # Returns nonsense for non-digits.
- # Examples:
- # <code>
- # RUBY_VERSION[0].digit == '1.8.2'[0].digit == 1
- # </code>
- #
- # <code>
- # ?6.digit == 6
- # </code>
- #
- # <code>
- # ?A.digit == 17
- # </code>
- def digit
- self - ?0
- end
-end
-
-##
-# Stellt einen einfachen Scanner für die lexikalische Analyse der Sprache Pas-0 dar.
-#
-# @author Andreas Kunert
-# Ruby port by murphy
-class Scanner
-
- include TokenConsts
-
- attr_reader :line, :pos
-
- # To allow Scanner.new without parameters.
- DUMMY_INPUT = 'dummy file'
- def DUMMY_INPUT.getc
- nil
- end
-
- ##
- # Erzeugt einen Scanner, der als Eingabe das übergebene IO benutzt.
- def initialize input = DUMMY_INPUT
- @line = 1
- @pos = 0
-
- begin
- @input = input
- @next_char = @input.getc
- rescue IOError # TODO show the reason!
- Error.ioError
- raise
- end
- end
-
- ##
- # Liest das n
- def read_next_char
- begin
- @pos += 1
- @current_char = @next_char
- @next_char = @input.getc
- rescue IOError
- Error.ioError
- raise
- end
- end
-
- ##
- # Sucht das nächste Symbol, identifiziert es, instantiiert ein entsprechendes
- # PascalSymbol-Objekt und gibt es zurück.
- # @see Symbol
- # @return das gefundene Symbol als PascalSymbol-Objekt
- def get_symbol
- current_symbol = nil
- until current_symbol
- read_next_char
-
- if @current_char.alpha?
- identifier = @current_char.chr
- while @next_char.alpha? or @next_char.digit?
- identifier << @next_char
- read_next_char
- end
- current_symbol = handle_identifier(identifier.upcase)
- elsif @current_char.digit?
- current_symbol = number
- else
- case @current_char
- when ?\s
- # ignore
- when ?\n
- new_line
- when nil
- current_symbol = PascalSymbol.new EOP
- when ?{
- comment
-
- when ?:
- if @next_char == ?=
- read_next_char
- current_symbol = PascalSymbol.new BECOMES
- else
- current_symbol = PascalSymbol.new COLON
- end
-
- when ?<
- if (@next_char == ?=)
- read_next_char
- current_symbol = PascalSymbol.new LEQSY
- elsif (@next_char == ?>)
- read_next_char
- current_symbol = PascalSymbol.new NEQSY
- else
- current_symbol = PascalSymbol.new LSSSY
- end
-
- when ?>
- if (@next_char == ?=)
- read_next_char
- current_symbol = PascalSymbol.new GEQSY
- else
- current_symbol = PascalSymbol.new GRTSY
- end
-
- when ?. then current_symbol = PascalSymbol.new PERIOD
- when ?( then current_symbol = PascalSymbol.new LPARENT
- when ?, then current_symbol = PascalSymbol.new COMMA
- when ?* then current_symbol = PascalSymbol.new TIMES
- when ?/ then current_symbol = PascalSymbol.new SLASH
- when ?+ then current_symbol = PascalSymbol.new PLUS
- when ?- then current_symbol = PascalSymbol.new MINUS
- when ?= then current_symbol = PascalSymbol.new EQLSY
- when ?) then current_symbol = PascalSymbol.new RPARENT
- when ?; then current_symbol = PascalSymbol.new SEMICOLON
- else
- Error.error(100, @line, @pos) if @current_char > ?\s
- end
- end
- end
- current_symbol
- end
-
-private
- ##
- # Versucht, in dem gegebenen String ein Schlüsselwort zu erkennen.
- # Sollte dabei ein Keyword gefunden werden, so gibt er ein PascalSymbol-Objekt zurück, das
- # das entsprechende Keyword repräsentiert. Ansonsten besteht die Rückgabe aus
- # einem SymbolIdent-Objekt (abgeleitet von PascalSymbol), das den String 1:1 enthält
- # @see symbol
- # @return falls Keyword gefunden, zugehöriges PascalSymbol, sonst SymbolIdent
- def handle_identifier identifier
- if sym = KEYWORD_SYMBOLS[identifier]
- PascalSymbol.new sym
- else
- SymbolIdent.new identifier
- end
- end
-
- MAXINT = 2**31 - 1
- MAXINT_DIV_10 = MAXINT / 10
- MAXINT_MOD_10 = MAXINT % 10
- ##
- # Versucht, aus dem gegebenen Zeichen und den folgenden eine Zahl zusammenzusetzen.
- # Dabei wird der relativ intuitive Algorithmus benutzt, die endgültige Zahl bei
- # jeder weiteren Ziffer mit 10 zu multiplizieren und diese dann mit der Ziffer zu
- # addieren. Sonderfälle bestehen dann nur noch in der Behandlung von reellen Zahlen.
- # <BR>
- # Treten dabei kein Punkt oder ein E auf, so gibt diese Methode ein SymbolIntCon-Objekt
- # zurück, ansonsten (reelle Zahl) ein SymbolRealCon-Objekt. Beide Symbole enthalten
- # jeweils die Zahlwerte.
- # <BR>
- # Anmerkung: Diese Funktion ist mit Hilfe der Java/Ruby-API deutlich leichter zu realisieren.
- # Sie wurde dennoch so implementiert, um den Algorithmus zu demonstrieren
- # @see symbol
- # @return SymbolIntcon- oder SymbolRealcon-Objekt, das den Zahlwert enthält
- def number
- is_integer = true
- integer_too_long = false
- exponent = 0
- exp_counter = -1
- exp_sign = 1
-
- integer_mantisse = @current_char.digit
-
- while (@next_char.digit? and integer_mantisse < MAXINT_DIV_10) or
- (integer_mantisse == MAXINT_DIV_10 and @next_char.digit <= MAXINT_MOD_10)
- integer_mantisse *= 10
- integer_mantisse += @next_char.digit
- read_next_char
- end
-
- real_mantisse = integer_mantisse
-
- while @next_char.digit?
- integer_too_long = true
- real_mantisse *= 10
- real_mantisse += @next_char.digit
- read_next_char
- end
- if @next_char == ?.
- read_next_char
- is_integer = false
- unless @next_char.digit?
- Error.error 101, @line, @pos
- end
- while @next_char.digit?
- real_mantisse += @next_char.digit * (10 ** exp_counter)
- read_next_char
- exp_counter -= 1
- end
- end
- if @next_char == ?E
- is_integer = false
- read_next_char
- if @next_char == ?-
- exp_sign = -1
- read_next_char
- end
- unless @next_char.digit?
- Error.error 101, @line, @pos
- end
- while @next_char.digit?
- exponent *= 10
- exponent += @next_char.digit
- read_next_char
- end
- end
-
- if is_integer
- if integer_too_long
- Error.error 102, @line, @pos
- end
- SymbolIntcon.new integer_mantisse
- else
- SymbolRealcon.new real_mantisse * (10 ** (exp_sign * exponent))
- end
- end
-
- ##
- # Sorgt für ein Überlesen von Kommentaren.
- # Es werden einfach alle Zeichen bis zu einer schließenden Klammer eingelesen
- # und verworfen.
- def comment
- while @current_char != ?}
- forbid_eop
- new_line if @current_char == ?\n
- read_next_char
- end
- end
-
- def new_line
- @line += 1
- @pos = 0
- end
-
- def forbid_eop
- if eop?
- Error.error 103, @line, @pos
- end
- exit
- end
-
- def eop?
- @current_char.nil?
- end
-end
-
-##
-# Läßt ein Testprogramm ablaufen.
-# Dieses erzeugt sich ein Scanner-Objekt und ruft an diesem kontinuierlich bis zum Dateiende
-# get_symbol auf.
-if $0 == __FILE__
- scan = Scanner.new(File.new(ARGV[0] || 'test.pas'))
- loop do
- c = scan.get_symbol
- puts c
- break if c.typ == TokenConsts::EOP
- end
-end
-# -*- ruby -*-
-
-# Local variables:
-# indent-tabs-mode: nil
-# ruby-indent-level: 4
-# End:
-
-# @@PLEAC@@_NAME
-# @@SKIP@@ Ruby
-
-# @@PLEAC@@_WEB
-# @@SKIP@@ http://www.ruby-lang.org
-
-
-# @@PLEAC@@_1.0
-string = '\n' # two characters, \ and an n
-string = 'Jon \'Maddog\' Orwant' # literal single quotes
-
-string = "\n" # a "newline" character
-string = "Jon \"Maddog\" Orwant" # literal double quotes
-
-string = %q/Jon 'Maddog' Orwant/ # literal single quotes
-
-string = %q[Jon 'Maddog' Orwant] # literal single quotes
-string = %q{Jon 'Maddog' Orwant} # literal single quotes
-string = %q(Jon 'Maddog' Orwant) # literal single quotes
-string = %q<Jon 'Maddog' Orwant> # literal single quotes
-
-a = <<"EOF"
-This is a multiline here document
-terminated by EOF on a line by itself
-EOF
-
-
-# @@PLEAC@@_1.1
-value = string[offset,count]
-value = string[offset..-1]
-
-string[offset,count] = newstring
-string[offset..-1] = newtail
-
-# in Ruby we can also specify intervals by their two offsets
-value = string[offset..offs2]
-string[offset..offs2] = newstring
-
-leading, s1, s2, trailing = data.unpack("A5 x3 A8 A8 A*")
-
-fivers = string.unpack("A5" * (string.length/5))
-
-chars = string.unpack("A1" * string.length)
-
-string = "This is what you have"
-# +012345678901234567890 Indexing forwards (left to right)
-# 109876543210987654321- Indexing backwards (right to left)
-# note that 0 means 10 or 20, etc. above
-
-first = string[0, 1] # "T"
-start = string[5, 2] # "is"
-rest = string[13..-1] # "you have"
-last = string[-1, 1] # "e"
-end_ = string[-4..-1] # "have"
-piece = string[-8, 3] # "you"
-
-string[5, 2] = "wasn't" # change "is" to "wasn't"
-string[-12..-1] = "ondrous" # "This wasn't wondrous"
-string[0, 1] = "" # delete first character
-string[-10..-1] = "" # delete last 10 characters
-
-if string[-10..-1] =~ /pattern/
- puts "Pattern matches in last 10 characters"
-end
-
-string[0, 5].gsub!(/is/, 'at')
-
-a = "make a hat"
-a[0, 1], a[-1, 1] = a[-1, 1], a[0, 1]
-
-a = "To be or not to be"
-b = a.unpack("x6 A6")
-
-b, c = a.unpack("x6 A2 X5 A2")
-puts "#{b}\n#{c}\n"
-
-def cut2fmt(*args)
- template = ''
- lastpos = 1
- for place in args
- template += "A" + (place - lastpos).to_s + " "
- lastpos = place
- end
- template += "A*"
- return template
-end
-
-fmt = cut2fmt(8, 14, 20, 26, 30)
-
-
-# @@PLEAC@@_1.2
-# careful! "b is true" doesn't mean "b != 0" (0 is true in Ruby)
-# thus no problem of "defined" later since only nil is false
-# the following sets to `c' if `b' is nil or false
-a = b || c
-
-# if you need Perl's behaviour (setting to `c' if `b' is 0) the most
-# effective way is to use Numeric#nonzero? (thanks to Dave Thomas!)
-a = b.nonzero? || c
-
-# you will still want to use defined? in order to test
-# for scope existence of a given object
-a = defined?(b) ? b : c
-
-dir = ARGV.shift || "/tmp"
-
-
-# @@PLEAC@@_1.3
-v1, v2 = v2, v1
-
-alpha, beta, production = %w(January March August)
-alpha, beta, production = beta, production, alpha
-
-
-# @@PLEAC@@_1.4
-num = char[0]
-char = num.chr
-
-# Ruby also supports having a char from character constant
-num = ?r
-
-char = sprintf("%c", num)
-printf("Number %d is character %c\n", num, num)
-
-ascii = string.unpack("C*")
-string = ascii.pack("C*")
-
-hal = "HAL"
-ascii = hal.unpack("C*")
-# We can't use Array#each since we can't mutate a Fixnum
-ascii.collect! { |i|
- i + 1 # add one to each ASCII value
-}
-ibm = ascii.pack("C*")
-puts ibm
-
-
-# @@PLEAC@@_1.5
-array = string.split('')
-
-array = string.unpack("C*")
-
-string.scan(/./) { |b|
- # do something with b
-}
-
-string = "an apple a day"
-print "unique chars are: ", string.split('').uniq.sort, "\n"
-
-sum = 0
-for ascval in string.unpack("C*") # or use Array#each for a pure OO style :)
- sum += ascval
-end
-puts "sum is #{sum & 0xffffffff}" # since Ruby will go Bignum if necessary
-
-# @@INCLUDE@@ include/ruby/slowcat.rb
-
-
-# @@PLEAC@@_1.6
-revbytes = string.reverse
-
-revwords = string.split(" ").reverse.join(" ")
-
-revwords = string.split(/(\s+)/).reverse.join
-
-# using the fact that IO is Enumerable, you can directly "select" it
-long_palindromes = File.open("/usr/share/dict/words").
- select { |w| w.chomp!; w.reverse == w && w.length > 5 }
-
-
-# @@PLEAC@@_1.7
-while string.sub!("\t+") { ' ' * ($&.length * 8 - $`.length % 8) }
-end
-
-
-# @@PLEAC@@_1.8
-'You owe #{debt} to me'.gsub(/\#{(\w+)}/) { eval($1) }
-
-rows, cols = 24, 80
-text = %q(I am #{rows} high and #{cols} long)
-text.gsub!(/\#{(\w+)}/) { eval("#{$1}") }
-puts text
-
-'I am 17 years old'.gsub(/\d+/) { 2 * $&.to_i }
-
-
-# @@PLEAC@@_1.9
-e = "bo peep".upcase
-e.downcase!
-e.capitalize!
-
-"thIS is a loNG liNE".gsub!(/\w+/) { $&.capitalize }
-
-
-# @@PLEAC@@_1.10
-"I have #{n+1} guanacos."
-print "I have ", n+1, " guanacos."
-
-
-# @@PLEAC@@_1.11
-var = <<'EOF'.gsub(/^\s+/, '')
- your text
- goes here
-EOF
-
-
-# @@PLEAC@@_1.12
-string = "Folding and splicing is the work of an editor,\n"+
- "not a mere collection of silicon\n"+
- "and\n"+
- "mobile electrons!"
-
-def wrap(str, max_size)
- all = []
- line = ''
- for l in str.split
- if (line+l).length >= max_size
- all.push(line)
- line = ''
- end
- line += line == '' ? l : ' ' + l
- end
- all.push(line).join("\n")
-end
-
-print wrap(string, 20)
-#=> Folding and
-#=> splicing is the
-#=> work of an editor,
-#=> not a mere
-#=> collection of
-#=> silicon and mobile
-#=> electrons!
-
-
-# @@PLEAC@@_1.13
-string = %q(Mom said, "Don't do that.")
-string.gsub(/['"]/) { '\\'+$& }
-string.gsub(/['"]/, '\&\&')
-string.gsub(/[^A-Z]/) { '\\'+$& }
-"is a test!".gsub(/\W/) { '\\'+$& } # no function like quotemeta?
-
-
-# @@PLEAC@@_1.14
-string.strip!
-
-
-# @@PLEAC@@_1.15
-def parse_csv(text)
- new = text.scan(/"([^\"\\]*(?:\\.[^\"\\]*)*)",?|([^,]+),?|,/)
- new << nil if text[-1] == ?,
- new.flatten.compact
-end
-
-line = %q<XYZZY,"","O'Reilly, Inc","Wall, Larry","a \"glug\" bit,",5,"Error, Core Dumped">
-fields = parse_csv(line)
-fields.each_with_index { |v,i|
- print "#{i} : #{v}\n";
-}
-
-
-# @@PLEAC@@_1.16
-# Use the soundex.rb Library from Michael Neumann.
-# http://www.s-direktnet.de/homepages/neumann/rb_prgs/Soundex.rb
-require 'Soundex'
-
-code = Text::Soundex.soundex(string)
-codes = Text::Soundex.soundex(array)
-
-# substitution function for getpwent():
-# returns an array of user entries,
-# each entry contains the username and the full name
-def login_names
- result = []
- File.open("/etc/passwd") { |file|
- file.each_line { |line|
- next if line.match(/^#/)
- cols = line.split(":")
- result.push([cols[0], cols[4]])
- }
- }
- result
-end
-
-puts "Lookup user: "
-user = STDIN.gets
-user.chomp!
-exit unless user
-name_code = Text::Soundex.soundex(user)
-
-splitter = Regexp.new('(\w+)[^,]*\b(\w+)')
-for username, fullname in login_names do
- firstname, lastname = splitter.match(fullname)[1,2]
- if name_code == Text::Soundex.soundex(username)
- || name_code == Text::Soundex.soundex(firstname)
- || name_code == Text::Soundex.soundex(lastname)
- then
- puts "#{username}: #{firstname} #{lastname}"
- end
-end
-
-
-# @@PLEAC@@_1.17
-# @@INCLUDE@@ include/ruby/fixstyle.rb
-
-
-# @@PLEAC@@_1.18
-# @@INCLUDE@@ include/ruby/psgrep.rb
-
-
-# @@PLEAC@@_2.1
-# Matz tells that you can use Integer() for strict checked conversion.
-Integer("abc")
-#=> `Integer': invalid value for Integer: "abc" (ArgumentError)
-Integer("567")
-#=> 567
-
-# You may use Float() for floating point stuff
-Integer("56.7")
-#=> `Integer': invalid value for Integer: "56.7" (ArgumentError)
-Float("56.7")
-#=> 56.7
-
-# You may also use a regexp for that
-if string =~ /^[+-]?\d+$/
- p 'is an integer'
-else
- p 'is not'
-end
-
-if string =~ /^-?(?:\d+(?:\.\d*)?|\.\d+)$/
- p 'is a decimal number'
-else
- p 'is not'
-end
-
-
-# @@PLEAC@@_2.2
-# equal(num1, num2, accuracy) : returns true if num1 and num2 are
-# equal to accuracy number of decimal places
-def equal(i, j, a)
- sprintf("%.#{a}g", i) == sprintf("%.#{a}g", j)
-end
-
-wage = 536 # $5.36/hour
-week = 40 * wage # $214.40
-printf("One week's wage is: \$%.2f\n", week/100.0)
-
-
-# @@PLEAC@@_2.3
-num.round # rounds to integer
-
-a = 0.255
-b = sprintf("%.2f", a)
-print "Unrounded: #{a}\nRounded: #{b}\n"
-printf "Unrounded: #{a}\nRounded: %.2f\n", a
-
-print "number\tint\tfloor\tceil\n"
-a = [ 3.3 , 3.5 , 3.7, -3.3 ]
-for n in a
- printf("% .1f\t% .1f\t% .1f\t% .1f\n", # at least I don't fake my output :)
- n, n.to_i, n.floor, n.ceil)
-end
-
-
-# @@PLEAC@@_2.4
-def dec2bin(n)
- [n].pack("N").unpack("B32")[0].sub(/^0+(?=\d)/, '')
-end
-
-def bin2dec(n)
- [("0"*32+n.to_s)[-32..-1]].pack("B32").unpack("N")[0]
-end
-
-
-# @@PLEAC@@_2.5
-for i in x .. y
- # i is set to every integer from x to y, inclusive
-end
-
-x.step(y,7) { |i|
- # i is set to every integer from x to y, stepsize = 7
-}
-
-print "Infancy is: "
-(0..2).each { |i|
- print i, " "
-}
-print "\n"
-
-
-# @@PLEAC@@_2.6
-# We can add conversion methods to the Integer class,
-# this makes a roman number just a representation for normal numbers.
-class Integer
-
- @@romanlist = [["M", 1000],
- ["CM", 900],
- ["D", 500],
- ["CD", 400],
- ["C", 100],
- ["XC", 90],
- ["L", 50],
- ["XL", 40],
- ["X", 10],
- ["IX", 9],
- ["V", 5],
- ["IV", 4],
- ["I", 1]]
-
- def to_roman
- remains = self
- roman = ""
- for sym, num in @@romanlist
- while remains >= num
- remains -= num
- roman << sym
- end
- end
- roman
- end
-
- def Integer.from_roman(roman)
- ustr = roman.upcase
- sum = 0
- for entry in @@romanlist
- sym, num = entry[0], entry[1]
- while sym == ustr[0, sym.length]
- sum += num
- ustr.slice!(0, sym.length)
- end
- end
- sum
- end
-
-end
-
-
-roman_fifteen = 15.to_roman
-puts "Roman for fifteen is #{roman_fifteen}"
-i = Integer.from_roman(roman_fifteen)
-puts "Converted back, #{roman_fifteen} is #{i}"
-
-# check
-for i in (1..3900)
- r = i.to_roman
- j = Integer.from_roman(r)
- if i != j
- puts "error: #{i} : #{r} - #{j}"
- end
-end
-
-
-# @@PLEAC@@_2.7
-random = rand(y-x+1)+x
-
-chars = ["A".."Z","a".."z","0".."9"].collect { |r| r.to_a }.join + %q(!@$%^&*)
-password = (1..8).collect { chars[rand(chars.size)] }.pack("C*")
-
-
-# @@PLEAC@@_2.8
-srand # uses a combination of the time, the process id, and a sequence number
-srand(val) # for repeatable behaviour
-
-
-# @@PLEAC@@_2.9
-# from the randomr lib:
-# http://raa.ruby-lang.org/project/randomr/
-----> http://raa.ruby-lang.org/project/randomr/
-
-require 'random/mersenne_twister'
-mers = Random::MersenneTwister.new 123456789
-puts mers.rand(0) # 0.550321932544541
-puts mers.rand(10) # 2
-
-# using online sources of random data via the realrand package:
-# http://raa.ruby-lang.org/project/realrand/
-# **Note**
-# The following online services are used in this package:
-# http://www.random.org - source: atmospheric noise
-# http://www.fourmilab.ch/hotbits - source: radioactive decay timings
-# http://random.hd.org - source: entropy from local and network noise
-# Please visit the sites and respect the rules of each service.
-
-require 'random/online'
-
-generator1 = Random::RandomOrg.new
-puts generator1.randbyte(5).join(",")
-puts generator1.randnum(10, 1, 6).join(",") # Roll dice 10 times.
-
-generator2 = Random::FourmiLab.new
-puts generator2.randbyte(5).join(",")
-# randnum is not supported.
-
-generator3 = Random::EntropyPool.new
-puts generator3.randbyte(5).join(",")
-# randnum is not supported.
-
-
-# @@PLEAC@@_2.10
-def gaussian_rand
- begin
- u1 = 2 * rand() - 1
- u2 = 2 * rand() - 1
- w = u1*u1 + u2*u2
- end while (w >= 1)
- w = Math.sqrt((-2*Math.log(w))/w)
- [ u2*w, u1*w ]
-end
-
-mean = 25
-sdev = 2
-salary = gaussian_rand[0] * sdev + mean
-printf("You have been hired at \$%.2f\n", salary)
-
-
-# @@PLEAC@@_2.11
-def deg2rad(d)
- (d/180.0)*Math::PI
-end
-
-def rad2deg(r)
- (r/Math::PI)*180
-end
-
-
-# @@PLEAC@@_2.12
-sin_val = Math.sin(angle)
-cos_val = Math.cos(angle)
-tan_val = Math.tan(angle)
-
-# AFAIK Ruby's Math module doesn't provide acos/asin
-# While we're at it, let's also define missing hyperbolic functions
-module Math
- def Math.asin(x)
- atan2(x, sqrt(1 - x**2))
- end
- def Math.acos(x)
- atan2(sqrt(1 - x**2), x)
- end
- def Math.atan(x)
- atan2(x, 1)
- end
- def Math.sinh(x)
- (exp(x) - exp(-x)) / 2
- end
- def Math.cosh(x)
- (exp(x) + exp(-x)) / 2
- end
- def Math.tanh(x)
- sinh(x) / cosh(x)
- end
-end
-
-# The support for Complex numbers is not built-in
-y = Math.acos(3.7)
-#=> in `sqrt': square root for negative number (ArgumentError)
-
-# There is an implementation of Complex numbers in 'complex.rb' in current
-# Ruby distro, but it doesn't support atan2 with complex args, so it doesn't
-# solve this problem.
-
-
-# @@PLEAC@@_2.13
-log_e = Math.log(val)
-log_10 = Math.log10(val)
-
-def log_base(base, val)
- Math.log(val)/Math.log(base)
-end
-
-answer = log_base(10, 10_000)
-puts "log10(10,000) = #{answer}"
-
-
-# @@PLEAC@@_2.14
-require 'matrix.rb'
-
-a = Matrix[[3, 2, 3], [5, 9, 8]]
-b = Matrix[[4, 7], [9, 3], [8, 1]]
-c = a * b
-
-a.row_size
-a.column_size
-
-c.det
-a.transpose
-
-
-# @@PLEAC@@_2.15
-require 'complex.rb'
-require 'rational.rb'
-
-a = Complex(3, 5) # 3 + 5i
-b = Complex(2, -2) # 2 - 2i
-puts "c = #{a*b}"
-
-c = a * b
-d = 3 + 4*Complex::I
-
-printf "sqrt(#{d}) = %s\n", Math.sqrt(d)
-
-
-# @@PLEAC@@_2.16
-number = hexadecimal.hex
-number = octal.oct
-
-print "Gimme a number in decimal, octal, or hex: "
-num = gets.chomp
-exit unless defined?(num)
-num = num.oct if num =~ /^0/ # does both oct and hex
-printf "%d %x %o\n", num, num, num
-
-print "Enter file permission in octal: "
-permissions = gets.chomp
-raise "Exiting ...\n" unless defined?(permissions)
-puts "The decimal value is #{permissions.oct}"
-
-
-# @@PLEAC@@_2.17
-def commify(n)
- n.to_s =~ /([^\.]*)(\..*)?/
- int, dec = $1.reverse, $2 ? $2 : ""
- while int.gsub!(/(,|\.|^)(\d{3})(\d)/, '\1\2,\3')
- end
- int.reverse + dec
-end
-
-
-# @@PLEAC@@_2.18
-printf "It took %d hour%s\n", time, time == 1 ? "" : "s"
-
-# dunno if an equivalent to Lingua::EN::Inflect exists...
-
-
-# @@PLEAC@@_2.19
-#-----------------------------
-#!/usr/bin/ruby
-# bigfact - calculating prime factors
-def factorize(orig)
- factors = {}
- factors.default = 0 # return 0 instead nil if key not found in hash
- n = orig
- i = 2
- sqi = 4 # square of i
- while sqi <= n do
- while n.modulo(i) == 0 do
- n /= i
- factors[i] += 1
- # puts "Found factor #{i}"
- end
- # we take advantage of the fact that (i +1)**2 = i**2 + 2*i +1
- sqi += 2 * i + 1
- i += 1
- end
-
- if (n != 1) && (n != orig)
- factors[n] += 1
- end
- factors
-end
-
-def printfactorhash(orig, factorcount)
- print format("%-10d ", orig)
- if factorcount.length == 0
- print "PRIME"
- else
- # sorts after number, because the hash keys are numbers
- factorcount.sort.each { |factor,exponent|
- print factor
- if exponent > 1
- print "**", exponent
- end
- print " "
- }
- end
- puts
-end
-
-for arg in ARGV
- n = arg.to_i
- mfactors = factorize(n)
- printfactorhash(n, mfactors)
-end
-#-----------------------------
-
-
-# @@PLEAC@@_3.0
-puts Time.now
-
-print "Today is day ", Time.now.yday, " of the current year.\n"
-print "Today is day ", Time.now.day, " of the current month.\n"
-
-
-# @@PLEAC@@_3.1
-day, month, year = Time.now.day, Time.now.month, Time.now.year
-# or
-day, month, year = Time.now.to_a[3..5]
-
-tl = Time.now.localtime
-printf("The current date is %04d %02d %02d\n", tl.year, tl.month, tl.day)
-
-Time.now.localtime.strftime("%Y-%m-%d")
-
-
-# @@PLEAC@@_3.2
-Time.local(year, month, day, hour, minute, second).tv_sec
-Time.gm(year, month, day, hour, minute, second).tv_sec
-
-
-# @@PLEAC@@_3.3
-sec, min, hour, day, month, year, wday, yday, isdst, zone = Time.at(epoch_secs).to_a
-
-
-# @@PLEAC@@_3.4
-when_ = now + difference # now -> Time ; difference -> Numeric (delta in seconds)
-then_ = now - difference
-
-
-# @@PLEAC@@_3.5
-bree = 361535725
-nat = 96201950
-
-difference = bree - nat
-puts "There were #{difference} seconds between Nat and Bree"
-
-seconds = difference % 60
-difference = (difference - seconds) / 60
-minutes = difference % 60
-difference = (difference - minutes) / 60
-hours = difference % 24
-difference = (difference - hours) / 24
-days = difference % 7
-weeks = (difference - days) / 7
-
-puts "(#{weeks} weeks, #{days} days, #{hours}:#{minutes}:#{seconds})"
-
-
-# @@PLEAC@@_3.6
-monthday, weekday, yearday = date.mday, date.wday, date.yday
-
-# AFAIK the week number is not just a division since week boundaries are on sundays
-weeknum = d.strftime("%U").to_i + 1
-
-year = 1981
-month = "jun" # or `6' if you want to emulate a broken language
-day = 16
-t = Time.mktime(year, month, day)
-print "#{month}/#{day}/#{year} was a ", t.strftime("%A"), "\n"
-
-
-# @@PLEAC@@_3.7
-yyyy, mm, dd = $1, $2, $3 if "1998-06-25" =~ /(\d+)-(\d+)-(\d+)/
-
-epoch_seconds = Time.mktime(yyyy, mm, dd).tv_sec
-
-# dunno an equivalent to Date::Manip#ParseDate
-
-
-# @@PLEAC@@_3.8
-string = Time.at(epoch_secs)
-Time.at(1234567890).gmtime # gives: Fri Feb 13 23:31:30 UTC 2009
-
-time = Time.mktime(1973, "jan", 18, 3, 45, 50)
-print "In localtime it gives: ", time.localtime, "\n"
-
-
-# @@PLEAC@@_3.9
-# Ruby provides micro-seconds in Time object
-Time.now.usec
-
-# Ruby gives the seconds in floating format when substracting two Time objects
-before = Time.now
-line = gets
-elapsed = Time.now - before
-puts "You took #{elapsed} seconds."
-
-# On my Celeron-400 with Linux-2.2.19-14mdk, average for three execs are:
-# This Ruby version: average 0.00321 sec
-# Cookbook's Perl version: average 0.00981 sec
-size = 500
-number_of_times = 100
-total_time = 0
-number_of_times.times {
- # populate array
- array = []
- size.times { array << rand }
- # sort it
- begin_ = Time.now
- array.sort!
- time = Time.now - begin_
- total_time += time
-}
-printf "On average, sorting %d random numbers takes %.5f seconds\n",
- size, (total_time/Float(number_of_times))
-
-
-# @@PLEAC@@_3.10
-sleep(0.005) # Ruby is definitely not as broken as Perl :)
-# (may be interrupted by sending the process a SIGALRM)
-
-
-# @@PLEAC@@_3.11
-#!/usr/bin/ruby -w
-# hopdelta - feed mail header, produce lines
-# showing delay at each hop.
-require 'time'
-class MailHopDelta
-
- def initialize(mail)
- @head = mail.gsub(/\n\s+/,' ')
- @topline = %w-Sender Recipient Time Delta-
- @start_from = mail.match(/^From.*\@([^\s>]*)/)[1]
- @date = Time.parse(mail.match(/^Date:\s+(.*)/)[1])
- end
-
- def out(line)
- "%-20.20s %-20.20s %-20.20s %s" % line
- end
-
- def hop_date(day)
- day.strftime("%I:%M:%S %Y/%m/%d")
- end
-
- def puts_hops
- puts out(@topline)
- puts out(['Start', @start_from, hop_date(@date),''])
- @head.split(/\n/).reverse.grep(/^Received:/).each do |hop|
- hop.gsub!(/\bon (.*?) (id.*)/,'; \1')
- whence = hop.match(/;\s+(.*)$/)[1]
- unless whence
- warn "Bad received line: #{hop}"
- next
- end
- from = $+ if hop =~ /from\s+(\S+)|\((.*?)\)/
- by = $1 if hop =~ /by\s+(\S+\.\S+)/
- next unless now = Time.parse(whence).localtime
- delta = now - @date
- puts out([from, by, hop_date(now), hop_time(delta)])
- @date = now
- end
- end
-
- def hop_time(secs)
- sign = secs < 0 ? -1 : 1
- days, secs = secs.abs.divmod(60 * 60 * 24)
- hours,secs = secs.abs.divmod(60 * 60)
- mins, secs = secs.abs.divmod(60)
- rtn = "%3ds" % [secs * sign]
- rtn << "%3dm" % [mins * sign] if mins != 0
- rtn << "%3dh" % [hours * sign] if hours != 0
- rtn << "%3dd" % [days * sign] if days != 0
- rtn
- end
-end
-
-$/ = ""
-mail = MailHopDelta.new(ARGF.gets).puts_hops
-
-
-# @@PLEAC@@_4.0
-single_level = [ "this", "that", "the", "other" ]
-
-# Ruby directly supports nested arrays
-double_level = [ "this", "that", [ "the", "other" ] ]
-still_single_level = [ "this", "that", [ "the", "other" ] ].flatten
-
-
-# @@PLEAC@@_4.1
-a = [ "quick", "brown", "fox" ]
-a = %w(Why are you teasing me?)
-
-lines = <<"END_OF_HERE_DOC".gsub(/^\s*(.+)/, '\1')
- The boy stood on the burning deck,
- It was as hot as glass.
-END_OF_HERE_DOC
-
-bigarray = IO.readlines("mydatafile").collect { |l| l.chomp }
-
-name = "Gandalf"
-banner = %Q(Speak, #{name}, and welcome!)
-
-host_info = `host #{his_host}`
-
-%x(ps #{$$})
-
-banner = 'Costs only $4.95'.split(' ')
-
-rax = %w! ( ) < > { } [ ] !
-
-
-# @@PLEAC@@_4.2
-def commify_series(a)
- a.size == 0 ? '' :
- a.size == 1 ? a[0] :
- a.size == 2 ? a.join(' and ') :
- a[0..-2].join(', ') + ', and ' + a[-1]
-end
-
-array = [ "red", "yellow", "green" ]
-
-print "I have ", array, " marbles\n"
-# -> I have redyellowgreen marbles
-
-# But unlike Perl:
-print "I have #{array} marbles\n"
-# -> I have redyellowgreen marbles
-# So, needs:
-print "I have #{array.join(' ')} marbles\n"
-# -> I have red yellow green marbles
-
-def commify_series(a)
- sepchar = a.select { |p| p =~ /,/ } != [] ? '; ' : ', '
- a.size == 0 ? '' :
- a.size == 1 ? a[0] :
- a.size == 2 ? a.join(' and ') :
- a[0..-2].join(sepchar) + sepchar + 'and ' + a[-1]
-end
-
-
-# @@PLEAC@@_4.3
-# (note: AFAIK Ruby doesn't allow gory change of Array length)
-# grow the array by assigning nil to past the end of array
-ary[new_size-1] = nil
-# shrink the array by slicing it down
-ary.slice!(new_size..-1)
-# init the array with given size
-Array.new(number_of_elems)
-# assign to an element past the original end enlarges the array
-ary[index_new_last_elem] = value
-
-def what_about_that_array(a)
- print "The array now has ", a.size, " elements.\n"
- # Index of last element is not really interesting in Ruby
- print "Element #3 is `#{a[3]}'.\n"
-end
-people = %w(Crosby Stills Nash Young)
-what_about_that_array(people)
-
-
-# @@PLEAC@@_4.4
-# OO style
-bad_users.each { |user|
- complain(user)
-}
-# or, functional style
-for user in bad_users
- complain(user)
-end
-
-for var in ENV.keys.sort
- puts "#{var}=#{ENV[var]}"
-end
-
-for user in all_users
- disk_space = get_usage(user)
- if (disk_space > MAX_QUOTA)
- complain(user)
- end
-end
-
-for l in IO.popen("who").readlines
- print l if l =~ /^gc/
-end
-
-# we can mimic the obfuscated Perl way
-while fh.gets # $_ is set to the line just read
- chomp # $_ has a trailing \n removed, if it had one
- split.each { |w| # $_ is split on whitespace
- # but $_ is not set to each chunk as in Perl
- print w.reverse
- }
-end
-# ...or use a cleaner way
-for l in fh.readlines
- l.chomp.split.each { |w| print w.reverse }
-end
-
-# same drawback as in problem 1.4, we can't mutate a Numeric...
-array.collect! { |v| v - 1 }
-
-a = [ .5, 3 ]; b = [ 0, 1 ]
-for ary in [ a, b ]
- ary.collect! { |v| v * 7 }
-end
-puts "#{a.join(' ')} #{b.join(' ')}"
-
-# we can mutate Strings, cool; we need a trick for the scalar
-for ary in [ [ scalar ], array, hash.values ]
- ary.each { |v| v.strip! } # String#strip rules :)
-end
-
-
-# @@PLEAC@@_4.5
-# not relevant in Ruby since we have always references
-for item in array
- # do somethingh with item
-end
-
-
-# @@PLEAC@@_4.6
-unique = list.uniq
-
-# generate a list of users logged in, removing duplicates
-users = `who`.collect { |l| l =~ /(\w+)/; $1 }.sort.uniq
-puts("users logged in: #{commify_series(users)}") # see 4.2 for commify_series
-
-
-# @@PLEAC@@_4.7
-a - b
-# [ 1, 1, 2, 2, 3, 3, 3, 4, 5 ] - [ 1, 2, 4 ] -> [3, 5]
-
-
-# @@PLEAC@@_4.8
-union = a | b
-intersection = a & b
-difference = a - b
-
-
-# @@PLEAC@@_4.9
-array1.concat(array2)
-# if you will assign to another object, better use:
-new_ary = array1 + array2
-
-members = [ "Time", "Flies" ]
-initiates = [ "An", "Arrow" ]
-members += initiates
-
-members = [ "Time", "Flies" ]
-initiates = [ "An", "Arrow" ]
-members[2,0] = [ "Like", initiates ].flatten
-
-members[0] = "Fruit"
-members[3,2] = "A", "Banana"
-
-
-# @@PLEAC@@_4.10
-reversed = ary.reverse
-
-ary.reverse_each { |e|
- # do something with e
-}
-
-descending = ary.sort.reverse
-descending = ary.sort { |a,b| b <=> a }
-
-
-# @@PLEAC@@_4.11
-# remove n elements from front of ary (shift n)
-front = ary.slice!(0, n)
-
-# remove n elements from the end of ary (pop n)
-end_ = ary.slice!(-n .. -1)
-
-# let's extend the Array class, to make that useful
-class Array
- def shift2()
- slice!(0 .. 1) # more symetric with pop2...
- end
- def pop2()
- slice!(-2 .. -1)
- end
-end
-
-friends = %w(Peter Paul Mary Jim Tim)
-this, that = friends.shift2
-
-beverages = %w(Dew Jolt Cola Sprite Fresca)
-pair = beverages.pop2
-
-
-# @@PLEAC@@_4.12
-# use Enumerable#detect (or the synonym Enumerable#find)
-highest_eng = employees.detect { |emp| emp.category == 'engineer' }
-
-
-# @@PLEAC@@_4.13
-# use Enumerable#select (or the synonym Enumerable#find_all)
-bigs = nums.select { |i| i > 1_000_000 }
-pigs = users.keys.select { |k| users[k] > 1e7 }
-
-matching = `who`.select { |u| u =~ /^gnat / }
-
-engineers = employees.select { |e| e.position == 'Engineer' }
-
-secondary_assistance = applicants.select { |a|
- a.income >= 26_000 && a.income < 30_000
-}
-
-
-# @@PLEAC@@_4.14
-# normally you would have an array of Numeric (Float or
-# Fixnum or Bignum), so you would use:
-sorted = unsorted.sort
-# if you have strings representing Integers or Floats
-# you may specify another sort method:
-sorted = unsorted.sort { |a,b| a.to_f <=> b.to_f }
-
-# let's use the list of my own PID's
-`ps ux`.split("\n")[1..-1].
- select { |i| i =~ /^#{ENV['USER']}/ }.
- collect { |i| i.split[1] }.
- sort { |a,b| a.to_i <=> b.to_i }.each { |i| puts i }
-puts "Select a process ID to kill:"
-pid = gets.chomp
-raise "Exiting ... \n" unless pid && pid =~ /^\d+$/
-Process.kill('TERM', pid.to_i)
-sleep 2
-Process.kill('KILL', pid.to_i)
-
-descending = unsorted.sort { |a,b| b.to_f <=> a.to_f }
-
-
-# @@PLEAC@@_4.15
-ordered = unordered.sort { |a,b| compare(a,b) }
-
-precomputed = unordered.collect { |e| [compute, e] }
-ordered_precomputed = precomputed.sort { |a,b| a[0] <=> b[0] }
-ordered = ordered_precomputed.collect { |e| e[1] }
-
-ordered = unordered.collect { |e| [compute, e] }.
- sort { |a,b| a[0] <=> b[0] }.
- collect { |e| e[1] }
-
-for employee in employees.sort { |a,b| a.name <=> b.name }
- print employee.name, " earns \$ ", employee.salary, "\n"
-end
-
-# Beware! `0' is true in Ruby.
-# For chaining comparisons, you may use Numeric#nonzero?, which
-# returns num if num is not zero, nil otherwise
-sorted = employees.sort { |a,b| (a.name <=> b.name).nonzero? || b.age <=> a.age }
-
-users = []
-# getpwent is not wrapped in Ruby... let's fallback
-IO.readlines('/etc/passwd').each { |u| users << u.split(':') }
-users.sort! { |a,b| a[0] <=> b[0] }
-for user in users
- puts user[0]
-end
-
-sorted = names.sort { |a,b| a[1, 1] <=> b[1, 1] }
-sorted = strings.sort { |a,b| a.length <=> b.length }
-
-# let's show only the compact version
-ordered = strings.collect { |e| [e.length, e] }.
- sort { |a,b| a[0] <=> b[0] }.
- collect { |e| e[1] }
-
-ordered = strings.collect { |e| [/\d+/.match(e)[0].to_i, e] }.
- sort { |a,b| a[0] <=> b[0] }.
- collect { |e| e[1] }
-
-print `cat /etc/passwd`.collect { |e| [e, e.split(':').indexes(3,2,0)].flatten }.
- sort { |a,b| (a[1] <=> b[1]).nonzero? || (a[2] <=> b[2]).nonzero? || a[3] <=> b[3] }.
- collect { |e| e[0] }
-
-
-# @@PLEAC@@_4.16
-circular.unshift(circular.pop) # the last shall be first
-circular.push(circular.shift) # and vice versa
-
-def grab_and_rotate(l)
- l.push(ret = l.shift)
- ret
-end
-
-processes = [1, 2, 3, 4, 5]
-while (1)
- process = grab_and_rotate(processes)
- puts "Handling process #{process}"
- sleep 1
-end
-
-
-# @@PLEAC@@_4.17
-def fisher_yates_shuffle(a)
- (a.size-1).downto(1) { |i|
- j = rand(i+1)
- a[i], a[j] = a[j], a[i] if i != j
- }
-end
-
-def naive_shuffle(a)
- for i in 0...a.size
- j = rand(a.size)
- a[i], a[j] = a[j], a[i]
- end
-end
-
-
-# @@PLEAC@@_4.18
-#!/usr/bin/env ruby
-# example 4-2 words
-# words - gather lines, present in colums
-
-# class to encapsulate the word formatting from the input
-class WordFormatter
- def initialize(cols)
- @cols = cols
- end
-
- # helper to return the length of the longest word in the wordlist
- def maxlen(wordlist)
- max = 1
- for word in wordlist
- if word.length > max
- max = word.length
- end
- end
- max
- end
-
- # process the wordlist and print it formmated into columns
- def output(wordlist)
- collen = maxlen(wordlist) + 1
- columns = @cols / collen
- columns = 1 if columns == 0
- rows = (wordlist.length + columns - 1) / columns
- # now process each item, picking out proper piece for this position
- 0.upto(rows * columns - 1) { |item|
- target = (item % columns) * rows + (item / columns)
- eol = ((item+1) % columns == 0)
- piece = wordlist[target] || ""
- piece = piece.ljust(collen) unless eol
- print piece
- puts if eol
- }
- # no need to finish it up, because eol is always true for the last element
- end
-end
-
-# get nr of chars that fit in window or console, see PLEAC 15.4
-# not portable -- linux only (?)
-def getWinCharWidth()
- buf = "\0" * 8
- $stdout.ioctl(0x5413, buf)
- ws_row, ws_col, ws_xpixel, ws_ypixel = buf.unpack("$4")
- ws_col || 80
-rescue
- 80
-end
-
-# main program
-cols = getWinCharWidth()
-formatter = WordFormatter.new(cols)
-words = readlines()
-words.collect! { |line|
- line.chomp
-}
-formatter.output(words)
-
-
-# @@PLEAC@@_4.19
-# In ruby, Fixnum's are automatically converted to Bignum's when
-# needed, so there is no need for an extra module
-def factorial(n)
- s = 1
- while n > 0
- s *= n
- n -= 1
- end
- s
-end
-
-puts factorial(500)
-
-#---------------------------------------------------------
-# Example 4-3. tsc-permute
-# tsc_permute: permute each word of input
-def permute(items, perms)
- unless items.length > 0
- puts perms.join(" ")
- else
- for i in items
- newitems = items.dup
- newperms = perms.dup
- newperms.unshift(newitems.delete(i))
- permute(newitems, newperms)
- end
- end
-end
-# In ruby the main program must be after all definitions it is using
-permute(ARGV, [])
-
-#---------------------------------------------------------
-# mjd_permute: permute each word of input
-
-def factorial(n)
- s = 1
- while n > 0
- s *= n
- n -= 1
- end
- s
-end
-
-# we use a class with a class variable store the private cache
-# for the results of the factorial function.
-class Factorial
- @@fact = [ 1 ]
- def Factorial.compute(n)
- if @@fact[n]
- @@fact[n]
- else
- @@fact[n] = n * Factorial.compute(n - 1)
- end
- end
-end
-
-#---------------------------------------------------------
-# Example 4-4- mjd-permute
-# n2pat(n, len): produce the N-th pattern of length len
-
-# We must use a lower case letter as parameter N, otherwise it is
-# handled as constant Length is the length of the resulting
-# array, not the index of the last element (length -1) like in
-# the perl example.
-def n2pat(n, length)
- pat = []
- i = 1
- while i <= length
- pat.push(n % i)
- n /= i
- i += 1
- end
- pat
-end
-
-# pat2perm(pat): turn pattern returned by n2pat() into
-# permutation of integers.
-def pat2perm(pat)
- source = (0 .. pat.length - 1).to_a
- perm = []
- perm.push(source.slice!(pat.pop)) while pat.length > 0
- perm
-end
-
-def n2perm(n, len)
- pat2perm(n2pat(n,len))
-end
-
-# In ruby the main program must be after all definitions
-while gets
- data = split
- # the perl solution has used $#data, which is length-1
- num_permutations = Factorial.compute(data.length())
- 0.upto(num_permutations - 1) do |i|
- # in ruby we can not use an array as selector for an array
- # but by exchanging the two arrays, we can use the collect method
- # which returns an array with the result of all block invocations
- permutation = n2perm(i, data.length).collect {
- |j| data[j]
- }
- puts permutation.join(" ")
- end
-end
-
-
-# @@PLEAC@@_5.0
-age = { "Nat", 24,
- "Jules", 25,
- "Josh", 17 }
-
-age["Nat"] = 24
-age["Jules"] = 25
-age["Josh"] = 17
-
-food_color = {
- "Apple" => "red",
- "Banana" => "yellow",
- "Lemon" => "yellow",
- "Carrot" => "orange"
- }
-
-# In Ruby, you cannot avoid the double or simple quoting
-# while manipulatin hashes
-
-
-# @@PLEAC@@_5.1
-hash[key] = value
-
-food_color["Raspberry"] = "pink"
-puts "Known foods:", food_color.keys
-
-
-# @@PLEAC@@_5.2
-# does hash have a value for key ?
-if (hash.has_key?(key))
- # it exists
-else
- # it doesn't
-end
-
-[ "Banana", "Martini" ].each { |name|
- print name, " is a ", food_color.has_key?(name) ? "food" : "drink", "\n"
-}
-
-age = {}
-age['Toddler'] = 3
-age['Unborn'] = 0
-age['Phantasm'] = nil
-
-for thing in ['Toddler', 'Unborn', 'Phantasm', 'Relic']
- print "#{thing}: "
- print "Has-key " if age.has_key?(thing)
- print "True " if age[thing]
- print "Nonzero " if age[thing] && age[thing].nonzero?
- print "\n"
-end
-
-#=>
-# Toddler: Has-key True Nonzero
-# Unborn: Has-key True
-# Phantasm: Has-key
-# Relic:
-
-# You use Hash#has_key? when you use Perl's exists -> it checks
-# for existence of a key in a hash.
-# All Numeric are "True" in ruby, so the test doesn't have the
-# same semantics as in Perl; you would use Numeric#nonzero? to
-# achieve the same semantics (false if 0, true otherwise).
-
-
-# @@PLEAC@@_5.3
-food_color.delete("Banana")
-
-
-# @@PLEAC@@_5.4
-hash.each { |key, value|
- # do something with key and value
-}
-
-hash.each_key { |key|
- # do something with key
-}
-
-food_color.each { |food, color|
- puts "#{food} is #{color}"
-}
-
-food_color.each_key { |food|
- puts "#{food} is #{food_color[food]}"
-}
-
-# IMO this demonstrates that OO style is by far more readable
-food_color.keys.sort.each { |food|
- puts "#{food} is #{food_color[food]}."
-}
-
-#-----------------------------
-#!/usr/bin/ruby
-# countfrom - count number of messages from each sender
-
-# Default value is 0
-from = Hash.new(0)
-while gets
- /^From: (.*)/ and from[$1] += 1
-end
-
-# More useful to sort by number of received mail by person
-from.sort {|a,b| b[1]<=>a[1]}.each { |v|
- puts "#{v[1]}: #{v[0]}"
-}
-#-----------------------------
-
-
-# @@PLEAC@@_5.5
-# You may use the built-in 'inspect' method this way:
-p hash
-
-# Or do it the Cookbook way:
-hash.each { |k,v| puts "#{k} => #{v}" }
-
-# Sorted by keys
-hash.sort.each { |e| puts "#{e[0]} => #{e[1]}" }
-# Sorted by values
-hash.sort{|a,b| a[1]<=>b[1]}.each { |e| puts "#{e[0]} => #{e[1]}" }
-
-
-# @@PLEAC@@_5.7
-ttys = Hash.new
-for i in `who`
- user, tty = i.split
- (ttys[user] ||= []) << tty # see problems_ruby for more infos
-end
-ttys.keys.sort.each { |k|
- puts "#{k}: #{commify_series(ttys[k])}" # from 4.2
-}
-
-
-# @@PLEAC@@_5.8
-surname = { "Mickey" => "Mantle", "Babe" => "Ruth" }
-puts surname.index("Mantle")
-
-# If you really needed to 'invert' the whole hash, use Hash#invert
-
-#-----------------------------
-#!/usr/bin/ruby -w
-# foodfind - find match for food or color
-
-given = ARGV.shift or raise "usage: foodfind food_or_color"
-
-color = {
- "Apple" => "red",
- "Banana" => "yellow",
- "Lemon" => "yellow",
- "Carrot" => "orange",
-}
-
-if (color.has_key?(given))
- puts "#{given} is a food with color #{color[given]}."
-end
-if (color.has_value?(given))
- puts "#{color.index(given)} is a food with color #{given}."
-end
-#-----------------------------
-
-
-# @@PLEAC@@_5.9
-# Sorted by keys (Hash#sort gives an Array of pairs made of each key,value)
-food_color.sort.each { |f|
- puts "#{f[0]} is #{f[1]}."
-}
-
-# Sorted by values
-food_color.sort { |a,b| a[1] <=> b[1] }.each { |f|
- puts "#{f[0]} is #{f[1]}."
-}
-
-# Sorted by length of values
-food_color.sort { |a,b| a[1].length <=> b[1].length }.each { |f|
- puts "#{f[0]} is #{f[1]}."
-}
-
-
-# @@PLEAC@@_5.10
-merged = a.clone.update(b) # because Hash#update changes object in place
-
-drink_color = { "Galliano" => "yellow", "Mai Tai" => "blue" }
-ingested_color = drink_color.clone.update(food_color)
-
-substance_color = {}
-for i in [ food_color, drink_color ]
- i.each_key { |k|
- if substance_color.has_key?(k)
- puts "Warning: #{k} seen twice. Using the first definition."
- next
- end
- substance_color[k] = 1
- }
-end
-
-
-# @@PLEAC@@_5.11
-common = hash1.keys & hash2.keys
-
-this_not_that = hash1.keys - hash2.keys
-
-
-# @@PLEAC@@_5.12
-# no problem here, Ruby handles any kind of object for key-ing
-# (it takes Object#hash, which defaults to Object#id)
-
-
-# @@PLEAC@@_5.13
-# AFAIK, not possible in Ruby
-
-
-# @@PLEAC@@_5.14
-# Be careful, the following is possible only because Fixnum objects are
-# special (documentation says: there is effectively only one Fixnum object
-# instance for any given integer value).
-count = Hash.new(0)
-array.each { |e|
- count[e] += 1
-}
-
-
-# @@PLEAC@@_5.15
-father = {
- "Cain" , "Adam",
- "Abel" , "Adam",
- "Seth" , "Adam",
- "Enoch" , "Cain",
- "Irad" , "Enoch",
- "Mehujael" , "Irad",
- "Methusael" , "Mehujael",
- "Lamech" , "Methusael",
- "Jabal" , "Lamech",
- "Jubal" , "Lamech",
- "Tubalcain" , "Lamech",
- "Enos" , "Seth",
-}
-
-while gets
- chomp
- begin
- print $_, " "
- end while $_ = father[$_]
- puts
-end
-
-children = {}
-father.each { |k,v|
- (children[v] ||= []) << k
-}
-while gets
- chomp
- puts "#{$_} begat #{(children[$_] || ['Nobody']).join(', ')}.\n"
-end
-
-includes = {}
-files.each { |f|
- begin
- for l in IO.readlines(f)
- next unless l =~ /^\s*#\s*include\s*<([^>]+)>/
- (includes[$1] ||= []) << f
- end
- rescue SystemCallError
- $stderr.puts "#$! (skipping)"
- end
-}
-
-include_free = includes.values.flatten.uniq - includes.keys
-
-
-# @@PLEAC@@_5.16
-# dutree - print sorted intented rendition of du output
-#% dutree
-#% dutree /usr
-#% dutree -a
-#% dutree -a /bin
-
-# The DuNode class collects all information about a directory,
-# and provides some convenience methods
-class DuNode
-
- attr_reader :name
- attr_accessor :size
- attr_accessor :kids
-
- def initialize(name)
- @name = name
- @kids = []
- @size = 0
- end
-
- # support for sorting nodes with side
- def size_compare(node2)
- @size <=> node2.size
- end
-
- def basename
- @name.sub(/.*\//, "")
- end
-
- #returns substring before last "/", nil if not there
- def parent
- p = @name.sub(/\/[^\/]+$/,"")
- if p == @name
- nil
- else
- p
- end
- end
-
-end
-
-# The DuTree does the acdtual work of
-# getting the input, parsing it, builging up a tree
-# and format it for output
-class Dutree
-
- attr_reader :topdir
-
- def initialize
- @nodes = Hash.new
- @dirsizes = Hash.new(0)
- @kids = Hash.new([])
- end
-
- # get a node by name, create it if it does not exist yet
- def get_create_node(name)
- if @nodes.has_key?(name)
- @nodes[name]
- else
- node = DuNode.new(name)
- @nodes[name] = node
- node
- end
- end
-
- # run du, read in input, save sizes and kids
- # stores last directory read in instance variable topdir
- def input(arguments)
- name = ""
- cmd = "du " + arguments.join(" ")
- IO.popen(cmd) { |pipe|
- pipe.each { |line|
- size, name = line.chomp.split(/\s+/, 2)
- node = get_create_node(name)
- node.size = size.to_i
- @nodes[name] = node
- parent = node.parent
- if parent
- get_create_node(parent).kids.push(node)
- end
- }
- }
- @topdir = @nodes[name]
- end
-
- # figure out how much is taken in each directory
- # that isn't stored in the subdirectories. Add a new
- # fake kid called "." containing that much.
- def get_dots(node)
- cursize = node.size
- for kid in node.kids
- cursize -= kid.size
- get_dots(kid)
- end
- if node.size != cursize
- newnode = get_create_node(node.name + "/.")
- newnode.size = cursize
- node.kids.push(newnode)
- end
- end
-
- # recursively output everything
- # passing padding and number width as well
- # on recursive calls
- def output(node, prefix="", width=0)
- line = sprintf("%#{width}d %s", node.size, node.basename)
- puts(prefix + line)
- prefix += line.sub(/\d /, "| ")
- prefix.gsub!(/[^|]/, " ")
- if node.kids.length > 0 # not a bachelor node
- kids = node.kids
- kids.sort! { |a,b|
- b.size_compare(a)
- }
- width = kids[0].size.to_s.length
- for kid in kids
- output(kid, prefix, width)
- end
- end
- end
-
-end
-
-tree = Dutree.new
-tree.input(ARGV)
-tree.get_dots(tree.topdir)
-tree.output(tree.topdir)
-
-
-# @@PLEAC@@_6.0
-# The verbose version are match, sub, gsub, sub! and gsub!;
-# pattern needs to be a Regexp object; it yields a MatchData
-# object.
-pattern.match(string)
-string.sub(pattern, replacement)
-string.gsub(pattern, replacement)
-# As usual in Ruby, sub! does the same as sub but also modifies
-# the object, the same for gsub!/gsub.
-
-# Sugared syntax yields the position of the match (or nil if no
-# match). Note that the object at the right of the operator needs
-# not to be a Regexp object (it can be a String). The "dont
-# match" operator yields true or false.
-meadow =~ /sheep/ # position of the match, nil if no match
-meadow !~ /sheep/ # true if doesn't match, false if it does
-# There is no sugared version for the substitution
-
-meadow =~ /\bovines?\b/i and print "Here be sheep!"
-
-string = "good food"
-string.sub!(/o*/, 'e')
-
-# % echo ababacaca | ruby -ne 'puts $& if /(a|ba|b)+(a|ac)+/'
-# ababa
-
-# The "global" (or "multiple") match is handled by String#scan
-scan (/(\d+)/) {
- puts "Found number #{$1}"
-}
-
-# String#scan yields an Array if not used with a block
-numbers = scan(/\d+/)
-
-digits = "123456789"
-nonlap = digits.scan(/(\d\d\d)/)
-yeslap = digits.scan(/(?=(\d\d\d))/)
-puts "Non-overlapping: #{nonlap.join(' ')}"
-puts "Overlapping: #{yeslap.join(' ')}";
-# Non-overlapping: 123 456 789
-# Overlapping: 123 234 345 456 567 678 789
-
-string = "And little lambs eat ivy"
-string =~ /l[^s]*s/
-puts "(#$`) (#$&) (#$')"
-# (And ) (little lambs) ( eat ivy)
-
-
-# @@PLEAC@@_6.1
-# Ruby doesn't have the same problem:
-dst = src.sub('this', 'that')
-
-progname = $0.sub('^.*/', '')
-
-bindirs = %w(/usr/bin /bin /usr/local/bin)
-libdirs = bindirs.map { |l| l.sub('bin', 'lib') }
-
-
-# @@PLEAC@@_6.3
-/\S+/ # as many non-whitespace bytes as possible
-/[A-Za-z'-]+/ # as many letters, apostrophes, and hyphens
-
-/\b([A-Za-z]+)\b/ # usually best
-/\s([A-Za-z]+)\s/ # fails at ends or w/ punctuation
-
-
-# @@PLEAC@@_6.4
-require 'socket'
-str = 'www.ruby-lang.org and www.rubygarden.org'
-re = /
- ( # capture the hostname in $1
- (?: # these parens for grouping only
- (?! [-_] ) # lookahead for neither underscore nor dash
- [\w-] + # hostname component
- \. # and the domain dot
- ) + # now repeat that whole thing a bunch of times
- [A-Za-z] # next must be a letter
- [\w-] + # now trailing domain part
- ) # end of $1 capture
- /x # /x for nice formatting
-
-str.gsub! re do # pass a block to execute replacement
- host = TCPsocket.gethostbyname($1)
- "#{$1} [#{host[3]}]"
-end
-
-puts str
-#-----------------------------
-# to match whitespace or #-characters in an extended re you need to escape
-# them.
-
-foo = 42
-str = 'blah #foo# blah'
-str.gsub! %r/ # replace
- \# # a pound sign
- (\w+) # the variable name
- \# # another pound sign
- /x do
- eval $1 # with the value of a local variable
- end
-puts str # => blah 42 blah
-
-
-# @@PLEAC@@_6.5
-# The 'g' modifier doesn't exist in Ruby, a regexp can't be used
-# directly in a while loop; instead, use String#scan { |match| .. }
-fish = 'One fish two fish red fish blue fish'
-WANT = 3
-count = 0
-fish.scan(/(\w+)\s+fish\b/i) {
- if (count += 1) == WANT
- puts "The third fish is a #{$1} one."
- end
-}
-
-if fish =~ /(?:\w+\s+fish\s+){2}(\w+)\s+fish/i
- puts "The third fish is a #{$1} one."
-end
-
-pond = 'One fish two fish red fish blue fish'
-# String#scan without a block gives an array of matches, each match
-# being an array of all the specified groups
-colors = pond.scan(/(\w+)\s+fish\b/i).flatten # get all matches
-color = colors[2] # then the one we want
-# or without a temporary array
-color = pond.scan(/(\w+)\s+fish\b/i).flatten[2] # just grab element 3
-puts "The third fish in the pond is #{color}."
-
-count = 0
-fishes = 'One fish two fish red fish blue fish'
-evens = fishes.scan(/(\w+)\s+fish\b/i).select { (count+=1) % 2 == 0 }
-print "Even numbered fish are #{evens.join(' ')}."
-
-count = 0
-fishes.gsub(/
- \b # makes next \w more efficient
- ( \w+ ) # this is what we\'ll be changing
- (
- \s+ fish \b
- )
- /x) {
- if (count += 1) == 4
- 'sushi' + $2
- else
- $1 + $2
- end
-}
-
-pond = 'One fish two fish red fish blue fish swim here.'
-puts "Last fish is #{pond.scan(/\b(\w+)\s+fish\b/i).flatten[-1]}"
-
-/
- A # find some pattern A
- (?! # mustn\'t be able to find
- .* # something
- A # and A
- )
- $ # through the end of the string
-/x
-
-# The "s" perl modifier is "m" in Ruby (not very nice since there is
-# also an "m" in perl..)
-pond = "One fish two fish red fish blue fish swim here."
-if (pond =~ /
- \b ( \w+) \s+ fish \b
- (?! .* \b fish \b )
- /mix)
- puts "Last fish is #{$1}."
-else
- puts "Failed!"
-end
-
-
-# @@PLEAC@@_6.6
-#-----------------------------
-#!/usr/bin/ruby -w
-# killtags - very bad html killer
-$/ = nil; # each read is whole file
-while file = gets() do
- file.gsub!(/<.*?>/m,''); # strip tags (terribly)
- puts file # print file to STDOUT
-end
-#-----------------------------
-#!/usr/bin/ruby -w
-#headerfy - change certain chapter headers to html
-$/ = ''
-while file = gets() do
- pattern = /
- \A # start of record
- ( # capture in $1
- Chapter # text string
- \s+ # mandatory whitespace
- \d+ # decimal number
- \s* # optional whitespace
- : # a real colon
- . * # anything not a newline till end of line
- )
- /x
- puts file.gsub(pattern,'<H1>\1</H1>')
-end
-#-----------------------------
-#% ruby -00pe "gsub!(/\A(Chapter\s+\d+\s*:.*)/,'<H1>\1</H1>')" datafile
-
-#!/usr/bin/ruby -w
-#-----------------------------
-for file in ARGV
- file = File.open(ARGV.shift)
- while file.gets('') do # each read is a paragraph
- print "chunk #{$.} in $ARGV has <<#{$1}>>\n" while /^START(.*?)^END/m
- end # /m activates the multiline mode
-end
-#-----------------------------
-
-# @@PLEAC@@_6.7
-#-----------------------------
-$/ = nil;
-file = File.open("datafile")
-chunks = file.gets.split(/pattern/)
-#-----------------------------
-# .Ch, .Se and .Ss divide chunks of STDIN
-chunks = gets(nil).split(/^\.(Ch|Se|Ss)$/)
-print "I read #{chunks.size} chunks.\n"
-#-----------------------------
-
-
-# @@PLEAC@@_6.8
-while gets
- if ~/BEGIN/ .. ~/END/
- # line falls between BEGIN and END inclusive
- end
-end
-
-while gets
- if ($. == firstnum) .. ($. == lastnum)
- # operate between firstnum and lastnum line number
- end
-end
-
-# in ruby versions prior to 1.8, the above two conditional
-# expressions could be shortened to:
-# if /BEGIN/ .. /END/
-# and
-# if firstnum .. lastnum
-# but these now only work this way from the command line
-
-#-----------------------------
-
-while gets
- if ~/BEGIN/ ... ~/END/
- # line falls between BEGIN and END on different lines
- end
-end
-
-while gets
- if ($. == first) ... ($. == last)
- # operate between first and last line number on different lines
- end
-end
-
-#-----------------------------
-# command-line to print lines 15 through 17 inclusive (see below)
-ruby -ne 'print if 15 .. 17' datafile
-
-# print out all <XMP> .. </XMP> displays from HTML doc
-while gets
- print if ~%r#<XMP>#i .. ~%r#</XMP>#i;
-end
-
-# same, but as shell command
-# ruby -ne 'print if %r#<XMP>#i .. %r#</XMP>#i' document.html
-#-----------------------------
-# ruby -ne 'BEGIN { $top=3; $bottom=5 }; \
-# print if $top .. $bottom' /etc/passwd # FAILS
-# ruby -ne 'BEGIN { $top=3; $bottom=5 }; \
-# print if $. == $top .. $. == $bottom' /etc/passwd # works
-# ruby -ne 'print if 3 .. 5' /etc/passwd # also works
-#-----------------------------
-print if ~/begin/ .. ~/end/;
-print if ~/begin/ ... ~/end/;
-#-----------------------------
-while gets
- $in_header = $. == 1 .. ~/^$/ ? true : false
- $in_body = ~/^$/ .. ARGF.eof ? true : false
-end
-#-----------------------------
-seen = {}
-ARGF.each do |line|
- next unless line =~ /^From:?\s/i .. line =~ /^$/;
- line.scan(%r/([^<>(),;\s]+\@[^<>(),;\s]+)/).each do |addr|
- puts addr unless seen[addr]
- seen[addr] ||= 1
- end
-end
-
-
-# @@PLEAC@@_6.9
-def glob2pat(globstr)
- patmap = {
- '*' => '.*',
- '?' => '.',
- '[' => '[',
- ']' => ']',
- }
- globstr.gsub!(/(.)/) { |c| patmap[c] || Regexp::escape(c) }
- '^' + globstr + '$'
-end
-
-
-# @@PLEAC@@_6.10
-# avoid interpolating patterns like this if the pattern
-# isn't going to change:
-pattern = ARGV.shift
-ARGF.each do |line|
- print line if line =~ /#{pattern}/
-end
-
-# the above creates a new regex each iteration. Instead,
-# use the /o modifier so the regex is compiled only once
-
-pattern = ARGV.shift
-ARGF.each do |line|
- print line if line =~ /#{pattern}/o
-end
-
-#-----------------------------
-
-#!/usr/bin/ruby
-# popgrep1 - grep for abbreviations of places that say "pop"
-# version 1: slow but obvious way
-popstates = %w(CO ON MI WI MN)
-ARGF.each do |line|
- popstates.each do |state|
- if line =~ /\b#{state}\b/
- print line
- last
- end
- end
-end
-
-#-----------------------------
-#!/usr/bin/ruby
-# popgrep2 - grep for abbreviations of places that say "pop"
-# version 2: eval strings; fast but hard to quote
-popstates = %w(CO ON MI WI MN)
-code = "ARGF.each do |line|\n"
-popstates.each do |state|
- code += "\tif line =~ /\\b#{state}\\b/; print(line); next; end\n"
-end
-code += "end\n"
-print "CODE IS\n---\n#{code}\n---\n" if false # turn on for debugging
-eval code
-
-# CODE IS
-# ---
-# ARGF.each do |line|
-# if line =~ /\bCO\b/; print(line); next; end
-# if line =~ /\bON\b/; print(line); next; end
-# if line =~ /\bMI\b/; print(line); next; end
-# if line =~ /\bWI\b/; print(line); next; end
-# if line =~ /\bMN\b/; print(line); next; end
-# end
-#
-# ---
-
-## alternatively, the same idea as above but compiling
-## to a case statement: (not in perlcookbook)
-#!/usr/bin/ruby -w
-# popgrep2.5 - grep for abbreviations of places that say "pop"
-# version 2.5: eval strings; fast but hard to quote
-popstates = %w(CO ON MI WI MN)
-code = "ARGF.each do |line|\n case line\n"
-popstates.each do |state|
- code += " when /\\b#{state}\\b/ : print line\n"
-end
-code += " end\nend\n"
-print "CODE IS\n---\n#{code}\n---\n" if false # turn on for debugging
-eval code
-
-# CODE IS
-# ---
-# ARGF.each do |line|
-# case line
-# when /\bCO\b/ : print line
-# when /\bON\b/ : print line
-# when /\bMI\b/ : print line
-# when /\bWI\b/ : print line
-# when /\bMN\b/ : print line
-# end
-# end
-#
-# ---
-
-# Note: (above) Ruby 1.8+ allows the 'when EXP : EXPR' on one line
-# with the colon separator.
-
-#-----------------------------
-#!/usr/bin/ruby
-# popgrep3 - grep for abbreviations of places that say "pop"
-# version3: build a match_any function
-popstates = %w(CO ON MI WI MN)
-expr = popstates.map{|e|"line =~ /\\b#{e}\\b/"}.join('||')
-eval "def match_any(line); #{expr};end"
-ARGF.each do |line|
- print line if match_any(line)
-end
-#-----------------------------
-
-## building a match_all function is a trivial
-## substitution of && for ||
-## here is a generalized example:
-#!/usr/bin/ruby -w
-## grepauth - print lines that mention both foo and bar
-class MultiMatch
- def initialize(*patterns)
- _any = build_match('||',patterns)
- _all = build_match('&&',patterns)
- eval "def match_any(line);#{_any};end\n"
- eval "def match_all(line);#{_all};end\n"
- end
- def build_match(sym,args)
- args.map{|e|"line =~ /#{e}/"}.join(sym)
- end
-end
-
-mm = MultiMatch.new('foo','bar')
-ARGF.each do |line|
- print line if mm.match_all(line)
-end
-#-----------------------------
-
-#!/usr/bin/ruby
-# popgrep4 - grep for abbreviations of places that say "pop"
-# version4: pretty fast, but simple: compile all re's first:
-popstates = %w(CO ON MI WI MN)
-popstates = popstates.map{|re| %r/\b#{re}\b/}
-ARGF.each do |line|
- popstates.each do |state_re|
- if line =~ state_re
- print line
- break
- end
- end
-end
-
-## speeds trials on the jargon file(412): 26006 lines, 1.3MB
-## popgrep1 => 7.040s
-## popgrep2 => 0.656s
-## popgrep2.5 => 0.633s
-## popgrep3 => 0.675s
-## popgrep4 => 1.027s
-
-# unless speed is criticial, the technique in popgrep4 is a
-# reasonable balance between speed and logical simplicity.
-
-
-# @@PLEAC@@_6.11
-begin
- print "Pattern? "
- pat = $stdin.gets.chomp
- Regexp.new(pat)
-rescue
- warn "Invalid Pattern"
- retry
-end
-
-
-# @@PLEAC@@_6.13
-# uses the 'amatch' extension found on:
-# http://raa.ruby-lang.org/project/amatch/
-require 'amatch'
-matcher = Amatch.new('balast')
-#$relative, $distance = 0, 1
-File.open('/usr/share/dict/words').each_line do |line|
- print line if matcher.search(line) <= 1
-end
-__END__
-#CODE
-ballast
-ballasts
-balustrade
-balustrades
-blast
-blasted
-blaster
-blasters
-blasting
-blasts
-
-
-# @@PLEAC@@_6.14
-str.scan(/\G(\d)/).each do |token|
- puts "found #{token}"
-end
-#-----------------------------
-n = " 49 here"
-n.gsub!(/\G /,'0')
-puts n
-#-----------------------------
-str = "3,4,5,9,120"
-str.scan(/\G,?(\d+)/).each do |num|
- puts "Found number: #{num}"
-end
-#-----------------------------
-# Ruby doesn't have the String.pos or a /c re modifier like Perl
-# But it does have StringScanner in the standard library (strscn)
-# which allows similar functionality:
-
-require 'strscan'
-text = 'the year 1752 lost 10 days on the 3rd of September'
-sc = StringScanner.new(text)
-while sc.scan(/.*?(\d+)/)
- print "found: #{sc[1]}\n"
-end
-if sc.scan(/\S+/)
- puts "Found #{sc[0]} after last number"
-end
-#-----------------------------
-# assuming continuing from above:
-puts "The position in 'text' is: #{sc.pos}"
-sc.pos = 30
-puts "The position in 'text' is: #{sc.pos}"
-
-
-# @@PLEAC@@_6.15
-#-----------------------------
-# greedy pattern
-str.gsub!(/<.*>/m,'') # not good
-
-# non-greedy (minimal) pattern
-str.gsub!(/<.*?>/m,'') # not great
-
-
-#-----------------------------
-#<b><i>this</i> and <i>that</i> are important</b> Oh, <b><i>me too!</i></b>
-#-----------------------------
-%r{ <b><i>(.*?)</i></b> }mx
-#-----------------------------
-%r/BEGIN((?:(?!BEGIN).)*)END/
-#-----------------------------
-%r{ <b><i>( (?: (?!</b>|</i>). )* ) </i></b> }mx
-#-----------------------------
-%r{ <b><i>( (?: (?!</[ib]>). )* ) </i></b> }mx
-#-----------------------------
-%r{
- <b><i>
- [^<]* # stuff not possibly bad, and not possibly the end.
- (?:
- # at this point, we can have '<' if not part of something bad
- (?! </?[ib]> ) # what we can't have
- < # okay, so match the '<'
- [^<]* # and continue with more safe stuff
- ) *
- </i></b>
- }mx
-
-
-# @@PLEAC@@_6.16
-#-----------------------------
-$/ = ""
-ARGF.each do |para|
- para.scan %r/
- \b # start at word boundary
- (\S+) # find chunk of non-whitespace
- \b # until a word boundary
- (
- \s+ # followed by whitespace
- \1 # and that same chunk again
- \b # and a word boundary
- ) + # one or more times
- /xi do
- puts "dup word '#{$1}' at paragraph #{$.}"
- end
-end
-#-----------------------------
-astr = 'nobody'
-bstr = 'bodysnatcher'
-if "#{astr} #{bstr}" =~ /^(\w+)(\w+) \2(\w+)$/
- print "#{$2} overlaps in #{$1}-#{$2}-#{$3}"
-end
-#-----------------------------
-#!/usr/bin/ruby -w
-# prime_pattern -- find prime factors of argument using patterns
-ARGV << 180
-cap = 'o' * ARGV.shift
-while cap =~ /^(oo+?)\1+$/
- print $1.size, " "
- cap.gsub!(/#{$1}/,'o')
-end
-puts cap.size
-#-----------------------------
-#diophantine
-# solve for 12x + 15y + 16z = 281, maximizing x
-if ('o' * 281).match(/^(o*)\1{11}(o*)\2{14}(o*)\3{15}$/)
- x, y, z = $1.size, $2.size, $3.size
- puts "One solution is: x=#{x}; y=#{y}; z=#{z}"
-else
- puts "No solution."
-end
-# => One solution is: x=17; y=3; z=2
-
-#-----------------------------
-# using different quantifiers:
-('o' * 281).match(/^(o+)\1{11}(o+)\2{14}(o+)\3{15}$/)
-# => One solution is: x=17; y=3; z=2
-
-('o' * 281).match(/^(o*?)\1{11}(o*)\2{14}(o*)\3{15}$/)
-# => One solution is: x=0; y=7; z=11
-
-('o' * 281).match(/^(o+?)\1{11}(o*)\2{14}(o*)\3{15}$/)
-# => One solution is: x=1; y=3; z=14
-
-
-# @@PLEAC@@_6.17
-# alpha OR beta
-%r/alpha|beta/
-
-# alpha AND beta
-%r/(?=.*alpha)(?=.*beta)/m
-
-# alpha AND beta, no overlap
-%r/alpha.*beta|beta.*alpha/m
-
-# NOT beta
-%r/^(?:(?!beta).)*$/m
-
-# NOT bad BUT good
-%r/(?=(?:(?!BAD).)*$)GOOD/m
-#-----------------------------
-
-if !(string =~ /pattern/) # ugly
- something()
-end
-
-if string !~ /pattern/ # preferred
- something()
-end
-
-
-#-----------------------------
-if string =~ /pat1/ && string =~ /pat2/
- something()
-end
-#-----------------------------
-if string =~ /pat1/ || string =~ /pat2/
- something()
-end
-#-----------------------------
-#!/usr/bin/ruby -w
-# minigrep - trivial grep
-pat = ARGV.shift
-ARGF.each do |line|
- print line if line =~ /#{pat}/o
-end
-#-----------------------------
- "labelled" =~ /^(?=.*bell)(?=.*lab)/m
-#-----------------------------
-$string =~ /bell/ && $string =~ /lab/
-#-----------------------------
-$murray_hill = "blah bell blah "
-if $murray_hill =~ %r{
- ^ # start of string
- (?= # zero-width lookahead
- .* # any amount of intervening stuff
- bell # the desired bell string
- ) # rewind, since we were only looking
- (?= # and do the same thing
- .* # any amount of intervening stuff
- lab # and the lab part
- )
- }mx # /m means . can match newline
-
- print "Looks like Bell Labs might be in Murray Hill!\n";
-end
-#-----------------------------
-"labelled" =~ /(?:^.*bell.*lab)|(?:^.*lab.*bell)/
-#-----------------------------
-$brand = "labelled";
-if $brand =~ %r{
- (?: # non-capturing grouper
- ^ .*? # any amount of stuff at the front
- bell # look for a bell
- .*? # followed by any amount of anything
- lab # look for a lab
- ) # end grouper
- | # otherwise, try the other direction
- (?: # non-capturing grouper
- ^ .*? # any amount of stuff at the front
- lab # look for a lab
- .*? # followed by any amount of anything
- bell # followed by a bell
- ) # end grouper
- }mx # /m means . can match newline
- print "Our brand has bell and lab separate.\n";
-end
-#-----------------------------
-$map =~ /^(?:(?!waldo).)*$/s
-#-----------------------------
-$map = "the great baldo"
-if $map =~ %r{
- ^ # start of string
- (?: # non-capturing grouper
- (?! # look ahead negation
- waldo # is he ahead of us now?
- ) # is so, the negation failed
- . # any character (cuzza /s)
- ) * # repeat that grouping 0 or more
- $ # through the end of the string
- }mx # /m means . can match newline
- print "There's no waldo here!\n";
-end
-=begin
- 7:15am up 206 days, 13:30, 4 users, load average: 1.04, 1.07, 1.04
-
-USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
-
-tchrist tty1 5:16pm 36days 24:43 0.03s xinit
-
-tchrist tty2 5:19pm 6days 0.43s 0.43s -tcsh
-
-tchrist ttyp0 chthon 7:58am 3days 23.44s 0.44s -tcsh
-
-gnat ttyS4 coprolith 2:01pm 13:36m 0.30s 0.30s -tcsh
-=end
-#% w | minigrep '^(?!.*ttyp).*tchrist'
-#-----------------------------
-%r{
- ^ # anchored to the start
- (?! # zero-width look-ahead assertion
- .* # any amount of anything (faster than .*?)
- ttyp # the string you don't want to find
- ) # end look-ahead negation; rewind to start
- .* # any amount of anything (faster than .*?)
- tchrist # now try to find Tom
-}x
-#-----------------------------
-#% w | grep tchrist | grep -v ttyp
-#-----------------------------
-#% grep -i 'pattern' files
-#% minigrep '(?i)pattern' files
-#-----------------------------
-
-
-# @@PLEAC@@_6.20
-ans = $stdin.gets.chomp
-re = %r/^#{Regexp.quote(ans)}/
-case
- when "SEND" =~ re : puts "Action is send"
- when "STOP" =~ re : puts "Action is stop"
- when "ABORT" =~ re : puts "Action is abort"
- when "EDIT" =~ re : puts "Action is edit"
-end
-#-----------------------------
-require 'abbrev'
-table = Abbrev.abbrev %w-send stop abort edit-
-loop do
- print "Action: "
- ans = $stdin.gets.chomp
- puts "Action for #{ans} is #{table[ans.downcase]}"
-end
-
-
-#-----------------------------
-# dummy values are defined for 'file', 'PAGER', and
-# the 'invoke_editor' and 'deliver_message' methods
-# do not do anything interesting in this example.
-#!/usr/bin/ruby -w
-require 'abbrev'
-
-file = 'pleac_ruby.data'
-PAGER = 'less'
-
-def invoke_editor
- puts "invoking editor"
-end
-
-def deliver_message
- puts "delivering message"
-end
-
-actions = {
- 'edit' => self.method(:invoke_editor),
- 'send' => self.method(:deliver_message),
- 'list' => proc {system(PAGER, file)},
- 'abort' => proc {puts "See ya!"; exit},
- "" => proc {puts "Unknown Command"}
-}
-
-dtable = Abbrev.abbrev(actions.keys)
-loop do
- print "Action: "
- ans = $stdin.gets.chomp.delete(" \t")
- actions[ dtable[ans.downcase] || "" ].call
-end
-
-
-# @@PLEAC@@_6.19
-#-----------------------------
-# basically, the Perl Cookbook categorizes this as an
-# unsolvable problem ...
-#-----------------------------
-1 while addr.gsub!(/\([^()]*\)/,'')
-#-----------------------------
-Dear someuser@host.com,
-
-Please confirm the mail address you gave us Wed May 6 09:38:41
-MDT 1998 by replying to this message. Include the string
-"Rumpelstiltskin" in that reply, but spelled in reverse; that is,
-start with "Nik...". Once this is done, your confirmed address will
-be entered into our records.
-
-
-# @@PLEAC@@_6.21
-#-----------------------------
-#% gunzip -c ~/mail/archive.gz | urlify > archive.urlified
-#-----------------------------
-#% urlify ~/mail/*.inbox > ~/allmail.urlified
-#-----------------------------
-#!/usr/bin/ruby -w
-# urlify - wrap HTML links around URL-like constructs
-
-urls = '(https?|telnet|gopher|file|wais|ftp)';
-ltrs = '\w';
-gunk = '/#~:.?+=&%@!\-';
-punc = '.:?\-';
-any = "#{ltrs}#{gunk}#{punc}";
-
-ARGF.each do |line|
- line.gsub! %r/
- \b # start at word boundary
- ( # begin $1 {
- #{urls} : # need resource and a colon
- [#{any}] +? # followed by on or more
- # of any valid character, but
- # be conservative and take only
- # what you need to....
- ) # end $1 }
- (?= # look-ahead non-consumptive assertion
- [#{punc}]* # either 0 or more punctuation
- [^#{any}] # followed by a non-url char
- | # or else
- $ # then end of the string
- )
- /iox do
- %Q|<A HREF="#{$1}">#{$1}</A>|
- end
- print line
-end
-
-
-# @@PLEAC@@_6.23
-%r/^m*(d?c{0,3}|c[dm])(l?x{0,3}|x[lc])(v?i{0,3}|i[vx])$/i
-#-----------------------------
-str.sub!(/(\S+)(\s+)(\S+)/, '\3\2\1')
-#-----------------------------
-%r/(\w+)\s*=\s*(.*)\s*$/ # keyword is $1, value is $2
-#-----------------------------
-%r/.{80,}/
-#-----------------------------
-%r|(\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+)|
-#-----------------------------
-str.gsub!(%r|/usr/bin|,'/usr/local/bin')
-#-----------------------------
-str.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/){ $1.hex.chr }
-#-----------------------------
-str.gsub!(%r{
- /\* # Match the opening delimiter
- .*? # Match a minimal number of characters
- \*/ # Match the closing delimiter
-}xm,'')
-#-----------------------------
-str.sub!(/^\s+/, '')
-str.sub!(/\s+$/, '')
-
-# but really, in Ruby we'd just do:
-str.strip!
-#-----------------------------
-str.gsub!(/\\n/,"\n")
-#-----------------------------
-str.sub!(/^.*::/, '')
-#-----------------------------
-%r/^([01]?\d\d|2[0-4]\d|25[0-5])\.([01]?\d\d|2[0-4]\d|25[0-5])\.
- ([01]?\d\d|2[0-4]\d|25[0-5])\.([01]?\d\d|2[0-4]\d|25[0-5])$/x
-#-----------------------------
-str.sub!(%r|^.*/|, '')
-#-----------------------------
-cols = ( (ENV['TERMCAP'] || " ") =~ /:co#(\d+):/ ) ? $1 : 80;
-#-----------------------------
-name = " #{$0} #{ARGV}".gsub(%r| /\S+/|, ' ')
-#-----------------------------
-require 'rbconfig'
-include Config
-raise "This isn't Linux" unless CONFIG['target_os'] =~ /linux/i;
-#-----------------------------
-str.gsub!(%r/\n\s+/, ' ')
-#-----------------------------
-nums = str.scan(/(\d+\.?\d*|\.\d+)/)
-#-----------------------------
-capwords = str.scan(%r/(\b[^\Wa-z0-9_]+\b)/)
-#-----------------------------
-lowords = str.scan(%r/(\b[^\WA-Z0-9_]+\b)/)
-#-----------------------------
-icwords = str.scan(%r/(\b[^\Wa-z0-9_][^\WA-Z0-9_]*\b)/)
-#-----------------------------
-links = str.scan(%r/<A[^>]+?HREF\s*=\s*["']?([^'" >]+?)[ '"]?>/mi)
-#-----------------------------
-initial = str =~ /^\S+\s+(\S)\S*\s+\S/ ? $1 : ""
-#-----------------------------
-str.gsub!(%r/"([^"]*)"/, %q-``\1''-)
-#-----------------------------
-
-$/ = ""
-sentences = []
-ARGF.each do |para|
- para.gsub!(/\n/, ' ')
- para.gsub!(/ {3,}/,' ')
- sentences << para.scan(/(\S.*?[!?.])(?= |\Z)/)
-end
-
-#-----------------------------
-%r/(\d{4})-(\d\d)-(\d\d)/ # YYYY in $1, MM in $2, DD in $3
-#-----------------------------
-%r/ ^
- (?:
- 1 \s (?: \d\d\d \s)? # 1, or 1 and area code
- | # ... or ...
- \(\d\d\d\) \s # area code with parens
- | # ... or ...
- (?: \+\d\d?\d? \s)? # optional +country code
- \d\d\d ([\s\-]) # and area code
- )
- \d\d\d (\s|\1) # prefix (and area code separator)
- \d\d\d\d # exchange
- $
- /x
-#-----------------------------
-%r/\boh\s+my\s+gh?o(d(dess(es)?|s?)|odness|sh)\b/i
-#-----------------------------
-lines = []
-lines << $1 while input.sub!(/^([^\012\015]*)(\012\015?|\015\012?)/,'')
-
-
-# @@PLEAC@@_7.0
-# An IO object being Enumerable, we can use 'each' directly on it
-File.open("/usr/local/widgets/data").each { |line|
- puts line if line =~ /blue/
-}
-
-logfile = File.new("/var/log/rubylog.txt", "w")
-mysub($stdin, logfile)
-
-# The method IO#readline is similar to IO#gets
-# but throws an exception when it reaches EOF
-f = File.new("bla.txt")
-begin
- while (line = f.readline)
- line.chomp
- $stdout.print line if line =~ /blue/
- end
-rescue EOFError
- f.close
-end
-
-while $stdin.gets # reads from STDIN
- unless (/\d/)
- $stderr.puts "No digit found." # writes to STDERR
- end
- puts "Read: #{$_}" # writes to STDOUT
-end
-
-logfile = File.new("/tmp/log", "w")
-
-logfile.close
-
-# $defout (or its synonym '$>') is the destination of output
-# for Kernel#print, Kernel#puts, and family functions
-logfile = File.new("log.txt", "w")
-old = $defout
-$defout = logfile # switch to logfile for output
-puts "Countdown initiated ..."
-$defout = old # return to original output
-puts "You have 30 seconds to reach minimum safety distance."
-
-
-# @@PLEAC@@_7.1
-source = File.new(path, "r") # open file "path" for reading only
-sink = File.new(path, "w") # open file "path" for writing only
-
-source = File.open(path, File::RDONLY) # open file "path" for reading only
-sink = File.open(path, File::WRONLY) # open file "path" for writing only
-
-file = File.open(path, "r+") # open "path" for reading and writing
-file = File.open(path, flags) # open "path" with the flags "flags" (see examples below for flags)
-
-# open file "path" read only
-file = File.open(path, "r")
-file = File.open(path, File::RDONLY)
-
-# open file "path" write only, create it if it does not exist
-# truncate it to zero length if it exists
-file = File.open(path, "w")
-file = File.open(path, File::WRONLY|File::TRUNC|File::CREAT)
-file = File.open(path, File::WRONLY|File::TRUNC|File::CREAT, 0666) # with permission 0666
-
-# open file "path" write only, fails if file exists
-file = File.open(path, File::WRONLY|File::EXCL|File::CREAT)
-file = File.open(path, File::WRONLY|File::EXCL|File::CREAT, 0666)
-
-# open file "path" for appending
-file = File.open(path, "a")
-file = File.open(path, File::WRONLY|File::APPEND|File::CREAT)
-file = File.open(path, File::WRONLY|File::APPEND|File::CREAT, 0666)
-
-# open file "path" for appending only when file exists
-file = File.open(path, File::WRONLY|File::APPEND)
-
-# open file "path" for reading and writing
-file = File.open(path, "r+")
-file = File.open(path, File::RDWR)
-
-# open file for reading and writing, create a new file if it does not exist
-file = File.open(path, File::RDWR|File::CREAT)
-file = File.open(path, File::RDWR|File::CREAT, 0600)
-
-# open file "path" reading and writing, fails if file exists
-file = File.open(path, File::RDWR|File::EXCL|File::CREAT)
-file = File.open(path, File::RDWR|File::EXCL|File::CREAT, 0600)
-
-
-# @@PLEAC@@_7.2
-# No problem with Ruby since the filename doesn't contain characters with
-# special meaning; like Perl's sysopen
-File.open(filename, 'r')
-
-
-# @@PLEAC@@_7.3
-File.expand_path('~root/tmp')
-#=> "/root/tmp"
-File.expand_path('~rpcuser')
-#=> "/var/lib/nfs"
-
-# To expand ~/.. it explicitely needs the environment variable HOME
-File.expand_path('~/tmp')
-#=> "/home/gc/tmp"
-
-
-# @@PLEAC@@_7.4
-# The exception raised in Ruby reports the filename
-File.open('afile')
-
-
-# @@PLEAC@@_7.5
-# Standard Ruby distribution provides the following useful extension
-require 'tempfile'
-# With the Tempfile class, the file is automatically deleted on garbage
-# collection, so you won't need to remove it, later on.
-tf = Tempfile.new('tmp') # a name is required to create the filename
-
-# If you need to pass the filename to an external program you can use
-# File#path, but don't forget to File#flush in order to flush anything
-# living in some buffer somewhere.
-tf.flush
-system("/usr/bin/dowhatever #{tf.path}")
-
-fh = Tempfile.new('tmp')
-fh.sync = true # autoflushes
-10.times { |i| fh.puts i }
-fh.rewind
-puts 'Tmp file has: ', fh.readlines
-
-
-# @@PLEAC@@_7.6
-while (DATA.gets) do
- # process the line
-end
-__END__
-# your data goes here
-# __DATA__ doesn't exist in Ruby
-
-#CODE
-# get info about the script (size, date of last modification)
-kilosize = DATA.stat.size / 1024
-last_modif = DATA.stat.mtime
-puts "<P>Script size is #{kilosize}"
-puts "<P>Last script update: #{last_modif}"
-__END__
-# DO NOT REMOVE THE PRECEEDING LINE.
-# Everything else in this file will be ignored.
-#CODE
-
-
-# @@PLEAC@@_7.7
-while line = gets do
- # do something with line.
-end
-
-# or
-while gets do
- # do something with $_
-end
-
-# or more rubyish
-$stdun.each do |line|
- # do stuff with line
-end
-
-
-# ARGF may makes this more easy
-# this is skipped if ARGV.size==0
-ARGV.each do |filename|
- # closing and exception handling are done by the block
- open(filename) do |fd|
- fd.each do |line|
- # do stuff with line
- end
- end rescue abort("can't open %s" % filename)
-end
-
-# globbing is done in the Dir module
-ARGV = Dir["*.[Cch]"] if ARGV.empty?
-
-# note: optparse is the preferred way to handle this
-if (ARGV[0] == '-c')
- chop_first += 1
- ARGV.shift
-end
-
-
-# processing numerical options
-if ARGV[0] =~ /^-(\d+)$/
- columns = $1
- ARGV.shift
-end
-
-# again, better to use optparse:
-require 'optparse'
-nostdout = 0
-append = 0
-unbuffer = 0
-ignore_ints = 0
-ARGV.options do |opt|
- opt.on('-n') { nostdout +=1 }
- opt.on('-a') { append +=1 }
- opt.on('-u') { unbuffer +=1 }
- opt.on('-i') { ignore_ints +=1 }
- opt.parse!
-end or abort("usage: " + __FILE__ + " [-ainu] [filenames]")
-
-# no need to do undef $/, we have File.read
-str = File.read(ARGV[0])
-
-# again we have File.read
-str = File.read(ARGV[0])
-
-# not sure what this should do:
-# I believe open the file, print filename, lineno and line:
-ARGF.each_with_index do |line, idx|
- print ARGF.filename, ":", idx, ";", line
-end
-
-# print all the lines in every file passed via command line that contains login
-ARGF.each do |line|
- puts line if line =~ /login/
-end
-#
-# even this would fit
-#%ruby -ne "print if /f/" 2.log
-#
-
-ARGF.each { |l| puts l.downcase! }
-
-#------------------
-#!/usr/bin/ruby -p
-# just like perl's -p
-$_.downcase!
-#
-
-# I don't know who should I trust.
-# perl's version splits on \w+ while python's on \w.
-
-chunks = 0
-
-File.read(ARGV[0]).split.each do |word|
- next if word =~ /^#/
- break if ["__DATA__", "__END__"].member? word
- chunks += 1
-end
-
-print "Found ", chunks, " chunks\n"
-
-
-# @@PLEAC@@_7.8
-old = File.open(old_file)
-new = File.open(new_file, "w")
-while old.gets do
- # change $_, then...
- new.print $_
-end
-old.close
-new.close
-File.rename(old_file, "old.orig")
-File.rename(new_file, old_file)
-
-while old.gets do
- if $. == 20 then # we are at the 20th line
- new.puts "Extra line 1"
- new.puts "Extra line 2"
- end
- new.print $_
-end
-
-while old.gets do
- next if 20..30 # skip the 20th line to the 30th
- # Ruby (and Perl) permit to write if 20..30
- # instead of if (20 <= $.) and ($. <= 30)
- new.print $_
-end
-
-
-# @@PLEAC@@_7.9
-#% ruby -i.orig -pe 'FILTER COMMAND' file1 file2 file3 ...
-#
-#-----------------------------
-##!/usr/bin/ruby -i.orig -p
-# filter commands go here
-#-----------------------------
-
-#% ruby -pi.orig -e 'gsub!(/DATE/){Time.now)'
-
-# effectively becomes:
-ARGV << 'I'
-oldfile = ""
-while gets
- if ARGF.filename != oldfile
- newfile = ARGF.filename
- File.rename(newfile, newfile + ".orig")
- $stdout = File.open(newfile,'w')
- oldfile = newfile
- end
- gsub!(/DATE/){Time.now}
- print
-end
-$stdout = STDOUT
-#-----------------------------
-#% ruby -i.old -pe 'gsub!(%r{\bhisvar\b}, 'hervar')' *.[Cchy]
-
-#-----------------------------
-# set up to iterate over the *.c files in the current directory,
-# editing in place and saving the old file with a .orig extension
-$-i = '.orig' # set up -i mode
-ARGV.replace(Dir['*.[Cchy]'])
-while gets
- if $. == 1
- print "This line should appear at the top of each file\n"
- end
- gsub!(/\b(p)earl\b/i, '\1erl') # Correct typos, preserving case
- print
- ARGF.close if ARGF.eof
-end
-
-
-# @@PLEAC@@_7.10
-File.open('itest', 'r+') do |f| # open file for update
- lines = f.readlines # read into array of lines
- lines.each do |it| # modify lines
- it.gsub!(/foo/, 'QQQ')
- end
- f.pos = 0 # back to start
- f.print lines # write out modified lines
- f.truncate(f.pos) # truncate to new length
-end # file is automatically closed
-#-----------------------------
-File.open('itest', 'r+') do |f|
- out = ""
- f.each do |line|
- out << line.gsub(/DATE/) {Time.now}
- end
- f.pos = 0
- f.print out
- f.truncate(f.pos)
-end
-
-# @@PLEAC@@_7.11
-File.open('infile', 'r+') do |f|
- f.flock File::LOCK_EX
- # update file
-end
-#-----------------------------
-File::LOCK_SH # shared lock (for reading)
-File::LOCK_EX # exclusive lock (for writing)
-File::LOCK_NB # non-blocking request
-File::LOCK_UN # free lock
-#-----------------------------
-unless f.flock File::LOCK_EX | File::LOCK_NB
- warn "can't get immediate lock: blocking ..."
- f.flock File::LOCK_EX
-end
-#-----------------------------
-File.open('numfile', File::RDWR|File::CREAT) do |f|
- f.flock(File::LOCK_EX)
- num = f.gets.to_i || 0
- f.pos = 0
- f.truncate 0
- f.puts num + 1q
-end
-
-
-# @@PLEAC@@_7.12
-output_handle.sync = true
-# Please note that like in Perl, $stderr is already unbuffered
-#-----------------------------
-#!/usr/bin/ruby -w
-# seeme - demo stdio output buffering
-$stdout.sync = ARGV.size > 0
-print "Now you don't see it..."
-sleep 2
-puts "now you do"
-#-----------------------------
-$stderr.sync = true
-afile.sync = false
-#-----------------------------
-# assume 'remote_con' is an interactive socket handle,
-# but 'disk_file' is a handle to a regular file.
-remote_con.sync = true # unbuffer for clarity
-disk_file.sync = false # buffered for speed
-#-----------------------------
-require 'socket'
-sock = TCPSocket.new('www.ruby-lang.org', 80)
-sock.sync = true
-sock.puts "GET /en/ HTTP/1.0 \n\n"
-resp = sock.read
-print "DOC IS: #{resp}\n"
-
-
-# @@PLEAC@@_7.13
-#-----------------------------
-# assumes fh1, fh2, fh2 are oen IO objects
-nfound = select([$stdin, fh1, fh2, fh3], nil, nil, 0)
-nfound[0].each do |file|
- case file
- when fh1
- # do something with fh1
- when fh2
- # do something with fh2
- when fh3
- # do something with fh3
- end
-end
-#-----------------------------
-input_files = []
-# repeat next line for all in-files to poll
-input_files << fh1
-if nfound = select(input_files, nil, nil, 0)
- # input ready on files in nfound[0]
-end
-
-
-# @@PLEAC@@_8.0
-#-----------------------------
-# datafile is a file or IO object
-datafile.readlines.each { |line|
- line.chomp!
- size = line.length
- puts size
-}
-#-----------------------------
-datafile.readlines.each { |line|
- puts line.chomp!.length
-}
-#-----------------------------
-lines = datafile.readlines
-#-----------------------------
-whole_file = file.read
-#-----------------------------
-# ruby -040 -e 'word = gets; puts "First word is #{word}"'
-#-----------------------------
-# ruby -ne 'BEGIN { $/="%%\n" }; $_.chomp; puts $_ if( $_=~/Unix/i)' fortune.dat
-#-----------------------------
-handle.print "one", "two", "three" # "onetwothree"
-puts "Baa baa black sheep." # sent to $stdout
-#-----------------------------
-buffer = handle.read(4096)
-rv = buffer.length
-#-----------------------------
-handle.truncate(length)
-open("/tmp#{$$}.pid", 'w') { |handle| handle.truncate(length) }
-#-----------------------------
-pos = datafile.pos # tell is an alias of pos
-puts "I'm #{pos} bytes from the start of datafile"
-#-----------------------------
-logfile.seek(0, IO::SEEK_END)
-datafile.seek(pos) # IO::SEEK_SET is the default
-out.seek(-20, IO::SEEK_CUR)
-#-----------------------------
-written = datafile.syswrite(mystring)
-raise RunTimeError unless written == mystring.length
-block = infile.sysread(256) # no equivalent to perl offset parameter in sysread
-puts "only read #{block.length} bytes" if 256 != block.length
-#-----------------------------
-pos = handle.sysseek(0, IO::SEEK_CUR) # don't change position
-
-
-# @@PLEAC@@_8.1
-while (line = fh.gets)
- line.chomp!
- nextline = nil
- line.gsub!(/\\$/) { |match| nextline = fh.gets; '' }
- if (nextline != nil)
- line += nextline
- redo
- end
- # process full record in line here
-end
-#-----------------------------
-# DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) \
-# $(TEXINFOS) $(INFOS) $(MANS) $(DATA)
-# DEP_DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) \
-# $(TEXINFOS) $(INFO_DEPS) $(MANS) $(DATA) \
-# $(EXTRA_DIST)
-#-----------------------------
-line.gsub!(/\\\s*$/, '') {
- # as before
-}
-
-
-# @@PLEAC@@_8.2
-#-----------------------------
-count = `wc -l < #{filename}`
-fail "wc failed: #{$?}" if $? != 0
-count.chomp!
-#-----------------------------
-count = 0
-File.open(file, 'r') { |fh|
- count += 1 while fh.gets
-}
-# count now holds the number of lines read
-#-----------------------------
-count = 0
-while (chunk = file.sysread(2**16))
- count += chunk.count("\n")
-end rescue EOFError
-#-----------------------------
-File.open(filename,'r') { |fh|
- count += 1 while fh.gets
-}
-# count now holds the number of lines read
-#-----------------------------
-# As ruby doesn't quite have an equivalent to using a for
-# statement as in perl, I threw this in
-count = File.readlines(filename).size
-#-----------------------------
-1 while file.gets
-count = $.
-#-----------------------------
-$/ = ''
-open(filename, 'r') { |fh|
- 1 while fh.gets
- para_count = $.
-} rescue fail("can't open #{filename}: $!")
-#-----------------------------
-
-
-# ^^PLEAC^^_8.3
-#-----------------------------
-while (gets)
- split.each { |chunk|
- # do something with chunk
- }
-end
-#-----------------------------
-while (gets)
- gsub(/(\w[\w'-]*)/) { |word|
- # do something with word
- }
-end
-#-----------------------------
-# Make a word frequency count
-# normally hashes can be created using {} or just Hash.new
-# but we want the default value of an entry to be 0 instead
-# of nil. (nil can't be incremented)
-seen = Hash.new(0)
-while (gets)
- gsub(/(\w[\w'-]*)/) { |word|
- seen[word.downcase] += 1
- }
-end
-# output hash in a descending numeric sort of its values
-seen.sort { |a,b| b[1] <=> a[1] }.each do |k,v|
- printf("%5d %s\n", v, k )
-end
-
-#-----------------------------
-# Line frequency count
-seen = Hash.new(0)
-while (gets)
- seen[$_.downcase] += 1
-end
-seen.sort { |a,b| b[1] <=> a[1] }.each do |k,v|
- printf("%5d %s\n", v, k )
-end
-#-----------------------------
-
-
-# @@PLEAC@@_8.4
-#-----------------------------
-# instead of file handle FILE, we can just
-# use a string containing the filename
-File.readlines(file).each { |line|
- # do something with line
-}
-#-----------------------------
-File.readlines(file).reverse_each { |line|
- # do something with line
-}
-#-----------------------------
-# the variable lines might have been created
-# this way
-# lines = File.readlines(file)
-#
-# normally one would use the reverse_each, but
-# if you insist on using a numerical index to
-# iterate over the lines array...
-(lines.size - 1).downto(0) { |i|
- line = lines[i]
-}
-#-----------------------------
-# the second readlines argument is a the
-# record separator $/, just like perl, a blank
-# separator splits the records into paragraphs
-File.readlines(file, '').each { |paragraph|
- # do something with paragraph
- puts "->Paragraph #{paragraph}"
-}
-#-----------------------------
-
-
-# @@PLEAC@@_8.6
-
-$/ = "%\n";
-srand;
-
-File.open('/usr/share/fortune/humorists').each do |line|
- adage = line if rand($.) < 1
-end
-
-puts adage;
-
-
-# @@PLEAC@@_8.10
-begin
- fh = File.open(file, "r+")
- addr = fh.tell unless fh.eof while fh.gets
- fh.truncate(addr)
-rescue SystemCallError
- $stderr.puts "#$!"
-end
-
-
-# @@PLEAC@@_9.0
-entry = File.stat("/usr/bin/vi")
-entry = File.stat("/usr/bin")
-entry = File.stat(INFILE)
-
-entry = File.stat("/usr/bin/vi")
-ctime = entry.ctime
-size = entry.size
-
-f = File.open(filename, "r")
-
-## There is no -T equivalent in Ruby, but we can still test emptiness
-if test(?s, filename)
- puts "#{filename} doesn't have text in it."
- exit
-end
-
-Dir.new("/usr/bin").each do |filename|
- puts "Inside /usr/bin is something called #{filename}"
-end
-
-
-# @@PLEAC@@_9.1
-file = File.stat("filename")
-readtime, writetime = file.atime, file.mtime
-file.utime(readtime, writetime)
-
-SECONDS_PER_DAY = 60 * 60 * 24
-file = File.stat("filename")
-atime, mtime = file.atime, file.mtime
-
-atime -= 7 * SECONDS_PER_DAY
-mtime -= 7 * SECONDS_PER_DAY
-
-File.utime(atime, mtime, file)
-mtime = File.stat(file).mtime
-File.utime(Time.new, mtime, file)
-File.utime(Time.new, File.stat("testfile").mtime, file)
-
-#-----------------------------
-#!/usr/bin/ruby -w
-## uvi - vi a file without changing it's access times
-
-if ARGV.length != 1
- puts "usage: uvi filename"
- exit
-end
-file = ARGV[0]
-atime, mtime = File.stat(file).atime, File.stat(file).mtime
-system(ENV["EDITOR"] || "vi", file)
-File.utime(atime, mtime, file)
-#-----------------------------
-
-
-# @@PLEAC@@_9.2
-File.unlink(FILENAME)
-
-err_flg = false
-filenames.each do |file|
- begin
- File.unlink(file)
- rescue
- err_flg = $!
- end
-end
-err_flg and raise "Couldn't unlink all of #{filenames.join(" ")}: #{err_flg}"
-
-File.unlink(file)
-
-count = filenames.length
-filenames.each do |file|
- begin
- File.unlink(file)
- rescue
- count -= 1
- end
-end
-if count != filenames.length
- STDERR.puts "could only delete #{count} of #{filenames.length} files"
-end
-
-
-# @@PLEAC@@_9.3
-require "ftools"
-File.copy(oldfile, newfile)
-
-infile = File.open(oldfile, "r")
-outfile = File.open(newfile, "w")
-
-blksize = infile.stat.blksize
-# This doesn't handle partial writes or ^Z
-# like the Perl version does.
-while (line = infile.read(blksize))
- outfile.write(line)
-end
-
-infile.close
-outfile.close
-
-system("cp #{oldfile} #{newfile}") # unix
-system("copy #{oldfile} #{newfile}") # dos, vms
-
-require "ftools"
-File.copy("datafile.dat", "datafile.bak")
-File.move("datafile.new", "datafile.dat")
-
-
-# @@PLEAC@@_9.4
-$seen = {} # must use global var to be seen inside of method below
-
-def do_my_thing(filename)
- dev, ino = File.stat(filename).dev, File.stat(filename).ino
- unless $seen[[dev, ino]]
- # do something with $filename because we haven't
- # seen it before
- end
- $seen[[dev, ino]] = $seen[[dev, ino]].to_i + 1
-end
-
-files.each do |filename|
- dev, ino = File.stat(filename).dev, File.stat(filename).ino
- if !$seen.has_key?([dev, ino])
- $seen[[dev, ino]] = []
- end
- $seen[[dev, ino]].push(filename)
-end
-
-$seen.keys.sort.each do |devino|
- ino, dev = devino
- if $seen[devino].length > 1
- # $seen[devino] is a list of filenames for the same file
- end
-end
-
-
-# @@PLEAC@@_9.5
-Dir.open(dirname) do |dir|
- dir.each do |file|
- # do something with dirname/file
- puts file
- end
-end
-# Dir.close is automatic
-
-# No -T equivalent in Ruby
-
-dir.each do |file|
- next if file =~ /^\.\.?$/
- # ...
-end
-
-def plainfiles(dir)
- dh = Dir.open(dir)
- dh.entries.grep(/^[^.]/).
- map {|file| "#{dir}/#{file}"}.
- find_all {|file| test(?f, file)}.
- sort
-end
-
-
-# @@PLEAC@@_9.6
-list = Dir.glob("*.c")
-
-dir = Dir.open(path)
-files = dir.entries.grep(/\.c$/)
-dir.close
-
-files = Dir.glob("*.c")
-files = Dir.open(path).entries.grep(/\.[ch]$/i)
-
-dir = Dir.new(path)
-files = dir.entries.grep(/\.[ch]$/i)
-
-begin
- d = Dir.open(dir)
-rescue Errno::ENOENT
- raise "Couldn't open #{dir} for reading: #{$!}"
-end
-
-files = []
-d.each do |file|
- puts file
- next unless file =~ /\.[ch]$/i
-
- filename = "#{dir}/#{file}"
- # There is no -T equivalent in Ruby, but we can still test emptiness
- files.push(filename) if test(?s, filename)
-end
-
-dirs.entries.grep(/^\d+$/).
- map { |file| [file, "#{path}/#{file}"]} .
- select { |file| test(?d, file[1]) }.
- sort { |a,b| a[0] <=> b[0] }.
- map { |file| file[1] }
-
-
-# @@PLEAC@@_9.7
-require 'find'
-Find.find(dirlist) do |file|
- # do whatever
-end
-
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-Find.find(*argv) do |file|
- print file, (test(?d, file) ? "/\n" : "\n")
-end
-
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-sum = 0
-Find.find(*argv) do |file|
- size = test(?s, file) || 0
- sum += size
-end
-puts "#{argv.join(' ')} contains #{sum} bytes"
-
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-saved_size, saved_name = -1, ""
-Find.find(*argv) do |file|
- size = test(?s, file) || 0
- next unless test(?f, file) && size > saved_size
- saved_size = size
- saved_name = file
-end
-puts "Biggest file #{saved_name} in #{argv.join(' ')} is #{saved_size}"
-
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-age, name = nil
-Find.find(*argv) do |file|
- mtime = File.stat(file).mtime
- next if age && age > mtime
- age = mtime
- name = file
-end
-puts "#{name} #{age}"
-
-#-----------------------------
-#!/usr/bin/ruby -w
-# fdirs - find all directories
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-File.find(*argv) { |file| puts file if test(?d, file) }
-#-----------------------------
-
-
-# @@PLEAC@@_9.8
-require 'fileutils'
-
-puts "Usage #{$0} dir ..." if ARGV.empty?
-ARGV.each do |dir|
- FileUtils.rmtree(dir)
-end
-
-
-# @@PLEAC@@_9.9
-require 'ftools'
-names.each do |file|
- newname = file
- begin
- File.move(file, newname)
- rescue Errno::EPERM
- $stderr.puts "Couldn't rename #{file} to #{newname}: #{$!}"
- end
-end
-
-require 'ftools'
-op = ARGV.empty? ? (raise "Usage: rename expr [files]\n") : ARGV.shift
-argv = ARGV.empty? ? $stdin.readlines.map { |f| f.chomp } : ARGV
-argv.each do |file|
- was = file
- file = eval("file.#{op}")
- File.move(was, file) unless was == file
-end
-
-
-# @@PLEAC@@_9.10
-base = File.basename(path)
-dir = File.dirname(path)
-# ruby has no fileparse equivalent
-dir, base = File.split(path)
-ext = base.scan(/\..*$/).to_s
-
-path = '/usr/lib/libc.a'
-file = File.basename(path)
-dir = File.dirname(path)
-
-puts "dir is #{dir}, file is #{file}"
-# dir is /usr/lib, file is libc.a
-
-path = '/usr/lib/libc.a'
-dir, filename = File.split(path)
-name, ext = filename.split(/(?=\.)/)
-puts "dir is #{dir}, name is #{name}, ext is #{ext}"
-# NOTE: The Ruby code prints
-# dir is /usr/lib, name is libc, extension is .a
-# while the Perl code prints a '/' after the directory name
-# dir is /usr/lib/, name is libc, extension is .a
-
-# No fileparse_set_fstype() equivalent in ruby
-
-def extension(path)
- ext = path.scan(/\..*$/).to_s
- ext.sub(/^\./, "")
-end
-
-
-# @@PLEAC@@_9.11
-#-----------------------------
-#!/usr/bin/ruby -w
-# symirror - build spectral forest of symlinks
-
-require 'find'
-require 'fileutils'
-
-raise "usage: #{$0} realdir mirrordir" unless ARGV.size == 2
-
-srcdir,dstdir = ARGV
-srcmode = File::stat(srcdir).mode
-Dir.mkdir(dstdir, srcmode & 07777) unless test(?d, dstdir)
-
-# fix relative paths
-Dir.chdir(srcdir) {srcdir = Dir.pwd}
-Dir.chdir(dstdir) {dstdir = Dir.pwd}
-
-Find.find(srcdir) do |srcfile|
- if test(?d, srcfile)
- dest = srcfile.sub(/^#{srcdir}/, dstdir)
- dmode = File::stat(srcfile).mode & 07777
- Dir.mkdir(dest, dmode) unless test(?d, dest)
- a = Dir["#{srcfile}/*"].reject{|f| test(?d, f)}
- FileUtils.ln_s(a, dest)
- end
-end
-
-
-# @@PLEAC@@_9.12
-# we use the Getopt/Declare library here for convenience:
-# http://raa.ruby-lang.org/project/getoptdeclare/
-#-----------------------------
-#!/usr/bin/ruby -w
-# lst - list sorted directory contents (depth first)
-
-require 'find'
-require 'etc'
-require "Getopt/Declare"
-
-# Note: in the option-spec below there must by at least one hard
-# tab in between each -option and its description. For example
-# -i <tab> read from stdin
-
-opts = Getopt::Declare.new(<<'EOPARAM')
- ============
- Input Format:
- -i read from stdin
- ============
- Output Format:
- -l long listing
- -r reverse listing
- ============
- Sort on: (one of)
- -m mtime (modify time - default)
- {$sort_criteria = :mtime}
- -u atime (access time)
- {$sort_criteria = :atime}
- -c ctime (inode change time)
- {$sort_criteria = :ctime}
- -s size
- {$sort_criteria = :size}
- [mutex: -m -u -c -s]
-
-EOPARAM
-
-$sort_criteria ||= :mtime
-files = {}
-DIRS = opts['-i'] ? $stdin.readlines.map{|f|f.chomp!} : ARGV
-DIRS.each do |dir|
- Find.find(dir) do |ent|
- files[ent] = File::stat(ent)
- end
-end
-entries = files.keys.sort_by{|f| files[f].send($sort_criteria)}
-entries = entries.reverse unless opts['-r']
-
-entries.each do |ent|
- unless opts['-l']
- puts ent
- next
- end
- stats = files[ent]
- ftime = stats.send($sort_criteria == :size ? :mtime : $sort_criteria)
- printf "%6d %04o %6d %8s %8s %8d %s %s\n",
- stats.ino,
- stats.mode & 07777,
- stats.nlink,
- ETC::PASSWD[stats.uid].name,
- ETC::GROUP[stats.gid].name,
- stats.size,
- ftime.strftime("%a %b %d %H:%M:%S %Y"),
- ent
-end
-
-
-# @@PLEAC@@_10.0
-def hello
- $greeted += 1 # in Ruby, a variable beginning with $ is global (can be any type of course)
- puts "hi there!"
-end
-
-# We need to initialize $greeted before it can be used, because "+=" is waiting a Numeric object
-$greeted = 0
-hello # note that appending () is optional to function calls with no parameters
-
-
-# @@PLEAC@@_10.1
-# In Ruby, parameters are named anyway
-def hypotenuse(side1, side2)
- Math.sqrt(side1**2 + side2**2) # the sqrt function comes from the Math module
-end
-diag = hypotenuse(3, 4)
-
-puts hypotenuse(3, 4)
-
-a = [3, 4]
-print hypotenuse(*a) # the star operator will magically convert an Array into a "tuple"
-
-both = men + women
-
-# In Ruby, all objects are references, so the same problem arises; we then return a new object
-nums = [1.4, 3.5, 6.7]
-def int_all(n)
- n.collect { |v| v.to_i }
-end
-ints = int_all(nums)
-
-nums = [1.4, 3.5, 6.7]
-def trunc_em(n)
- n.collect! { |v| v.to_i } # the bang-version of collect modifies the object
-end
-trunc_em(nums)
-
-# Ruby has two chomp version:
-# ``chomp'' chomps the record separator and returns what's expected
-# ``chomp!'' does the same but also modifies the parameter object
-
-
-# @@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/bench/example.rhtml b/bench/example.rhtml
deleted file mode 100644
index 041bec1..0000000
--- a/bench/example.rhtml
+++ /dev/null
@@ -1,561 +0,0 @@
-<% @title = 'Moderatoren-Interface' %>
-
-<dl>
- <dt><%= link_to 'Proben', :controller => '/admin/proben' %></dt>
- <dd>Die angesetzten Proben des Orchesters</dd>
- <dt><%= link_to 'Auftritte', :controller => '/admin/proben' %></dt>
- <dd>Die Auftritte des Orchesters</dd>
- <%- if @valid_user and @valid_user.admin? -%>
- <dt><%= link_to 'Benutzer', :controller => '/admin/user' %></dt>
- <dd>Benutzer organisieren (nur für den Admin)</dd>
- <%- end -%>
-</dl>
-<% @title = 'Anmeldung' %>
-
-<%= render :partial => 'user_form', :object => @user %>
-<% @title = 'Administrator erstellen' %>
-
-<%= render :partial => 'user_form', :object => @user %>
-<%= form_tag %>
-<table>
- <tr>
- <td>Name:</td>
- <td><%= text_field 'user', 'name' %></td>
- </tr>
- <tr>
- <td>Passwort:</td>
- <td><%= password_field 'user', 'password' %></td>
- </tr>
- <tr>
- <td></td>
- <td><%= submit_tag 'Anmelden' %></td>
-</table>
-<%= end_form_tag %>
-<% @title = 'Neuer Benutzer' -%>
-<%= error_messages_for :user %>
-<%= render :partial => 'form', :object => @user %>
-<%= form_tag %>
-<table>
- <tr>
- <td>Name:</td>
- <td><%= text_field 'user', 'name' %></td>
- </tr>
- <tr>
- <td>Passwort:</td>
- <td><%= password_field 'user', 'password' %></td>
- </tr>
- <tr>
- <td></td>
- <td><%= submit_tag 'Anlegen' %></td>
-</table>
-<%= end_form_tag %>
-<% @title = 'Auftritte' %>
-
-<table cellspacing="0" summary="Auftritte: Wann treten wir Wo auf?">
- <%= render :partial => 'head' %>
- <%= render :partial => 'day', :collection => @days %>
-</table>
-<% day, auftritte = *day -%>
-<%
- for auftritt in auftritte
--%>
-
-<tr>
- <td class="pplan_datum">
- <%= colorize day.to_s(:dots) if day %>
- <% if day and day.wday == 6 %><br /><em>Samstag</em><% end %>
- </td>
- <td class="pplan_zeit">
- <%= colorize auftritt.time %>
- </td>
- <td class="pplan_stueck">
- <%= colorize auftritt.program %>
- <%= link_to 'E', :controller => 'admin/auftritte', :action => :edit, :id => auftritt %>
- </td>
- <td class="pplan_besetzung">
- <%= colorize(auftritt.place, 'Ort: ') + '<br />' unless auftritt.place.blank? %>
- </td>
-</tr>
-
-<%
- day = nil
- end
--%>
-<tr>
- <th scope="col" class="pplan_datum">Datum</th>
- <th scope="col" class="pplan_zeit">Zeit</th>
- <th scope="col" class="pplan_stueck">Programm</th>
- <th scope="col" class="pplan_besetzung">Ort</th>
-</tr>
-<% @title = "Besetzung - #{@instrument.name}" %>
-
-<p>
-<%= pluralize(@members.size, 'Schüler spielt', 'Schüler spielen') %> <%= h @instrument.name %>:
-</p>
-
-<table class="members">
- <%= render :partial => 'member', :collection => @members %>
-</table>
-<% @title = 'Besetzung: %d Mitglieder' % Member.count -%>
-
-<div class="page-links">
-<% if params[:action] == 'all' -%>
-<%= link_to 'seitenweise', :action => :index %>
-<% else -%>
-<%= link_to_if @member_pages.current.previous, '<<', :page => @member_pages.current.previous %>
-| <%= link_to 'alle', :action => :all %> |
-<%= link_to_if @member_pages.current.next, '>>', :page => @member_pages.current.next %>
-<% end -%>
-| <%= link_to 'Nach Instrumenten', :action => :select_instrument %>
-</div>
-
-<table class="members">
-<%= render :partial => 'member', :collection => @members %>
-</table>
-<% @title = "Besetzung - Instrument wählen" %>
-
-<ul>
-<% for instr in @instruments -%>
-<li>
- <%= link_to h(instr.name), :action => :instrument, :id => instr.name %>
- <span class="counter">(<%= h instr.members.size %>)</span>
-</li>
-<% end -%>
-</ul>
-<% @title = "Besetzung: #{@member.name}" -%>
-
-<dl>
-
-<dt>Instrument / Aufgabe:</dt>
-<dd><%= link_to_instruments_of @member %></dd>
-
-<dt>Geburtstag:</dt>
-<dd><%= h @member.birthday.to_s(:dots) %></dd>
-
-<dt>Adresse:</dt>
-<dd><%= h @member.street %><br /><%= h @member.plz %></dd>
-
-<dt>Telefon:</dt>
-<dd><%= h @member.phone %></dd>
-
-<dt>Email:</dt>
-<dd><%= mail_to @member.email, @member.email, :encode => 'javascript' %></dd>
-
-</dl>
-<tr class="member">
- <td><%= link_to member.name, :action => :show, :id => member %>:
- <%= link_to_instruments_of member %>
- </td>
-</tr>
-<% @title = 'Arbeitsgruppen' -%>
-<p>
- Die Arbeitsgruppen sind verantwortlich für die Organisation und Durchführung verschiedenster Aufgaben:
-</p>
-
-<ul class="liste">
-
- <li><b>Plakate und Konzertkarten</b>
- <ul>
- <li>Frau Schraps</li>
- <li>Paul-Robert Achcenich</li>
- <li>Josefine Dahms</li>
- </ul>
- </li>
-
- <li><b>Noten</b><br />
- <ul>
- <li>Frau Puppe</li>
- <li>Theresa Rebin</li>
- </ul>
- </li>
-
- <li><b>Programme</b><br />
- <ul>
- <li>?</li>
- </ul>
- </li>
-
- <li><b>Instrumentenstransporte</b><br />
- <ul>
- <li>Frau Feldmann</li>
- <li>Knut Müller</li>
- <li>Patrick Wolter</li>
- <li>Alexaner Wolf</li>
- </ul>
- </li>
-
- <li><b>Internetseite</b><br />
- <ul>
- <li>Frau Sternbeck</li>
- <li>Uwe Ritzschke</li>
- <li>Paul-Robert Achcenich</li>
- <li>Knut Müller</li>
- <li>Alexander Wolf</li>
- </ul>
- </li>
-
-</ul>
-<% @title = 'Chronik' -%>
-<p>
- Das Jugendsinfonieorchester Marzahn-Hellersdorf wurde im Januar 2005 an der
- Musikschule Marzahn-Hellersdorf gegründet und gab im Mai 2005 sein erstes
- umjubeltes Konzert im FEZ Wuhlheide. Das Orchester umfasst zur Zeit ca. 65
- jugendliche Musiker und soll auf die Größe eines ausgewachsenen
- Sinfonieorchesters erweitert werden (80-100 Musiker).
-</p>
-
-<p>
- Als musikalischer Leiter konnte der Dirigent und Echo-Preisträger Jobst
- Liebrecht gewonnen werden, der die Musikschule schon aus einer früheren
- Zusammenarbeit anlässlich der Kinderoper 'Pollicino' von Hans Werner Henze
- kennt. Das Orchester probt wöchentlich. Neben den Tuttiproben finden außerdem
- ebenfalls wöchentlich Stimmsatzproben statt, die von Lehrkräften betreut werden.
- Das gemeinsame Ziel ist der Aufbau eines leistungsstarken, lebendigen
- Klangkörpers, der die Jugendlichen und die Zuhörer ganz neu und direkt für die
- Orchestermusik begeistert und diese Musik in den sozialen Brennpunkt Marzahn-
- Hellersdorf trägt.
-</p>
-
-<p>
- Im Jahr sind etwa 2-3 Konzertprogramme geplant, mit denen wir in Konzertsälen
- auftreten. Das erste Konzert des Jugendsinfonieorchesters Marzahn-Hellersdorf
- wurde von DeutschlandRadio Kultur aufgezeichnet und in einer Sendung mit dem
- Titel &bdquo;EINSTAND: Nicht nur auf der Strasse herumhängen&rdquo; porträtiert.
- Wir wollen außerdem vor Ort in Marzahn und Hellersdorf in die Öffentlichkeit
- gehen und spielen, um so für die Kultur zu werben und auch weitere Kinder und
- Jugendliche für die Musik und fürs Mitmachen zu gewinnen. Durch die Einrichtung
- eines zusätzlichen Vororchesters wird längerfristig versucht, die Arbeit auf ein
- breites Fundament zu stellen, eine Werkstatt, ein musikalisches Bauhaus zu
- gründen. Wenn die Orchesterarbeit erfolgreich angelaufen ist, sollen auch
- übergreifende Projekte (Theater, Tanz, Chor) stattfinden.
-</p>
-
-<p>
- Das Orchester will Musik von heute spielen in jedem Sinn, ob es sich um Stücke
- aus der sinfonischen Tradition handelt oder um zeitgenössische Musik. Wir kennen
- keine Berührungsängste und sind neugierig auf Musik aller Art und möchten diese
- Neugierde mit unserem Publikum teilen.
-</p>
-<% @title = 'Dirigent - Jobst Liebrecht' -%>
-<p>
- <%= image_tag 'jobstliebrecht.jpg', :alt => 'Jobst Liebrecht', :title => 'Jobst Liebrecht', :class => 'pic_right' %>
- Jobst Liebrecht studierte Dirigieren an der Musikhochschule in München und bei Peter Eötvös. Sein spezielles Interesse
- für neue Musik führte schnell zur Zusammenarbeit mit renommierten Ensembles auf dem Gebiet wie dem Ensemble Modern,
- Frankfurt, dem Klangforum-Ensemble, Wien, dem Ensemble Köln sowie dem Ensemble United Berlin. Aufnahmen entstanden beim
- WDR, beim DeutschlandRadio Berlin, beim BR und beim SFB. Er dirigierte u.a. das Rundfunk Sinfonieorchester Berlin, die
- Duisburger Philharmoniker und das Münchner Kammerorchester sowie in den Opernhäusern in Halle und Giessen. Tourneen im
- Ausland führten ihn nach Argentinien, Georgien, Südkorea und in die USA.
-</p>
-
-<p>
- Zu den Ur- und Erstaufführungen, die er betreut hat, gehören die Opern 'Lunu' von Moritz Eggert, 'Gloria von Jaxtberg' von
- HK Gruber sowie in Zusammenarbeit mit dem Regisseur Einar Schleef das Musiktheaterspiel 'Der Golem in Bayreuth' von Ulla
- Berkewicz/Lesch Schmidt am Wiener Burgtheater.
-</p>
-
-<p>
- Jobst Liebrecht war mehrere Jahre lang Assistent von Hans Werner Henze und auch immer wieder pädagogisch tätig. Seine
- Aufnahme von Henzes Märchenoper 'Pollicino', die als CD bei Wergo erschienen ist, wurde mit dem ECHO-Preis 2004 in der
- Sparte 'Klassik für Kinder' ausgezeichnet.
-</p>
-
-<p>
- Als Komponist ist Jobst Liebrecht mit Liedern, Kammermusik sowie Bühnenmusiken an die Öffentlichkeit getreten.
-</p>
-<% message, backtrace = session[:boom] -%>
-<% @title = 'Fehler in Zeile %d' % [backtrace[/line\s+#(\d+)/,1]] -%>
-<div class="flash">
-<div class="error"><%= h message %></div>
-</div>
-<%= debug backtrace %>
-<% cache :action_suffix => (action = params[:action]) do -%>
-<p>
-Der Inhalt für die Aktion <%= h action.inspect %> fehlt noch.
-</p>
-<% end -%>
-<% @title = 'Schulferien Berlin' -%>
-<p>
- Unser Orchester besteht zu einem sehr großen Teil aus Schülern und auch die
- Musikschule, der die meisten von uns entstammen, hat in den Schulferien
- geschlossen.<br />
- Deshalb finden innerhalb der <strong>Berliner Ferienzeiten keine Proben</strong> statt.
-</p>
-
-<table cellspacing="0" summary="Schulferien" class="ferien">
- <tr>
- <th scope="col" class="ferien_zeitraum">Zeitraum</th>
- <th scope="col" class="ferien_jahr">2006</th>
- <th scope="col" class="ferien_jahr">2007</th>
- <th scope="col" class="ferien_jahr">2008</th>
- </tr>
-
- <tr>
- <td class="ferien_zeitraum">
- Winter</td>
- <td class="ferien_jahr">
- 30.01. - 03.02.</td>
- <td class="ferien_jahr">
- 05.02. - 10.02.</td>
- <td class="ferien_jahr">
- 04.02. - 09.02.</td>
- </tr>
-
- <tr>
- <td class="ferien_zeitraum">
- Ostern/Frühjahr</td>
- <td class="ferien_jahr">
- 10.04. - 21.04.</td>
- <td class="ferien_jahr">
- 02.04. - 13.04.</td>
- <td class="ferien_jahr">
- 17.03. - 28.03.</td>
- </tr>
-
- <tr>
- <td class="ferien_zeitraum">
- Himmelf./Pfingsten</td>
- <td class="ferien_jahr">
- 30.04. / 18.05.</td>
- <td class="ferien_jahr">
- 30.04. / 18.05.</td>
- <td class="ferien_jahr">
- 02.05.</td>
- </tr>
-
- <tr>
- <td class="ferien_zeitraum">
- Sommer</td>
- <td class="ferien_jahr">
- 06.07. - 19.08.</td>
- <td class="ferien_jahr">
- 12.07. - 25.08.</td>
- <td class="ferien_jahr">
- 17.07. - 30.08.</td>
- </tr>
-
- <tr>
- <td class="ferien_zeitraum">
- Herbst</td>
- <td class="ferien_jahr">
- 02.10. - 14.10.</td>
- <td class="ferien_jahr">
- 15.10. - 27.10.</td>
- <td class="ferien_jahr">
- </td>
- </tr>
-
- <tr>
- <td class="ferien_zeitraum">
- Weihnachten</td>
- <td class="ferien_jahr">
- 27.12. - 05.01.07</td>
- <td class="ferien_jahr">
- 24.12. - 04.01.08</td>
- <td class="ferien_jahr">
- </td>
- </tr>
-
-</table>
-<% @title = 'Termine' -%>
-
-<ul>
- <li><%= link_to 'Auftritte', :controller => '/auftritte' %></li>
- <li><%= link_to 'Schulferien', :controller => '/content', :action => :schulferien %></li>
-</ul>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de">
-<head>
- <%= tag 'meta', :'http-equiv' => 'content-language', :content => 'de' %>
- <%= tag 'meta', :'http-equiv' => 'content-type', :content => 'text/html; charset=UTF-8' %>
- <meta name="AUTHOR" content="Knut Müller, Alexander Wolf, Uwe Ritzschke, Paul-Robert Achcenich" />
- <meta name="Publisher" content="Knut Müller, Alexander Wolf, Uwe Ritzschke, Paul-Robert Achcenich" />
- <meta name="Copyright" content="Knut Müller, Alexander Wolf, Uwe Ritzschke, Paul-Robert Achcenich, 2006" />
- <meta name="Keywords" content="Jugendsinfonieorchester,Marzahn,Hellersdorf,Marzahn-Hellersdorf,Berlin,Orchester,Jobst Liebrecht,FEZ,Pollicino,Moritz Eggert,Popel,Konzert" />
- <meta name="Description" content="JSO - JugendSinfonieOrchester der Musikschule Marzahn-Hellerdorf in Berlin" />
- <meta name="Page-topic" content="JSO Marzahn-Hellersdorf - " />
-
- <meta name="Audience" content="Alle" />
- <meta name="content-language" content="DE" />
- <meta name="Page-Type" content="Homepage" />
- <meta name="robots" content="all" />
-
- <title>JSO<%-if @title-%> - <%= h @title %><%- end -%></title>
- <%= stylesheet_link_tag '/rcss/main' %>
- <%#= stylesheet_link_tag 'main' %>
- <%= javascript_include_tag 'nospam' %>
- <%#= javascript_include_tag :defaults %>
-</head>
-
-<body>
-
-<table style="width:100%; height:100%;" cellspacing="10">
- <tr>
- <td style="height:120px; width:15%;text-align:center;vertical-align:middle;">
- <%= image_tag 'JSO-Logo.gif', :alt => 'JSO-Logo' %>
- </td>
- <td id="title">
- <div id="musikschule"><a href="http://www.musikschule-marzahn-hellersdorf.de">Musikschule Marzahn Hellersdorf</a></div>
- <div id="orchester"><strong>j</strong>ugend<strong>s</strong>infonie<strong>o</strong>rchester</div>
- </td>
- </tr>
- <tr>
- <td style="width:15%;">
-<% if valid_user -%>
-<ul>
- <li class="menu2"><%= link_to "Logout #{valid_user.name}", :controller => '/admin/admin', :action => :logout %></li>
-</ul>
-<% end -%>
-<% cache :controller => 'menu', :action => 'main_menu' do -%>
- <%= render_component :controller => 'menu', :action => 'index' %>
-<% end -%>
- </td>
- <td id="main">
-<% unless @flash.keys.empty? -%>
-<div class="flash">
- <%- for kind, msg in @flash -%>
- <div class="<%= h kind %>"><%= h msg %></div>
- <%- end -%>
-</div>
-<% end -%>
-<%= content_tag 'h3', h(@title) if @title %>
-<%= @content_for_layout %>
- </td>
- </tr>
- <tr>
- <td style="height:80px; width:15%;">
- </td>
- <td style="height:80px;">
- <div style="position:relative; top:80px; right:0px; text-align:right; font-size: x-small; color: #003;">
- powered by <a href="http://rubyonrails.org">Ruby on Rails</a> <%= Rails::Info.properties.value_for 'Rails version' %> [<%= h RAILS_ENV[/^./] %>]
- <%= image_tag 'css.png', :alt => 'valid CSS', :title => 'valid Cascading Style Sheet', :style => 'display: inline; vertical-align: middle' %>
- <%= image_tag 'xhtml11.png', :alt => 'valid XHTML 1.1', :title => 'valid eXtensible Hypertext Markup Language 1.1', :style => 'display: inline; vertical-align: middle' %>
- </div>
- </td>
- </tr>
-</table>
-
-</body>
-
-</html>
-<% @title = 'Ãœbersicht' -%>
-
-<h4>nächste Probe</h4>
-<table cellspacing="0" summary="Probenplan: Wann wird Was geprobt?" class="proben">
- <%= render :partial => 'proben/head' %>
- <%= render :partial => 'proben/day', :object => @next_probe %>
-</table>
-<h4><%= link_to 'weitere Proben...', :controller => 'proben' %></h4>
-
-<h4>nächster Auftritt</h4>
-<table cellspacing="0" summary="Auftritte: Wann treten wir Wo auf?" class="auftritte">
- <%= render :partial => 'auftritte/head' %>
- <%= render :partial => 'auftritte/day', :object => @next_auftritt %>
-</table>
-<h4><%= link_to 'mehr Auftritte...', :controller => 'auftritte' %></h4>
-<ul>
- <%= category 'Ãœbersicht', home_url %>
- <%= subcat 'Wer sind wir?', :wer %>
- <%= subcat 'Dirigent' %>
- <%= subcat 'Besetzung', url_for(:controller => '/besetzung') %>
- <%= subcat 'Repertoire' %>
-
- <%= category 'Termine' %>
- <%= subcat 'Auftritte', url_for(:controller => '/auftritte', :action => :plan) %>
- <%= subcat 'Schulferien' %>
-
- <%= category 'Probenplan', url_for(:controller => '/proben', :action => :plan) %>
-
- <%= category 'Organisation' %>
- <%= subcat 'Orchesterrat' %>
- <%= subcat 'Arbeitsgruppen' %>
-
- <%= category 'Chronik' %>
- <%= subcat 'Konzerte' %>
- <%= subcat 'Audio' %>
- <%= subcat 'Presse' %>
-
- <%= category 'Links', '#' %>
- <%= subcat 'Bilderseite', 'http://musikschule.iden04.de' %>
- <%= subcat 'Musikschule', 'http://www.musikschule-marzahn-hellersdorf.de' %>
-
- <li><br /></li>
-
- <%= category 'Kontakt' %>
-</ul>
-<% @title = 'Probenplan' %>
-
-<table cellspacing="0" summary="Probenplan: Wann wird Was geprobt?">
- <%= render :partial => 'head' %>
- <%= render :partial => 'day', :collection => @days %>
-</table>
-
-<p style="font-size:14px; margin-top:-10px; padding-top:0px; padding-left:40px;">
-Ort (wenn nicht anders angegeben): Schule am Pappelhof
-</p>
-
-<%= render_partial 'raum' %>
-<% day, proben = *day -%>
-<%
- for probe in proben
--%>
-
-<tr>
- <td class="pplan_datum">
- <%= colorize day.to_s(:dots) if day %>
- <% if day and day.wday == 6 %><br /><em>Samstag</em><% end %>
- </td>
- <td class="pplan_zeit">
- <%= colorize probe.time %>
- </td>
- <td class="pplan_stueck">
- <%= colorize(probe.place, 'Ort: ') + '<br />' unless probe.place.blank? %>
- <%= colorize probe.program %>
- <%= link_to 'E', :controller => 'admin/proben', :action => :edit, :id => probe %>
- </td>
- <td class="pplan_besetzung">
- <%= h probe.instrumentation %>
- </td>
-</tr>
-
-<%
- day = nil
- end
--%>
-<tr>
- <th scope="col" class="pplan_datum">Datum</th>
- <th scope="col" class="pplan_zeit">Zeit</th>
- <th scope="col" class="pplan_stueck">Stücke</th>
- <th scope="col" class="pplan_besetzung">Besetzung</th>
-</tr>
-<h4>Probenräume</h4>
-<table cellspacing="0" summary="Probenräume: Wer probt Wo?">
- <tr>
- <th scope="col" class="praum_wer">Wer</th>
- <th scope="col" class="praum_raum">Raum</th>
- <th scope="col" class="praum_adresse">Adresse</th>
-
- </tr>
- <tr>
- <td class="praum_wer">Streicher</td>
- <td class="praum_raum">Schule am Pappelhof<br />(Raum Nr.)</td>
- <td class="praum_adresse">(Anschrifft Pappelhofschule)</td>
- </tr>
- <tr>
-
- <td class="praum_wer">Blechbläser</td>
- <td class="praum_raum">Musikschule Marzahn<br />(Raum Nr.)</td>
- <td class="praum_adresse">(Anschrifft Musikscule Marzahn)</td>
- </tr>
- <tr>
- <td class="praum_wer">Holzbläser</td>
-
- <td class="praum_raum">Schule am Pappelhof<br />(Raum Nr.)</td>
- <td class="praum_adresse">(Anschrifft Pappelhofschule)</td>
- </tr>
- <tr>
- <td class="praum_wer">...</td>
- <td class="praum_raum">(Ort)<br />(Raum Nr.)</td>
-
- <td class="praum_adresse">(Anschrifft)</td>
- </tr>
-</table>
diff --git a/bench/example.rubyfast b/bench/example.rubyfast
deleted file mode 100644
index a3367d1..0000000
--- a/bench/example.rubyfast
+++ /dev/null
@@ -1,10428 +0,0 @@
-#n ist das anzuzeigende Feld, o die Zwischenablage für eine #Iteration p dient dazu zu jedem Feld die Nachbarschaft zu definieren.
-n=Array.new
-o=Array.new
-p=Array.new
-x=0
-
-#Anlegen des Arrays n
-while x<=10000
- n[x]=0
- x +=1
-end
-
-#Anlegen des Arrays p
-x=0
-while x<=10000
- p[x]=3
- x +=1
-end
-
-
-n[2]=1
-n[102]=1
-n[202]=1
-
-loop{
-x=0
-#Die nachbarschaften aller Felder werden überprüft
-while x<10000
-#a bis f dienen dazu die Nachbarschaft festzulegen. Man stelle sich die #Zahl von 1 bis 64 im Binärcode vor 1 bedeutet an 0 aus
- a=p[x]/32<1 ? 0 : 1
- b=(p[x]%32)/16<1 ? 0 : 1
- c=(p[x]%16)/8<1 ? 0 : 1
- d=(p[x]%8)/4<1 ? 0 : 1
- e=(p[x]%4)/2<1 ? 0 : 1
- f=(p[x]%2)<1 ? 0 : 1
-#t= n[x-201].to_i*b+n[x-200].to_i*d+n[x-199].to_i*b+
- #n[x-102].to_i*a+n[x-101].to_i*e+n[x-100].to_i+n[x-99].to_i*f+n[x-98]#to_i*a+
- #n[x-2].to_i*c+n[x-1].to_i+n[x+1].to_i+n[x+2].to_i*c+
- #n[x+98].to_i*a+n[x+99].to_i*f+n[x+100].to_i+n[x+101].#to_i*e+n[x+102].to_i*a+
- #n[x+199].to_i*b+n[x+200].to_i*d+n[x+201].to_i*b
- #Die Summe der Felder die zur Nachbarschaft gerechnet werden a bis f
-#sind hierbei Multiplikatoren mit dem Wert 1oder 0
-
-t=(x-201>=0? n[x-201].to_i : 0)*b+(x-200>=0? n[x-200].to_i : 0)*d+(x-199>=0? n[x-199].to_i : 0)*b+
- (x-102>=0? n[x-102].to_i : 0)*a+(x-101>=0?n[x-101].to_i : 0)*e+n[x-100].to_i+(x-99>=0? n[x-99].to_i : 0)*f+(x-98>=0? n[x-98].to_i : 0)*a+
- (x-2>=0? n[x-2].to_i : 0)*c+(x-1>=0? n[x-1].to_i : 0)+n[x+1].to_i+n[x+2].to_i*c+
- n[x+98].to_i*a+n[x+99].to_i*f+n[x+100].to_i+n[x+101].to_i*e+n[x+102].to_i*a+
- n[x+199].to_i*b+n[x+200].to_i*d+n[x+201].to_i*b
-
-#Bedingungen wann eine Zelle lebt,stirbt oder geboren wird im Moment
-#sind die regeln 3 Nachbarn =Geburt und Nachbarn 3,2=Überleben
-#sonst Tod
- if t==3
- o[x]=1
- elsif t==2 and n[x]=1
- o[x]=1
- else
- o[x]=0
- end
- x+=1
-end
-#wird überschrieben
-n=o
-
-#und die Ausgabe folgt
-g=%w{}
-x=0
-
-while x<100
- g[x]=n[100*x+1..100*x+100]
- x+=1
-end
-x=0
-
-while x<100
- puts"#{g[x]}"
- x+=1
-end
-
-puts""
-sleep(10)
-}
-
-1E1E1
-puts 30.send(:/, 5) # prints 6
-
-"instance variables can be #@included, #@@class_variables and #$globals as well."
-
-#%W[ but #@0illegal_values look strange.]
-
-%s#ruby allows strange#{constructs}.
-%s#ruby allows strange#$constructs
-%s#ruby allows strange#@@constructs
-
-%r\VERY STRANGE!\x00
-
-~%r#<XMP>#i .. ~%r#</XMP>#i;
-
-a = <<"EOF"
-This is a multiline here document
-terminated by EOF on a line by itself
-EOF
-
-b=(p[x] %32)/16<1 ? 0 : 1
-
-<<""
-#{test}
-#@bla
-#die suppe!!!
-\xfffff
-
-super <<-EOE % [
- EOE
-
-<<X
-X
-X
-%s(uninter\)pre\ted)
-%q(uninter\)pre\ted)
-%Q(inter\)pre\ted)
-:"inter\)pre\ted"
-:'uninter\'pre\ted'
-
-%q[haha! [nesting [rocks] ! ] ]
-
-
-##################################################################
-class NP
-def initialize a=@p=[], b=@b=[]; end
-def +@;@b<<1;b2c end;def-@;@b<<0;b2c end
-def b2c;if @b.size==8;c=0;@b.each{|b|c<<=1;c|=b};send(
- 'lave'.reverse,(@p.join))if c==0;@p<<c.chr;@b=[] end
- self end end ; begin _ = NP.new end
-c
-# ^ This is a bug :(
-
-# The Programming Language `NegaPosi'
-+-+--++----+--+-+++--+-------+--++--+++---+-+++-+-+-+++-----+++-_
-+--++++--+---++-+-+-+++--+--+-+------+--++++-++---++-++---++-++-_
-+++--++-+-+--++--+++--+------+----+--++--+++-++-+----++------+--_
--+-+----+++--+--+----+--+--+-++-++--+++-++++-++-----+-+-+----++-_
----------+-+---- _
-##################################################################
-
-
-# date: 03/18/2004
-# title: primes less than 1000 ( 2005 Obfuscated Ruby Contest )
-# author: Jim Lawless
-# email: jimbo at radiks dotski net
-# comments: This program will display all positive prime integers
-# less than 1000. Program licens is the same as the Ruby
-# license ( http://www.ruby-lang.org/en/LICENSE.txt )
-
- $e=""
-
-def a()
- $a=$a+1
-end
-
-def b()
- $a=$a+5
-end
-
-def c()
- $e=$e+$a.chr
-end
-
-def d()
- $a=10
-end
-
-def e()
- $a=$a+16
-end
-
-d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;e;e;a;a;a;c;d;e;e;b;b;
-a;c;d;c;d;e;e;e;e;e;e;b;b;a;a;a;c;d;e;e;e;e;e;b;b;a;a;a;a;c;d;e;e;e;e;
-e;b;b;a;a;a;a;a;c;d;e;e;e;e;e;e;a;a;c;d;e;e;e;e;e;b;b;a;c;d;e;b;a;c;
-d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;e;e;a;a;c;d;e;e;b;a;a;
-c;d;e;e;b;a;c;d;e;e;b;a;c;d;e;e;b;a;c;d;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;b;
-b;a;a;a;a;a;c;d;e;e;e;a;a;a;c;d;e;e;b;a;a;a;c;d;c;d;e;b;a;a;a;a;a;c;d;e;
-e;e;e;e;b;b;a;a;c;d;e;e;e;e;e;e;a;a;a;a;a;c;d;e;e;e;e;e;e;b;b;a;c;
-d;e;e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;e;e;e;a;a;a;c;d;e;
-e;b;a;c;d;c;d;e;e;e;e;e;e;b;b;a;a;a;c;d;e;e;e;e;e;b;b;a;a;a;a;c;d;e;e;
-e;e;e;b;b;a;a;a;a;a;c;d;e;e;e;e;e;e;a;a;c;d;e;e;e;e;e;b;b;a;c;d;e;b;
-a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;b;b;a;a;a;a;a;c;d;e;e;e;a;a;c;d;e;b;
-a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;b;a;c;d;c;d;e;e;e;e;e;b;b;a;
-a;a;a;a;c;d;e;e;e;e;e;b;b;a;a;c;d;e;b;b;a;a;a;a;c;d;e;b;a;c;d;e;b;b;a;
-a;a;a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;e;a;a;a;a;c;
-d;e;e;e;e;e;e;a;a;a;c;d;e;e;e;e;e;e;a;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;
-a;a;c;d;e;e;e;e;e;e;b;b;a;c;d;e;e;e;e;e;e;a;a;c;d;e;e;e;e;e;e;a;a;a;
-a;a;c;d;e;b;b;a;a;a;a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;b;b;a;a;a;a;a;
-c;d;e;b;b;a;a;a;a;a;c;d;e;b;b;a;a;a;a;a;c;d;e;e;e;a;a;a;c;d;e;e;e;a;a;
-a;c;d;e;e;b;a;c;d;e;b;b;a;a;a;a;a;c;d;e;b;a;c;d;c;d;e;b;a;a;a;a;a;c;d;e;e;
-e;e;e;b;b;a;a;c;d;e;e;e;e;e;e;a;a;a;a;a;c;d;e;e;e;e;e;e;b;b;a;c;d;e;
-e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;e;e;e;a;a;a;c;d;e;e;
-b;a;a;c;d;c;d;e;e;e;e;e;b;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;c;d;e;e;e;e;e;
-b;b;a;c;d;e;e;e;e;e;b;a;a;c;d;e;e;e;e;e;e;a;c;d;c;d;e;e;e;e;e;b;b;a;c;
-d;e;e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;c;d;e;b;a;a;a;a;a;
-c;d;e;e;e;e;e;b;b;a;a;a;a;a;c;d;e;e;e;a;a;a;c;d;e;b;a;a;a;a;a;c;d;e;e;
-e;e;e;b;b;a;a;a;a;a;c;d;e;e;a;c;d;e;e;b;a;a;c;d;c;d;e;e;e;e;e;b;b;a;a;
-a;a;a;c;d;e;e;e;e;e;b;b;a;a;c;d;e;b;a;c;d;e;b;b;a;a;a;a;c;d;e;b;b;a;a;
-a;a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;b;b;a;a;a;a;a;c;d;e;b;b;b;a;c;d;e;
-b;a;a;a;a;a;c;d;e;e;e;e;e;b;b;a;a;a;a;a;c;d;e;b;b;a;a;a;a;a;c;d;e;e;
-e;a;a;a;a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;b;b;a;a;
-a;a;a;c;d;c;d;e;e;e;e;e;b;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;c;d;e;e;e;e;e;
-b;b;a;c;d;e;e;e;e;e;b;a;a;c;d;e;e;e;e;e;e;a;c;d;c;d;e;e;e;e;e;b;b;a;c;
-d;e;e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;c;d;e;e;e;e;e;b;b;
-a;c;d;e;e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;c;d;e;e;e;e;e;
-b;b;a;a;a;a;a;c;d;e;e;e;e;e;b;b;a;a;c;d;e;b;b;a;a;a;a;c;d;e;b;a;a;a;
-a;a;c;d;e;e;e;e;e;b;b;a;a;c;d;e;e;e;e;e;e;a;a;a;a;a;c;d;e;e;e;e;e;e;
-b;b;a;c;d;e;e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;e;e;e;a;
-a;a;c;d;e;e;e;a;a;a;c;d;e;e;b;a;c;d;e;b;b;a;a;a;a;a;c;d;e;b;a;c;d;c;d;e;e;
-e;e;e;e;b;a;c;d;e;e;e;e;e;e;b;b;a;c;d;e;e;e;e;e;e;b;a;a;a;a;a;c;d;e;
-e;e;e;e;e;b;a;a;a;a;c;d;e;b;a;c;d;e;b;a;a;a;c;d;e;b;a;a;a;a;c;d;e;e;e;
-e;e;e;e;a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;e;e;e;e;
-e;e;a;a;a;c;d;e;b;a;c;d;e;e;e;e;e;b;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;
-a;a;a;c;d;e;b;a;c;d;e;e;e;e;e;e;b;a;c;d;e;e;e;e;e;e;b;a;a;a;c;d;e;e;e;
-e;e;b;b;a;a;a;a;a;c;d;e;e;e;e;e;e;a;a;a;c;d;e;e;e;e;e;b;b;a;c;d;e;b;
-a;a;a;c;d;c;d;e;e;e;e;e;b;b;a;c;d;e;e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;
-a;a;a;a;a;c;d;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;b;a;c;
-d;e;e;e;a;a;a;c;d;e;b;a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;
-d;e;b;a;c;d;e;e;a;c;d;e;b;a;c;d;e;e;b;a;a;c;d;c;d;e;e;e;e;e;b;b;a;c;d;e;e;e;
-e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;c;d;e;b;a;c;d;e;b;a;c;d;e;b;
-a;c;d;e;b;a;c;d;e;b;a;c;d;e;b;a;c;d;e;b;a;c;eval $e
-
-$_=%{q,l= %w{Ruby\\ Quiz Loader}
-n,p,a= "\#{q.do#{%w{w a n c}.sort{|o,t|t<=>o}}se.d\x65l\x65t\x65(' ')}.com/",
-{"bmJzcA==\n".\x75np\x61ck("m")[0]=>" ","bHQ=\n".\x75np\x61ck((?n-1).chr)[0]=>
-:<,"Z3Q=\n".\x75np\x61ck("m")[0]=>:>,"YW1w\n".\x75np\x61ck((?l+1).chr)[0]=>:&},
-[[/^\\s+<\\/div>.+/m,""],[/^\\s+/,""],[/\n/,"\n\n"],[/<br \\/>/,"\n"],
-[/<hr \\/>/,"-="*40],[/<[^>]+>/,""],[/^ruby/,""],[/\n{3,}/,"\n\n"]];p\165ts"
-\#{l[0..-3]}ing...\n\n";send(Kernel.methods.find_all{|x|x[0]==?e}[-1],
-"re\#{q[5...8].downcase}re '111112101110-117114105'.scan(/-|\\\\d{3}/).
-inject(''){|m,v|v.length>1?m+v.to_i.chr: m+v}");o#{%w{e P}.sort.join.downcase
-}n("http://www.\#{n}"){|w|$F=w.read.sc\x61n(/li>.+?"([^"]+)..([^<]+)/)};\160uts\
-"\#{q}\n\n";$F.\145\141ch{|e|i=e[0][/\\d+/];s="%2s. %s"%[i,e[1]];i.to_i%2==0 ?
-\160ut\x73(s) : #{%w{s p}[-1]}rint("%-38s "%s)};p\x72\x69\x6et"\n? ";e\x76al(
-['puts"\n\#{l[0..3]}ing...\n\n"','$c=gets.chomp.to_i'].sort.join(";"));#{111.chr
-}pen("http://www.\#{n}"+$F[$c-1][0]){|n|$_=n.read[/^\\s+<span.+/m];#{('a'.."z").
-to_a[10-5*2]}.e\141ch{|(z,f)|\x67sub!(z,f)};\147sub!(/&(\\w+);/){|y|p.
-ke\171\077($1)?p[$1]:y};while$_=~/([^\n]{81,})/:z=$1.dup;f=$1.dup;f[f.rindex(
-" ",80),1]="\n";f.s\165b!(/\n[ \t]+/,"\n");s\165b!(/\#{R\x65g\x65xp.
-\x65scap\x65(z)}/,f)end};while\040\163ub!(/^(?:[^\n]*\n){20}/, ""):puts"\#$&
---\x4dO\x52E--";g=$_;g#{"\145"}ts;;#{"excited"[0..4].delete("c")}\040if$_[0]==?q
-$_=g;end;$_.d#{"Internet Service Provider".scan(/[A-Z]/).join.downcase
-}lay};eval$_
-
- d=[30644250780,9003106878,
- 30636278846,66641217692,4501790980,
- 671_24_603036,131_61973916,66_606629_920,
- 30642677916,30643069058];a,s=[],$*[0]
- s.each_byte{|b|a<<("%036b"%d[b.
- chr.to_i]).scan(/\d{6}/)}
- a.transpose.each{ |a|
- a.join.each_byte{\
- |i|print i==49?\
- ($*[1]||"#")\
- :32.chr}
- puts
- }
-
-#! /usr/bin/env ruby
-# License: If Ruby is licensed to the general public in a certain way, this is also licensed in that way.
-require'zlib';eval(Zlib::Inflate.inflate("x\332\355WKo\333F\020\276\367W\250\262\001\222\tM\357\246M\017\242\211\242h\200\036\212`\201\026\350\205`\f=h\233\301Zt%\273A-2\277\275\363\315\222\334\241,#v\214\366T\331\262\326\303y\3177\263\243M\371\347]\265)\203UuYnoO\257Wo\203\364>[T\353U\265\276L\257\353\325\235-'\277\226\233ui\323Uy1\251\027\027\341\253\371\346r\e\245u\366\216\205f\263\367\357\336&\353\362S\010zr=\277\3315w\315]r[\237o\333\344c]\255#>\343O\025\352\037\334\177\341\367\364\271\t\003\245\337|\027\304\364aM@:\363\260\316>\237\232\323(\326\252(\327\253\t\275\323\332h\253\224V\306d\247\037\362\371\311}\321\314f\356\363C\016\311\342\365\361ij\026\037\313\345\355\3577\363e\231\224\363\345\325y\315\204]\263l\3620\177\317\241\024M\376\263\235o\267Et\222/\223%\037\213\374D\323\373M\3214Kv-\373<\361\026\233&\\\304\253,\354\270\263\314)\232\3748\311\247]z\216v\3136\235\306\323\243\035\262\263\214\332\f\024\342\257\327\345\264\230\205\313o36\3122\254e2\260\236\2610\202\354\037\260\256 (f=/\313:Z\024\245\313\244Zoo\347\353ey~]\336^\325\253-\a\273k\252fqv6\235\333j\276\355\236tV\252\230\377F\276\n\333\277\257\241\345\206\262\323\306G\273\352\340\203t\332\246\2441`'\316\316\266\245\275H\0032\377l\253\017,=42E\002\360\236\246\345_s;Y\274^\305\367Q\233\036\233\276\016\312\2450=\256=\305U\202\230\254\"\222\265\004\217\237~\373\345\017\"h\243\210\307j\235\251\205V8\353\304X\372!1CGc-\251\240\337\020\317\361#\036\023\n\2556\254Cg3\002}\265\356s\235\202K[K\022\020 \243\206\216\241p3\33255\350\232\036\030q$\233\344!\363\204^},$\023Xg\235:\364r1\"1\344\277\261\207\031(\301DE\260\344\026Y\177\345\036\221\204mP\263\266Mk\305\366\210%3\220\302S\322\306IR\316\377!\203 S\336\310\216\215\203\315\002-\211 5D2\257\210\302\321p\234\364\205\222Jj\220\022E\321h\347\223RQ*94K\022\243\314H`4{LV\003\021N\f\333\364I\347l\327UR\305t\340\332i>\241x=Mu4R\245\373\223\244\251NB\211\247\236\3465\253^bx\332Yc\263\252M\220b\253\220\310\004\331\242\020,`\005T\021Y\251P@\020\365Ax\310z\364\264\240\265vj2\037?0\v\"en\244\374\251\032\225\253v\346\253\3712\215\032\322(o\206~A\006\010\f\324\22357\026\"\316\024\365\021\360@\277:\363.$\f\342\016$\200\v\341\302\230\020\340\341\201K\017\270+i\326-\312\313j\235\n[\376({\330u\254\266\334\034\031\367%:CK\210{\311h\aQH\333Q\023\250\210;e\360\322\362\213\202\247\216\266\340C&(p\274HT7\336&B\352\300\036z\206\204\375 \032z\304\233\217\034\267AK\207R\363\213\324u\334\203\272h\234 \304&\364S\302]|\024\233b\000\023E\034\005\300!\330\2274\026\205\316\363\203\364\"\316\245!\242\360Y?4\204b\023.\2009\036X\300\213p\200]\304\324\200$^\204\025\222D\325X \363\324\004\223\205\207\241M\245\352\341(s\3415\260w\226\313=\2422 \200\177\344\355\211\3350\004\341\217\207\215r%x\030\302\304\230\335{#\250#o\204h\327;\220\242\275B%j&\343e\005\226/\r\200\035\035\206K\243\027\216Z\230\323.\335\356^!\vF\002K\366\246kG\321\364E\301\362\250\275a\f\031\207i%\216\342&ie\205\260\324}\272\252ho\222\306\370\362!}6\364C\003\2717\206'!.\315\036mhMm\370\252\241\365\221g\275\326A\302\254\270X,\371\353\232:\222\321\253\025\217v%\222\023!\243r\272\364(\376\177\236\374\233\363\3048\330b\241xdTp\325\321\377\3428F\234\214\263\357\255f\324\306\226\257\022\"\000\354\003\024C\207\na\353\240&O\305\376\004ncy\350\f\276\357+Q|\201bBi\206\277\345u\251\273\310\367\242\303*\204d\n\271}\016\2345r8\034\201[\343:>\364*\242\266\025+HZ\263e\212\0247q\357\310X\267[\333(9_o}P\201\324>\266\364\000\217hh\352\225a\213q\260\031\334\022sg\360\e\206\234B=\246\2421\341e\364\270\321\224\347\0056L\267\227)\244\210\307\027\257<\343\257\000\303\264u{\235\326\352i\303^\332\200\n\236\243a\277\034J#~S\335'2\371\001q\3745$\356\027^\371\325\344\331\036\362\004\267\330\251<\212\237\257\345kr\371\302d\362r\376\344d\252C\311\374R6\017e\375\005\271yAV\363/\257\345\261(\340hW\020\222\a\027k)60\354\217\363\3501\263rt\0364\025\025|\265\031\355\276d\357\3159\367\225\025\223U\273n\027\324\321H\031\030\036\357\356\377\010\266\337\374\003\3375Q\335"))
-#include "ruby.h" /*
- /sLaSh *
- oBfUsCaTeD RuBy *
- cOpYrIgHt 2005 *
-bY SiMoN StRaNdGaArD *
- #{X=320;Y=200;Z=20} */
-
-#define GUN1 42:
-#define GUN2 43:
-#define bo do
-#define when(gun) /**/
-#define DATA "p 'Hello embedded world'"
-#define DIRTY(argc,argv)\
-argc,argv,char=eval(\
-"#{DATA.read}\n[3,2,1]"\
-);sun=O.new\
-if(0)
-
-int
-sun[]={12,9,16,9,2,1,7,1,3,9,27,4, 13,2,11,5,4,1,25,
-5,0,1,14,9,15,4,26,9,23,2,17,6,31, 6,10,8,22,9,21,1,
-24,8,20,8,18,9,29,5,9,5,1,1,28,8,8,1,30, 9,6,8, 5,1,
-19,9,36,19,43, 9,34,11,50,19,48,18,49,9, 35,8,42,18,
-51,8,44,11,32, 11,47,9,37,1,39,9,38,19, 45,8,40,12,
-41,9,46,12,33,1,57,1,85,5,88,28,83,4,87, 6,62,28,89,
-9,80,28,60,21,52,21,72,29,54,21,75,8,70,29,58,28,65,
-9,91,8,74,29,79,2,77,1,53,1,81,5, 69,2,64,21, 86,29,
-67,9,59,1,61,5,73,6,76,28,56,21,68,29,78,29,63,5,66,
-28,90,29, 71,4,55,9,84,28,82,29,101,5, 103,9, 98,35,
-97,1,94,35,93,1,100,35,92,31,99,5,96,39,95,5,102,35};
-
-void run(int gun=0) { // [gun]=[:GUN1,:GUN2]
- printf("run() %i\n", gun);
- switch(gun) {
- case GUN1 when(2)
- printf("when2\n");
- break; // end
- case GUN2 when(3)
- printf("when3\n");
- break; // end
- }
-}
-
-int main(int argc, char** argv) {
- printf("hello world. number of arguments=%i\n", argc);
- int fun=5;
- bo {
- fun -= 1; //.id - gun = fun
- run(fun);
- } while(fun>0);
- ruby_init();
- rb_eval_string(DATA);
- return 0;
-}
-
-#if 0 // nobody reads un-defined code
-__END__
-#CODE
-def goto*s;$s=[];Y.times{s=[];X.times{s<<[0]*3};$s<< s}end;A=0.5
-include Math;def u g,h,i,j,k,l;f,*m=((j-h).abs>(k-i).abs)?[proc{
-|n,o| g[o] [n ]=l },[h ,i ],[j,k]]:[proc{
-|p,q| g[ p][ q] =l} ,[ i,h ], [k,j]];b,a=m.sort
-c,d=a [1 ]-b [1 ],a [0 ]-b [0 ];d.times{|e|f.
-call( e+b[ 0] ,c* e/d+b [1])};end;V=0;def bo&u
-$u||= V; ;$u += 1+V ;; return u.call if$u>1;q=128.0
-;x=(V .. 255 ). map {| y|f1,z =sin(y.to_f*PI/q),
-sin(( y. to_f + 200 )*PI/( q));[(f1*30.0+110.0).
-to_i,((f1+z)*10.0+40.0).to_i,(z*20.0+120.0).to_i]};Y.times{|i|X.
-times{|j|i1=((i*0.3+150)*(j*1.1+50)/50.0).to_i;i2=((i*0.8+510)*(
-j*0.9+1060)/51.0).to_i;$s[i][j]=x[(i1*i2)%255].clone}};$a=(0..25).
-inject([]){|a,i|a<<(V..3).inject([]){|r,j|r<<$c[i*4+j]}};u.call;end
-I=LocalJumpError;def run*a,&b;return if a.size==V;if a[V]==666;$b=b
-elsif$b;$b.call;end;end;def main s,&u;$m=V;u.call rescue I;end
-def rb_eval_string(*a);end # you promised not to look here
-def ruby_init;q=2.0;l=((X**q)*A+(Y**q)*A)**A;V.upto(Y-4){|s|V.
-upto(X-4){|q|d=((q-X/A)**q+(s-Y/A)**q)**A;e=(cos(d*PI/(l/q))/q
-+A)*3.0+1.0;v=2;f=v/e;a,p,b=$s[s],$s[s+1],$s[s+v];r=a[q][V]*e+
-p[q][V]+a[q+1][V]+b[q][V]+a[q+v][V]+b[q+v/v][V]+p[q+v][V]+b[q+
-v][V]*f;g=[a[q][V],b[q][V],a[q+v][V],b[q+v][V]];h=(g.max-g.min
-)*f;$s[s][q][V]=[[(r/(e+f+6.0)+A+(h*0.4)).to_i,255].min,V].max
-}};File.open("res.ppm","w+"){|f|f.write(# secret.greetings :-)
-"P3\n# res.ppm\n#{X} #{Y}\n255\n"+$s.map{|a|a.map{|b|b.join' '
-}.join(' ')+"\n"}.join)};end;def switch i,&b;b.call;return unless
-defined?($m);b=(X*0.01).to_i;d=1.0/40.0;e=0.09;c=(Y*0.01).to_i
-a=$a.map{|(f,g,h,j)|[f*d,g*e,h*d,j*e]};a.each{|(k,l,m,n)|u($s,(k*X
-).to_i+b+i,(l*Y).to_i+c+i,(m*X).to_i+b+i,(n*Y).to_i+c+i,[Z]*3)}
-a.each{|(o,q,r,s)|u($s,(o*(X-Z)).to_i+i,(q*(Y-Z)).to_i+i,(r*(X-
-Z)).to_i+i,(s*(Y-Z)).to_i+i,[(1<<8)-1]*3)};end;Q=Object;class
-Regexp;def []=(v,is);is.each{|s|Q.send(:remove_const,s)if Q.
-const_defined? s;Q.const_set(s,v)};end;end;def int*ptr;666
-end;class O;def []=(a,b=nil);$c=a;end;end;alias:void:goto
-#endif // pretend as if you havn't seen anything
-
-module CodeRay
- module Scanners
-
-class Ruby < Scanner
-
- RESERVED_WORDS = [
- 'and', 'def', 'end', 'in', 'or', 'unless', 'begin',
- 'defined?', 'ensure', 'module', 'redo', 'super', 'until',
- 'BEGIN', 'break', 'do', 'next', 'rescue', 'then',
- 'when', 'END', 'case', 'else', 'for', 'retry',
- 'while', 'alias', 'class', 'elsif', 'if', 'not', 'return',
- 'undef', 'yield',
- ]
-
- DEF_KEYWORDS = ['def']
- MODULE_KEYWORDS = ['class', 'module']
- DEF_NEW_STATE = WordList.new(:initial).
- add(DEF_KEYWORDS, :def_expected).
- add(MODULE_KEYWORDS, :module_expected)
-
- WORDS_ALLOWING_REGEXP = [
- 'and', 'or', 'not', 'while', 'until', 'unless', 'if', 'elsif', 'when'
- ]
- REGEXP_ALLOWED = WordList.new(false).
- add(WORDS_ALLOWING_REGEXP, :set)
-
- PREDEFINED_CONSTANTS = [
- 'nil', 'true', 'false', 'self',
- 'DATA', 'ARGV', 'ARGF', '__FILE__', '__LINE__',
- ]
-
- IDENT_KIND = WordList.new(:ident).
- add(RESERVED_WORDS, :reserved).
- add(PREDEFINED_CONSTANTS, :pre_constant)
-
- METHOD_NAME = / #{IDENT} [?!]? /xo
- METHOD_NAME_EX = /
- #{METHOD_NAME} # common methods: split, foo=, empty?, gsub!
- | \*\*? # multiplication and power
- | [-+~]@? # plus, minus
- | [\/%&|^`] # division, modulo or format strings, &and, |or, ^xor, `system`
- | \[\]=? # array getter and setter
- | <=?>? | >=? # comparison, rocket operator
- | << | >> # append or shift left, shift right
- | ===? # simple equality and case equality
- /ox
- GLOBAL_VARIABLE = / \$ (?: #{IDENT} | \d+ | [~&+`'=\/,;_.<>!@0$?*":F\\] | -[a-zA-Z_0-9] ) /ox
-
- DOUBLEQ = / " [^"\#\\]* (?: (?: \#\{.*?\} | \#(?:$")? | \\. ) [^"\#\\]* )* "? /ox
- SINGLEQ = / ' [^'\\]* (?: \\. [^'\\]* )* '? /ox
- STRING = / #{SINGLEQ} | #{DOUBLEQ} /ox
- SHELL = / ` [^`\#\\]* (?: (?: \#\{.*?\} | \#(?:$`)? | \\. ) [^`\#\\]* )* `? /ox
- REGEXP = / \/ [^\/\#\\]* (?: (?: \#\{.*?\} | \#(?:$\/)? | \\. ) [^\/\#\\]* )* \/? /ox
-
- DECIMAL = /\d+(?:_\d+)*/ # doesn't recognize 09 as octal error
- OCTAL = /0_?[0-7]+(?:_[0-7]+)*/
- HEXADECIMAL = /0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*/
- BINARY = /0b[01]+(?:_[01]+)*/
-
- EXPONENT = / [eE] [+-]? #{DECIMAL} /ox
- FLOAT = / #{DECIMAL} (?: #{EXPONENT} | \. #{DECIMAL} #{EXPONENT}? ) /
- INTEGER = /#{OCTAL}|#{HEXADECIMAL}|#{BINARY}|#{DECIMAL}/
-
- def reset
- super
- @regexp_allowed = false
- end
-
- def next_token
- return if @scanner.eos?
-
- kind = :error
- if @scanner.scan(/\s+/) # in every state
- kind = :space
- @regexp_allowed = :set if @regexp_allowed or @scanner.matched.index(?\n) # delayed flag setting
-
- elsif @state == :def_expected
- if @scanner.scan(/ (?: (?:#{IDENT}(?:\.|::))* | (?:@@?|$)? #{IDENT}(?:\.|::) ) #{METHOD_NAME_EX} /ox)
- kind = :method
- @state = :initial
- else
- @scanner.getch
- end
- @state = :initial
-
- elsif @state == :module_expected
- if @scanner.scan(/<</)
- kind = :operator
- else
- if @scanner.scan(/ (?: #{IDENT} (?:\.|::))* #{IDENT} /ox)
- kind = :method
- else
- @scanner.getch
- end
- @state = :initial
- end
-
- elsif # state == :initial
- # IDENTIFIERS, KEYWORDS
- if @scanner.scan(GLOBAL_VARIABLE)
- kind = :global_variable
- elsif @scanner.scan(/ @@ #{IDENT} /ox)
- kind = :class_variable
- elsif @scanner.scan(/ @ #{IDENT} /ox)
- kind = :instance_variable
- elsif @scanner.scan(/ __END__\n ( (?!\#CODE\#) .* )? | \#[^\n]* | =begin(?=\s).*? \n=end(?=\s|\z)(?:[^\n]*)? /mx)
- kind = :comment
- elsif @scanner.scan(METHOD_NAME)
- if @last_token_dot
- kind = :ident
- else
- matched = @scanner.matched
- kind = IDENT_KIND[matched]
- if kind == :ident and matched =~ /^[A-Z]/
- kind = :constant
- elsif kind == :reserved
- @state = DEF_NEW_STATE[matched]
- @regexp_allowed = REGEXP_ALLOWED[matched]
- end
- end
-
- elsif @scanner.scan(STRING)
- kind = :string
- elsif @scanner.scan(SHELL)
- kind = :shell
- elsif @scanner.scan(/<<
- (?:
- ([a-zA-Z_0-9]+)
- (?: .*? ^\1$ | .* )
- |
- -([a-zA-Z_0-9]+)
- (?: .*? ^\s*\2$ | .* )
- |
- (["\'`]) (.+?) \3
- (?: .*? ^\4$ | .* )
- |
- - (["\'`]) (.+?) \5
- (?: .*? ^\s*\6$ | .* )
- )
- /mxo)
- kind = :string
- elsif @scanner.scan(/\//) and @regexp_allowed
- @scanner.unscan
- @scanner.scan(REGEXP)
- kind = :regexp
-/%(?:[Qqxrw](?:\([^)#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^)#\\\\]*)*\)?|\[[^\]#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^\]#\\\\]*)*\]?|\{[^}#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^}#\\\\]*)*\}?|<[^>#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^>#\\\\]*)*>?|([^a-zA-Z\\\\])(?:(?!\1)[^#\\\\])*(?:(?:#\{.*?\}|#|\\\\.)(?:(?!\1)[^#\\\\])*)*\1?)|\([^)#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^)#\\\\]*)*\)?|\[[^\]#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^\]#\\\\]*)*\]?|\{[^}#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^}#\\\\]*)*\}?|<[^>#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^>#\\\\]*)*>?|([^a-zA-Z\s\\\\])(?:(?!\2)[^#\\\\])*(?:(?:#\{.*?\}|#|\\\\.)(?:(?!\2)[^#\\\\])*)*\2?|\\\\[^#\\\\]*(?:(?:#\{.*?\}|#)[^#\\\\]*)*\\\\?)/
- elsif @scanner.scan(/:(?:#{GLOBAL_VARIABLE}|#{METHOD_NAME_EX}|#{STRING})/ox)
- kind = :symbol
- elsif @scanner.scan(/
- \? (?:
- [^\s\\]
- |
- \\ (?:M-\\C-|C-\\M-|M-\\c|c\\M-|c|C-|M-))? (?: \\ (?: . | [0-7]{3} | x[0-9A-Fa-f][0-9A-Fa-f] )
- )
- /mox)
- kind = :integer
-
- elsif @scanner.scan(/ [-+*\/%=<>;,|&!()\[\]{}~?] | \.\.?\.? | ::? /x)
- kind = :operator
- @regexp_allowed = :set if @scanner.matched[-1,1] =~ /[~=!<>|&^,\(\[+\-\/\*%]\z/
- elsif @scanner.scan(FLOAT)
- kind = :float
- elsif @scanner.scan(INTEGER)
- kind = :integer
- else
- @scanner.getch
- end
- end
-
- token = Token.new @scanner.matched, kind
-
- if kind == :regexp
- token.text << @scanner.scan(/[eimnosux]*/)
- end
-
- @regexp_allowed = (@regexp_allowed == :set) # delayed flag setting
-
- token
- end
-end
-
-register Ruby, 'ruby', 'rb'
-
- end
-end
-class Set
- include Enumerable
-
- # Creates a new set containing the given objects.
- def self.[](*ary)
- new(ary)
- end
-
- # Creates a new set containing the elements of the given enumerable
- # object.
- #
- # If a block is given, the elements of enum are preprocessed by the
- # given block.
- def initialize(enum = nil, &block) # :yields: o
- @hash ||= Hash.new
-
- enum.nil? and return
-
- if block
- enum.each { |o| add(block[o]) }
- else
- merge(enum)
- end
- end
-
- # Copy internal hash.
- def initialize_copy(orig)
- @hash = orig.instance_eval{@hash}.dup
- end
-
- # Returns the number of elements.
- def size
- @hash.size
- end
- alias length size
-
- # Returns true if the set contains no elements.
- def empty?
- @hash.empty?
- end
-
- # Removes all elements and returns self.
- def clear
- @hash.clear
- self
- end
-
- # Replaces the contents of the set with the contents of the given
- # enumerable object and returns self.
- def replace(enum)
- if enum.class == self.class
- @hash.replace(enum.instance_eval { @hash })
- else
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- clear
- enum.each { |o| add(o) }
- end
-
- self
- end
-
- # Converts the set to an array. The order of elements is uncertain.
- def to_a
- @hash.keys
- end
-
- def flatten_merge(set, seen = Set.new)
- set.each { |e|
- if e.is_a?(Set)
- if seen.include?(e_id = e.object_id)
- raise ArgumentError, "tried to flatten recursive Set"
- end
-
- seen.add(e_id)
- flatten_merge(e, seen)
- seen.delete(e_id)
- else
- add(e)
- end
- }
-
- self
- end
- protected :flatten_merge
-
- # Returns a new set that is a copy of the set, flattening each
- # containing set recursively.
- def flatten
- self.class.new.flatten_merge(self)
- end
-
- # Equivalent to Set#flatten, but replaces the receiver with the
- # result in place. Returns nil if no modifications were made.
- def flatten!
- if detect { |e| e.is_a?(Set) }
- replace(flatten())
- else
- nil
- end
- end
-
- # Returns true if the set contains the given object.
- def include?(o)
- @hash.include?(o)
- end
- alias member? include?
-
- # Returns true if the set is a superset of the given set.
- def superset?(set)
- set.is_a?(Set) or raise ArgumentError, "value must be a set"
- return false if size < set.size
- set.all? { |o| include?(o) }
- end
-
- # Returns true if the set is a proper superset of the given set.
- def proper_superset?(set)
- set.is_a?(Set) or raise ArgumentError, "value must be a set"
- return false if size <= set.size
- set.all? { |o| include?(o) }
- end
-
- # Returns true if the set is a subset of the given set.
- def subset?(set)
- set.is_a?(Set) or raise ArgumentError, "value must be a set"
- return false if set.size < size
- all? { |o| set.include?(o) }
- end
-
- # Returns true if the set is a proper subset of the given set.
- def proper_subset?(set)
- set.is_a?(Set) or raise ArgumentError, "value must be a set"
- return false if set.size <= size
- all? { |o| set.include?(o) }
- end
-
- # Calls the given block once for each element in the set, passing
- # the element as parameter.
- def each
- @hash.each_key { |o| yield(o) }
- self
- end
-
- # Adds the given object to the set and returns self. Use +merge+ to
- # add several elements at once.
- def add(o)
- @hash[o] = true
- self
- end
- alias << add
-
- # Adds the given object to the set and returns self. If the
- # object is already in the set, returns nil.
- def add?(o)
- if include?(o)
- nil
- else
- add(o)
- end
- end
-
- # Deletes the given object from the set and returns self. Use +subtract+ to
- # delete several items at once.
- def delete(o)
- @hash.delete(o)
- self
- end
-
- # Deletes the given object from the set and returns self. If the
- # object is not in the set, returns nil.
- def delete?(o)
- if include?(o)
- delete(o)
- else
- nil
- end
- end
-
- # Deletes every element of the set for which block evaluates to
- # true, and returns self.
- def delete_if
- @hash.delete_if { |o,| yield(o) }
- self
- end
-
- # Do collect() destructively.
- def collect!
- set = self.class.new
- each { |o| set << yield(o) }
- replace(set)
- end
- alias map! collect!
-
- # Equivalent to Set#delete_if, but returns nil if no changes were
- # made.
- def reject!
- n = size
- delete_if { |o| yield(o) }
- size == n ? nil : self
- end
-
- # Merges the elements of the given enumerable object to the set and
- # returns self.
- def merge(enum)
- if enum.is_a?(Set)
- @hash.update(enum.instance_eval { @hash })
- else
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- enum.each { |o| add(o) }
- end
-
- self
- end
-
- # Deletes every element that appears in the given enumerable object
- # and returns self.
- def subtract(enum)
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- enum.each { |o| delete(o) }
- self
- end
-
- # Returns a new set built by merging the set and the elements of the
- # given enumerable object.
- def |(enum)
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- dup.merge(enum)
- end
- alias + | ##
- alias union | ##
-
- # Returns a new set built by duplicating the set, removing every
- # element that appears in the given enumerable object.
- def -(enum)
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- dup.subtract(enum)
- end
- alias difference - ##
-
- # Returns a new array containing elements common to the set and the
- # given enumerable object.
- def &(enum)
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- n = self.class.new
- enum.each { |o| n.add(o) if include?(o) }
- n
- end
- alias intersection & ##
-
- # Returns a new array containing elements exclusive between the set
- # and the given enumerable object. (set ^ enum) is equivalent to
- # ((set | enum) - (set & enum)).
- def ^(enum)
- enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
- n = dup
- enum.each { |o| if n.include?(o) then n.delete(o) else n.add(o) end }
- n
- end
-
- # Returns true if two sets are equal. The equality of each couple
- # of elements is defined according to Object#eql?.
- def ==(set)
- equal?(set) and return true
-
- set.is_a?(Set) && size == set.size or return false
-
- hash = @hash.dup
- set.all? { |o| hash.include?(o) }
- end
-
- def hash # :nodoc:
- @hash.hash
- end
-
- def eql?(o) # :nodoc:
- return false unless o.is_a?(Set)
- @hash.eql?(o.instance_eval{@hash})
- end
-
- # Classifies the set by the return value of the given block and
- # returns a hash of {value => set of elements} pairs. The block is
- # called once for each element of the set, passing the element as
- # parameter.
- #
- # e.g.:
- #
- # require 'set'
- # files = Set.new(Dir.glob("*.rb"))
- # hash = files.classify { |f| File.mtime(f).year }
- # p hash # => {2000=>#<Set: {"a.rb", "b.rb"}>,
- # # 2001=>#<Set: {"c.rb", "d.rb", "e.rb"}>,
- # # 2002=>#<Set: {"f.rb"}>}
- def classify # :yields: o
- h = {}
-
- each { |i|
- x = yield(i)
- (h[x] ||= self.class.new).add(i)
- }
-
- h
- end
-
- # Divides the set into a set of subsets according to the commonality
- # defined by the given block.
- #
- # If the arity of the block is 2, elements o1 and o2 are in common
- # if block.call(o1, o2) is true. Otherwise, elements o1 and o2 are
- # in common if block.call(o1) == block.call(o2).
- #
- # e.g.:
- #
- # require 'set'
- # numbers = Set[1, 3, 4, 6, 9, 10, 11]
- # set = numbers.divide { |i,j| (i - j).abs == 1 }
- # p set # => #<Set: {#<Set: {1}>,
- # # #<Set: {11, 9, 10}>,
- # # #<Set: {3, 4}>,
- # # #<Set: {6}>}>
- def divide(&func)
- if func.arity == 2
- require 'tsort'
-
- class << dig = {} # :nodoc:
- include TSort
-
- alias tsort_each_node each_key
- def tsort_each_child(node, &block)
- fetch(node).each(&block)
- end
- end
-
- each { |u|
- dig[u] = a = []
- each{ |v| func.call(u, v) and a << v }
- }
-
- set = Set.new()
- dig.each_strongly_connected_component { |css|
- set.add(self.class.new(css))
- }
- set
- else
- Set.new(classify(&func).values)
- end
- end
-
- InspectKey = :__inspect_key__ # :nodoc:
-
- # Returns a string containing a human-readable representation of the
- # set. ("#<Set: {element1, element2, ...}>")
- def inspect
- ids = (Thread.current[InspectKey] ||= [])
-
- if ids.include?(object_id)
- return sprintf('#<%s: {...}>', self.class.name)
- end
-
- begin
- ids << object_id
- return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2])
- ensure
- ids.pop
- end
- end
-
- def pretty_print(pp) # :nodoc:
- pp.text sprintf('#<%s: {', self.class.name)
- pp.nest(1) {
- pp.seplist(self) { |o|
- pp.pp o
- }
- }
- pp.text "}>"
- end
-
- def pretty_print_cycle(pp) # :nodoc:
- pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...')
- end
-end
-
-# SortedSet implements a set which elements are sorted in order. See Set.
-class SortedSet < Set
- @@setup = false
-
- class << self
- def [](*ary) # :nodoc:
- new(ary)
- end
-
- def setup # :nodoc:
- @@setup and return
-
- begin
- require 'rbtree'
-
- module_eval %{
- def initialize(*args, &block)
- @hash = RBTree.new
- super
- end
- }
- rescue LoadError
- module_eval %{
- def initialize(*args, &block)
- @keys = nil
- super
- end
-
- def clear
- @keys = nil
- super
- end
-
- def replace(enum)
- @keys = nil
- super
- end
-
- def add(o)
- @keys = nil
- @hash[o] = true
- self
- end
- alias << add
-
- def delete(o)
- @keys = nil
- @hash.delete(o)
- self
- end
-
- def delete_if
- n = @hash.size
- @hash.delete_if { |o,| yield(o) }
- @keys = nil if @hash.size != n
- self
- end
-
- def merge(enum)
- @keys = nil
- super
- end
-
- def each
- to_a.each { |o| yield(o) }
- end
-
- def to_a
- (@keys = @hash.keys).sort! unless @keys
- @keys
- end
- }
- end
-
- @@setup = true
- end
- end
-
- def initialize(*args, &block) # :nodoc:
- SortedSet.setup
- initialize(*args, &block)
- end
-end
-
-module Enumerable
- # Makes a set from the enumerable object with given arguments.
- def to_set(klass = Set, *args, &block)
- klass.new(self, *args, &block)
- end
-end
-
-# =begin
-# == RestricedSet class
-# RestricedSet implements a set with restrictions defined by a given
-# block.
-#
-# === Super class
-# Set
-#
-# === Class Methods
-# --- RestricedSet::new(enum = nil) { |o| ... }
-# --- RestricedSet::new(enum = nil) { |rset, o| ... }
-# Creates a new restricted set containing the elements of the given
-# enumerable object. Restrictions are defined by the given block.
-#
-# If the block's arity is 2, it is called with the RestrictedSet
-# itself and an object to see if the object is allowed to be put in
-# the set.
-#
-# Otherwise, the block is called with an object to see if the object
-# is allowed to be put in the set.
-#
-# === Instance Methods
-# --- restriction_proc
-# Returns the restriction procedure of the set.
-#
-# =end
-#
-# class RestricedSet < Set
-# def initialize(*args, &block)
-# @proc = block or raise ArgumentError, "missing a block"
-#
-# if @proc.arity == 2
-# instance_eval %{
-# def add(o)
-# @hash[o] = true if @proc.call(self, o)
-# self
-# end
-# alias << add
-#
-# def add?(o)
-# if include?(o) || !@proc.call(self, o)
-# nil
-# else
-# @hash[o] = true
-# self
-# end
-# end
-#
-# def replace(enum)
-# enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
-# clear
-# enum.each { |o| add(o) }
-#
-# self
-# end
-#
-# def merge(enum)
-# enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
-# enum.each { |o| add(o) }
-#
-# self
-# end
-# }
-# else
-# instance_eval %{
-# def add(o)
-# if @proc.call(o)
-# @hash[o] = true
-# end
-# self
-# end
-# alias << add
-#
-# def add?(o)
-# if include?(o) || !@proc.call(o)
-# nil
-# else
-# @hash[o] = true
-# self
-# end
-# end
-# }
-# end
-#
-# super(*args)
-# end
-#
-# def restriction_proc
-# @proc
-# end
-# end
-
-if $0 == __FILE__
- eval DATA.read, nil, $0, __LINE__+4
-end
-
-# = rweb - CGI Support Library
-#
-# Author:: Johannes Barre (mailto:rweb@igels.net)
-# Copyright:: Copyright (c) 2003, 04 by Johannes Barre
-# License:: GNU Lesser General Public License (COPYING, http://www.gnu.org/copyleft/lesser.html)
-# Version:: 0.1.0
-# CVS-ID:: $Id: rweb.rb 6 2004-06-16 15:56:26Z igel $
-#
-# == What is Rweb?
-# Rweb is a replacement for the cgi class included in the ruby distribution.
-#
-# == How to use
-#
-# === Basics
-#
-# This class is made to be as easy as possible to use. An example:
-#
-# require "rweb"
-#
-# web = Rweb.new
-# web.out do
-# web.puts "Hello world!"
-# end
-#
-# The visitor will get a simple "Hello World!" in his browser. Please notice,
-# that won't set html-tags for you, so you should better do something like this:
-#
-# require "rweb"
-#
-# web = Rweb.new
-# web.out do
-# web.puts "<html><body>Hello world!</body></html>"
-# end
-#
-# === Set headers
-# Of course, it's also possible to tell the browser, that the content of this
-# page is plain text instead of html code:
-#
-# require "rweb"
-#
-# web = Rweb.new
-# web.out do
-# web.header("content-type: text/plain")
-# web.puts "Hello plain world!"
-# end
-#
-# Please remember, headers can't be set after the page content has been send.
-# You have to set all nessessary headers before the first puts oder print. It's
-# possible to cache the content until everything is complete. Doing it this
-# way, you can set headers everywhere.
-#
-# If you set a header twice, the second header will replace the first one. The
-# header name is not casesensitive, it will allways converted in to the
-# capitalised form suggested by the w3c (http://w3.org)
-#
-# === Set cookies
-# Setting cookies is quite easy:
-# include 'rweb'
-#
-# web = Rweb.new
-# Cookie.new("Visits", web.cookies['visits'].to_i +1)
-# web.out do
-# web.puts "Welcome back! You visited this page #{web.cookies['visits'].to_i +1} times"
-# end
-#
-# See the class Cookie for more details.
-#
-# === Get form and cookie values
-# There are four ways to submit data from the browser to the server and your
-# ruby script: via GET, POST, cookies and file upload. Rweb doesn't support
-# file upload by now.
-#
-# include 'rweb'
-#
-# web = Rweb.new
-# web.out do
-# web.print "action: #{web.get['action']} "
-# web.puts "The value of the cookie 'visits' is #{web.cookies['visits']}"
-# web.puts "The post parameter 'test['x']' is #{web.post['test']['x']}"
-# end
-
-RWEB_VERSION = "0.1.0"
-RWEB = "rweb/#{RWEB_VERSION}"
-
-#require 'rwebcookie' -> edit by bunny :-)
-
-class Rweb
- # All parameter submitted via the GET method are available in attribute
- # get. This is Hash, where every parameter is available as a key-value
- # pair.
- #
- # If your input tag has a name like this one, it's value will be available
- # as web.get["fieldname"]
- # <input name="fieldname">
- # You can submit values as a Hash
- # <input name="text['index']">
- # <input name="text['index2']">
- # will be available as
- # web.get["text"]["index"]
- # web.get["text"]["index2"]
- # Integers are also possible
- # <input name="int[2]">
- # <input name="int[3]['hi']>
- # will be available as
- # web.get["int"][2]
- # web.get["int"][3]["hi"]
- # If you specify no index, the lowest unused index will be used:
- # <input name="int[]"><!-- First Field -->
- # <input name="int[]"><!-- Second one -->
- # will be available as
- # web.get["int"][0] # First Field
- # web.get["int"][1] # Second one
- # Please notice, this doesn'd work like you might expect:
- # <input name="text[index]">
- # It will not be available as web.get["text"]["index"] but
- # web.get["text[index]"]
- attr_reader :get
-
- # All parameters submitted via POST are available in the attribute post. It
- # works like the get attribute.
- # <input name="text[0]">
- # will be available as
- # web.post["text"][0]
- attr_reader :post
-
- # All cookies submitted by the browser are available in cookies. This is a
- # Hash, where every cookie is a key-value pair.
- attr_reader :cookies
-
- # The name of the browser identification is submitted as USER_AGENT and
- # available in this attribute.
- attr_reader :user_agent
-
- # The IP address of the client.
- attr_reader :remote_addr
-
- # Creates a new Rweb object. This should only done once. You can set various
- # options via the settings hash.
- #
- # "cache" => true: Everything you script send to the client will be cached
- # until the end of the out block or until flush is called. This way, you
- # can modify headers and cookies even after printing something to the client.
- #
- # "safe" => level: Changes the $SAFE attribute. By default, $SAFE will be set
- # to 1. If $SAFE is already higher than this value, it won't be changed.
- #
- # "silend" => true: Normaly, Rweb adds automaticly a header like this
- # "X-Powered-By: Rweb/x.x.x (Ruby/y.y.y)". With the silend option you can
- # suppress this.
- def initialize (settings = {})
- # {{{
- @header = {}
- @cookies = {}
- @get = {}
- @post = {}
-
- # Internal attributes
- @status = nil
- @reasonPhrase = nil
- @setcookies = []
- @output_started = false;
- @output_allowed = false;
-
- @mod_ruby = false
- @env = ENV.to_hash
-
- if defined?(MOD_RUBY)
- @output_method = "mod_ruby"
- @mod_ruby = true
- elsif @env['SERVER_SOFTWARE'] =~ /^Microsoft-IIS/i
- @output_method = "nph"
- else
- @output_method = "ph"
- end
-
- unless settings.is_a?(Hash)
- raise TypeError, "settings must be a Hash"
- end
- @settings = settings
-
- unless @settings.has_key?("safe")
- @settings["safe"] = 1
- end
-
- if $SAFE < @settings["safe"]
- $SAFE = @settings["safe"]
- end
-
- unless @settings.has_key?("cache")
- @settings["cache"] = false
- end
-
- # mod_ruby sets no QUERY_STRING variable, if no GET-Parameters are given
- unless @env.has_key?("QUERY_STRING")
- @env["QUERY_STRING"] = ""
- end
-
- # Now we split the QUERY_STRING by the seperators & and ; or, if
- # specified, settings['get seperator']
- unless @settings.has_key?("get seperator")
- get_args = @env['QUERY_STRING'].split(/[&;]/)
- else
- get_args = @env['QUERY_STRING'].split(@settings['get seperator'])
- end
-
- get_args.each do | arg |
- arg_key, arg_val = arg.split(/=/, 2)
- arg_key = Rweb::unescape(arg_key)
- arg_val = Rweb::unescape(arg_val)
-
- # Parse names like name[0], name['text'] or name[]
- pattern = /^(.+)\[("[^\]]*"|'[^\]]*'|[0-9]*)\]$/
- keys = []
- while match = pattern.match(arg_key)
- arg_key = match[1]
- keys = [match[2]] + keys
- end
- keys = [arg_key] + keys
-
- akt = @get
- last = nil
- lastkey = nil
- keys.each do |key|
- if key == ""
- # No key specified (like in "test[]"), so we use the
- # lowerst unused Integer as key
- key = 0
- while akt.has_key?(key)
- key += 1
- end
- elsif /^[0-9]*$/ =~ key
- # If the index is numerical convert it to an Integer
- key = key.to_i
- elsif key[0].chr == "'" || key[0].chr == '"'
- key = key[1, key.length() -2]
- end
- if !akt.has_key?(key) || !akt[key].class == Hash
- # create an empty Hash if there isn't already one
- akt[key] = {}
- end
- last = akt
- lastkey = key
- akt = akt[key]
- end
- last[lastkey] = arg_val
- end
-
- if @env['REQUEST_METHOD'] == "POST"
- if @env.has_key?("CONTENT_TYPE") && @env['CONTENT_TYPE'] == "application/x-www-form-urlencoded" && @env.has_key?('CONTENT_LENGTH')
- unless @settings.has_key?("post seperator")
- post_args = $stdin.read(@env['CONTENT_LENGTH'].to_i).split(/[&;]/)
- else
- post_args = $stdin.read(@env['CONTENT_LENGTH'].to_i).split(@settings['post seperator'])
- end
- post_args.each do | arg |
- arg_key, arg_val = arg.split(/=/, 2)
- arg_key = Rweb::unescape(arg_key)
- arg_val = Rweb::unescape(arg_val)
-
- # Parse names like name[0], name['text'] or name[]
- pattern = /^(.+)\[("[^\]]*"|'[^\]]*'|[0-9]*)\]$/
- keys = []
- while match = pattern.match(arg_key)
- arg_key = match[1]
- keys = [match[2]] + keys
- end
- keys = [arg_key] + keys
-
- akt = @post
- last = nil
- lastkey = nil
- keys.each do |key|
- if key == ""
- # No key specified (like in "test[]"), so we use
- # the lowerst unused Integer as key
- key = 0
- while akt.has_key?(key)
- key += 1
- end
- elsif /^[0-9]*$/ =~ key
- # If the index is numerical convert it to an Integer
- key = key.to_i
- elsif key[0].chr == "'" || key[0].chr == '"'
- key = key[1, key.length() -2]
- end
- if !akt.has_key?(key) || !akt[key].class == Hash
- # create an empty Hash if there isn't already one
- akt[key] = {}
- end
- last = akt
- lastkey = key
- akt = akt[key]
- end
- last[lastkey] = arg_val
- end
- else
- # Maybe we should print a warning here?
- $stderr.print("Unidentified form data recived and discarded.")
- end
- end
-
- if @env.has_key?("HTTP_COOKIE")
- cookie = @env['HTTP_COOKIE'].split(/; ?/)
- cookie.each do | c |
- cookie_key, cookie_val = c.split(/=/, 2)
-
- @cookies [Rweb::unescape(cookie_key)] = Rweb::unescape(cookie_val)
- end
- end
-
- if defined?(@env['HTTP_USER_AGENT'])
- @user_agent = @env['HTTP_USER_AGENT']
- else
- @user_agent = nil;
- end
-
- if defined?(@env['REMOTE_ADDR'])
- @remote_addr = @env['REMOTE_ADDR']
- else
- @remote_addr = nil
- end
- # }}}
- end
-
- # Prints a String to the client. If caching is enabled, the String will
- # buffered until the end of the out block ends.
- def print(str = "")
- # {{{
- unless @output_allowed
- raise "You just can write to output inside of a Rweb::out-block"
- end
-
- if @settings["cache"]
- @buffer += [str.to_s]
- else
- unless @output_started
- sendHeaders
- end
- $stdout.print(str)
- end
- nil
- # }}}
- end
-
- # Prints a String to the client and adds a line break at the end. Please
- # remember, that a line break is not visible in HTML, use the <br> HTML-Tag
- # for this. If caching is enabled, the String will buffered until the end
- # of the out block ends.
- def puts(str = "")
- # {{{
- self.print(str + "\n")
- # }}}
- end
-
- # Alias to print.
- def write(str = "")
- # {{{
- self.print(str)
- # }}}
- end
-
- # If caching is enabled, all cached data are send to the cliend and the
- # cache emptied.
- def flush
- # {{{
- unless @output_allowed
- raise "You can't use flush outside of a Rweb::out-block"
- end
- buffer = @buffer.join
-
- unless @output_started
- sendHeaders
- end
- $stdout.print(buffer)
-
- @buffer = []
- # }}}
- end
-
- # Sends one or more header to the client. All headers are cached just
- # before body data are send to the client. If the same header are set
- # twice, only the last value is send.
- #
- # Example:
- # web.header("Last-Modified: Mon, 16 Feb 2004 20:15:41 GMT")
- # web.header("Location: http://www.ruby-lang.org")
- #
- # You can specify more than one header at the time by doing something like
- # this:
- # web.header("Content-Type: text/plain\nContent-Length: 383")
- # or
- # web.header(["Content-Type: text/plain", "Content-Length: 383"])
- def header(str)
- # {{{
- if @output_started
- raise "HTTP-Headers are already send. You can't change them after output has started!"
- end
- unless @output_allowed
- raise "You just can set headers inside of a Rweb::out-block"
- end
- if str.is_a?Array
- str.each do | value |
- self.header(value)
- end
-
- elsif str.split(/\n/).length > 1
- str.split(/\n/).each do | value |
- self.header(value)
- end
-
- elsif str.is_a? String
- str.gsub!(/\r/, "")
-
- if (str =~ /^HTTP\/1\.[01] [0-9]{3} ?.*$/) == 0
- pattern = /^HTTP\/1.[01] ([0-9]{3}) ?(.*)$/
-
- result = pattern.match(str)
- self.setstatus(result[0], result[1])
- elsif (str =~ /^status: [0-9]{3} ?.*$/i) == 0
- pattern = /^status: ([0-9]{3}) ?(.*)$/i
-
- result = pattern.match(str)
- self.setstatus(result[0], result[1])
- else
- a = str.split(/: ?/, 2)
-
- @header[a[0].downcase] = a[1]
- end
- end
- # }}}
- end
-
- # Changes the status of this page. There are several codes like "200 OK",
- # "302 Found", "404 Not Found" or "500 Internal Server Error". A list of
- # all codes is available at
- # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10
- #
- # You can just send the code number, the reason phrase will be added
- # automaticly with the recommendations from the w3c if not specified. If
- # you set the status twice or more, only the last status will be send.
- # Examples:
- # web.status("401 Unauthorized")
- # web.status("410 Sad but true, this lonely page is gone :(")
- # web.status(206)
- # web.status("400")
- #
- # The default status is "200 OK". If a "Location" header is set, the
- # default status is "302 Found".
- def status(str)
- # {{{
- if @output_started
- raise "HTTP-Headers are already send. You can't change them after output has started!"
- end
- unless @output_allowed
- raise "You just can set headers inside of a Rweb::out-block"
- end
- if str.is_a?Integer
- @status = str
- elsif str.is_a?String
- p1 = /^([0-9]{3}) ?(.*)$/
- p2 = /^HTTP\/1\.[01] ([0-9]{3}) ?(.*)$/
- p3 = /^status: ([0-9]{3}) ?(.*)$/i
-
- if (a = p1.match(str)) == nil
- if (a = p2.match(str)) == nil
- if (a = p3.match(str)) == nil
- raise ArgumentError, "Invalid argument", caller
- end
- end
- end
- @status = a[1].to_i
- if a[2] != ""
- @reasonPhrase = a[2]
- else
- @reasonPhrase = getReasonPhrase(@status)
- end
- else
- raise ArgumentError, "Argument of setstatus must be integer or string", caller
- end
- # }}}
- end
-
- # Handles the output of your content and rescues all exceptions. Send all
- # data in the block to this method. For example:
- # web.out do
- # web.header("Content-Type: text/plain")
- # web.puts("Hello, plain world!")
- # end
- def out
- # {{{
- @output_allowed = true
- @buffer = []; # We use an array as buffer, because it's more performant :)
-
- begin
- yield
- rescue Exception => exception
- $stderr.puts "Ruby exception rescued (#{exception.class}): #{exception.message}"
- $stderr.puts exception.backtrace.join("\n")
-
- unless @output_started
- self.setstatus(500)
- @header = {}
- end
-
- unless (@settings.has_key?("hide errors") and @settings["hide errors"] == true)
- unless @output_started
- self.header("Content-Type: text/html")
- self.puts "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Strict//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">"
- self.puts "<html>"
- self.puts "<head>"
- self.puts "<title>500 Internal Server Error</title>"
- self.puts "</head>"
- self.puts "<body>"
- end
- if @header.has_key?("content-type") and (@header["content-type"] =~ /^text\/html/i) == 0
- self.puts "<h1>Internal Server Error</h1>"
- self.puts "<p>The server encountered an exception and was unable to complete your request.</p>"
- self.puts "<p>The exception has provided the following information:</p>"
- self.puts "<pre style=\"background: #FFCCCC; border: black solid 2px; margin-left: 2cm; margin-right: 2cm; padding: 2mm;\"><b>#{exception.class}</b>: #{exception.message} <b>on</b>"
- self.puts
- self.puts "#{exception.backtrace.join("\n")}</pre>"
- self.puts "</body>"
- self.puts "</html>"
- else
- self.puts "The server encountered an exception and was unable to complete your request"
- self.puts "The exception has provided the following information:"
- self.puts "#{exception.class}: #{exception.message}"
- self.puts
- self.puts exception.backtrace.join("\n")
- end
- end
- end
-
- if @settings["cache"]
- buffer = @buffer.join
-
- unless @output_started
- unless @header.has_key?("content-length")
- self.header("content-length: #{buffer.length}")
- end
-
- sendHeaders
- end
- $stdout.print(buffer)
- elsif !@output_started
- sendHeaders
- end
- @output_allowed = false;
- # }}}
- end
-
- # Decodes URL encoded data, %20 for example stands for a space.
- def Rweb.unescape(str)
- # {{{
- if defined? str and str.is_a? String
- str.gsub!(/\+/, " ")
- str.gsub(/%.{2}/) do | s |
- s[1,2].hex.chr
- end
- end
- # }}}
- end
-
- protected
- def sendHeaders
- # {{{
-
- Cookie.disallow # no more cookies can be set or modified
- if !(@settings.has_key?("silent") and @settings["silent"] == true) and !@header.has_key?("x-powered-by")
- if @mod_ruby
- header("x-powered-by: #{RWEB} (Ruby/#{RUBY_VERSION}, #{MOD_RUBY})");
- else
- header("x-powered-by: #{RWEB} (Ruby/#{RUBY_VERSION})");
- end
- end
-
- if @output_method == "ph"
- if ((@status == nil or @status == 200) and !@header.has_key?("content-type") and !@header.has_key?("location"))
- header("content-type: text/html")
- end
-
- if @status != nil
- $stdout.print "Status: #{@status} #{@reasonPhrase}\r\n"
- end
-
- @header.each do |key, value|
- key = key *1 # "unfreeze" key :)
- key[0] = key[0,1].upcase![0]
-
- key = key.gsub(/-[a-z]/) do |char|
- "-" + char[1,1].upcase
- end
-
- $stdout.print "#{key}: #{value}\r\n"
- end
- cookies = Cookie.getHttpHeader # Get all cookies as an HTTP Header
- if cookies
- $stdout.print cookies
- end
-
- $stdout.print "\r\n"
-
- elsif @output_method == "nph"
- elsif @output_method == "mod_ruby"
- r = Apache.request
-
- if ((@status == nil or @status == 200) and !@header.has_key?("content-type") and !@header.has_key?("location"))
- header("text/html")
- end
-
- if @status != nil
- r.status_line = "#{@status} #{@reasonPhrase}"
- end
-
- r.send_http_header
- @header.each do |key, value|
- key = key *1 # "unfreeze" key :)
-
- key[0] = key[0,1].upcase![0]
- key = key.gsub(/-[a-z]/) do |char|
- "-" + char[1,1].upcase
- end
- puts "#{key}: #{value.class}"
- #r.headers_out[key] = value
- end
- end
- @output_started = true
- # }}}
- end
-
- def getReasonPhrase (status)
- # {{{
- if status == 100
- "Continue"
- elsif status == 101
- "Switching Protocols"
- elsif status == 200
- "OK"
- elsif status == 201
- "Created"
- elsif status == 202
- "Accepted"
- elsif status == 203
- "Non-Authoritative Information"
- elsif status == 204
- "No Content"
- elsif status == 205
- "Reset Content"
- elsif status == 206
- "Partial Content"
- elsif status == 300
- "Multiple Choices"
- elsif status == 301
- "Moved Permanently"
- elsif status == 302
- "Found"
- elsif status == 303
- "See Other"
- elsif status == 304
- "Not Modified"
- elsif status == 305
- "Use Proxy"
- elsif status == 307
- "Temporary Redirect"
- elsif status == 400
- "Bad Request"
- elsif status == 401
- "Unauthorized"
- elsif status == 402
- "Payment Required"
- elsif status == 403
- "Forbidden"
- elsif status == 404
- "Not Found"
- elsif status == 405
- "Method Not Allowed"
- elsif status == 406
- "Not Acceptable"
- elsif status == 407
- "Proxy Authentication Required"
- elsif status == 408
- "Request Time-out"
- elsif status == 409
- "Conflict"
- elsif status == 410
- "Gone"
- elsif status == 411
- "Length Required"
- elsif status == 412
- "Precondition Failed"
- elsif status == 413
- "Request Entity Too Large"
- elsif status == 414
- "Request-URI Too Large"
- elsif status == 415
- "Unsupported Media Type"
- elsif status == 416
- "Requested range not satisfiable"
- elsif status == 417
- "Expectation Failed"
- elsif status == 500
- "Internal Server Error"
- elsif status == 501
- "Not Implemented"
- elsif status == 502
- "Bad Gateway"
- elsif status == 503
- "Service Unavailable"
- elsif status == 504
- "Gateway Time-out"
- elsif status == 505
- "HTTP Version not supported"
- else
- raise "Unknown Statuscode. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1 for more information."
- end
- # }}}
- end
-end
-
-class Cookie
- attr_reader :name, :value, :maxage, :path, :domain, :secure, :comment
-
- # Sets a cookie. Please see below for details of the attributes.
- def initialize (name, value = nil, maxage = nil, path = nil, domain = nil, secure = false)
- # {{{
- # HTTP headers (Cookies are a HTTP header) can only set, while no content
- # is send. So an exception will be raised, when @@allowed is set to false
- # and a new cookie has set.
- unless defined?(@@allowed)
- @@allowed = true
- end
- unless @@allowed
- raise "You can't set cookies after the HTTP headers are send."
- end
-
- unless defined?(@@list)
- @@list = []
- end
- @@list += [self]
-
- unless defined?(@@type)
- @@type = "netscape"
- end
-
- unless name.class == String
- raise TypeError, "The name of a cookie must be a string", caller
- end
- if value.class.superclass == Integer || value.class == Float
- value = value.to_s
- elsif value.class != String && value != nil
- raise TypeError, "The value of a cookie must be a string, integer, float or nil", caller
- end
- if maxage.class == Time
- maxage = maxage - Time.now
- elsif !maxage.class.superclass == Integer || !maxage == nil
- raise TypeError, "The maxage date of a cookie must be an Integer or Time object or nil.", caller
- end
- unless path.class == String || path == nil
- raise TypeError, "The path of a cookie must be nil or a string", caller
- end
- unless domain.class == String || domain == nil
- raise TypeError, "The value of a cookie must be nil or a string", caller
- end
- unless secure == true || secure == false
- raise TypeError, "The secure field of a cookie must be true or false", caller
- end
-
- @name, @value, @maxage, @path, @domain, @secure = name, value, maxage, path, domain, secure
- @comment = nil
- # }}}
- end
-
- # Modifies the value of this cookie. The information you want to store. If the
- # value is nil, the cookie will be deleted by the client.
- #
- # This attribute can be a String, Integer or Float object or nil.
- def value=(value)
- # {{{
- if value.class.superclass == Integer || value.class == Float
- value = value.to_s
- elsif value.class != String && value != nil
- raise TypeError, "The value of a cookie must be a string, integer, float or nil", caller
- end
- @value = value
- # }}}
- end
-
- # Modifies the maxage of this cookie. This attribute defines the lifetime of
- # the cookie, in seconds. A value of 0 means the cookie should be discarded
- # imediatly. If it set to nil, the cookie will be deleted when the browser
- # will be closed.
- #
- # Attention: This is different from other implementations like PHP, where you
- # gives the seconds since 1/1/1970 0:00:00 GMT.
- #
- # This attribute must be an Integer or Time object or nil.
- def maxage=(maxage)
- # {{{
- if maxage.class == Time
- maxage = maxage - Time.now
- elsif maxage.class.superclass == Integer || !maxage == nil
- raise TypeError, "The maxage of a cookie must be an Interger or Time object or nil.", caller
- end
- @maxage = maxage
- # }}}
- end
-
- # Modifies the path value of this cookie. The client will send this cookie
- # only, if the requested document is this directory or a subdirectory of it.
- #
- # The value of the attribute must be a String object or nil.
- def path=(path)
- # {{{
- unless path.class == String || path == nil
- raise TypeError, "The path of a cookie must be nil or a string", caller
- end
- @path = path
- # }}}
- end
-
- # Modifies the domain value of this cookie. The client will send this cookie
- # only if it's connected with this domain (or a subdomain, if the first
- # character is a dot like in ".ruby-lang.org")
- #
- # The value of this attribute must be a String or nil.
- def domain=(domain)
- # {{{
- unless domain.class == String || domain == nil
- raise TypeError, "The domain of a cookie must be a String or nil.", caller
- end
- @domain = domain
- # }}}
- end
-
- # Modifies the secure flag of this cookie. If it's true, the client will only
- # send this cookie if it is secured connected with us.
- #
- # The value od this attribute has to be true or false.
- def secure=(secure)
- # {{{
- unless secure == true || secure == false
- raise TypeError, "The secure field of a cookie must be true or false", caller
- end
- @secure = secure
- # }}}
- end
-
- # Modifies the comment value of this cookie. The comment won't be send, if
- # type is "netscape".
- def comment=(comment)
- # {{{
- unless comment.class == String || comment == nil
- raise TypeError, "The comment of a cookie must be a string or nil", caller
- end
- @comment = comment
- # }}}
- end
-
- # Changes the type of all cookies.
- # Allowed values are RFC2109 and netscape (default).
- def Cookie.type=(type)
- # {{{
- unless @@allowed
- raise "The cookies are allready send, so you can't change the type anymore."
- end
- unless type.downcase == "rfc2109" && type.downcase == "netscape"
- raise "The type of the cookies must be \"RFC2109\" or \"netscape\"."
- end
- @@type = type;
- # }}}
- end
-
- # After sending this message, no cookies can be set or modified. Use it, when
- # HTTP-Headers are send. Rweb does this for you.
- def Cookie.disallow
- # {{{
- @@allowed = false
- true
- # }}}
- end
-
- # Returns a HTTP header (type String) with all cookies. Rweb does this for
- # you.
- def Cookie.getHttpHeader
- # {{{
- if defined?(@@list)
- if @@type == "netscape"
- str = ""
- @@list.each do |cookie|
- if cookie.value == nil
- cookie.maxage = 0
- cookie.value = ""
- end
- # TODO: Name and value should be escaped!
- str += "Set-Cookie: #{cookie.name}=#{cookie.value}"
- unless cookie.maxage == nil
- expire = Time.now + cookie.maxage
- expire.gmtime
- str += "; Expire=#{expire.strftime("%a, %d-%b-%Y %H:%M:%S %Z")}"
- end
- unless cookie.domain == nil
- str += "; Domain=#{cookie.domain}"
- end
- unless cookie.path == nil
- str += "; Path=#{cookie.path}"
- end
- if cookie.secure
- str += "; Secure"
- end
- str += "\r\n"
- end
- return str
- else # type == "RFC2109"
- str = "Set-Cookie: "
- comma = false;
-
- @@list.each do |cookie|
- if cookie.value == nil
- cookie.maxage = 0
- cookie.value = ""
- end
- if comma
- str += ","
- end
- comma = true
-
- str += "#{cookie.name}=\"#{cookie.value}\""
- unless cookie.maxage == nil
- str += "; Max-Age=\"#{cookie.maxage}\""
- end
- unless cookie.domain == nil
- str += "; Domain=\"#{cookie.domain}\""
- end
- unless cookie.path == nil
- str += "; Path=\"#{cookie.path}\""
- end
- if cookie.secure
- str += "; Secure"
- end
- unless cookie.comment == nil
- str += "; Comment=\"#{cookie.comment}\""
- end
- str += "; Version=\"1\""
- end
- str
- end
- else
- false
- end
- # }}}
- end
-end
-
-require 'strscan'
-
-module BBCode
- DEBUG = true
-
- use 'encoder', 'tags', 'tagstack', 'smileys'
-
-=begin
- The Parser class takes care of the encoding.
- It scans the given BBCode (as plain text), finds tags
- and smilies and also makes links of urls in text.
-
- Normal text is send directly to the encoder.
-
- If a tag was found, an instance of a Tag subclass is created
- to handle the case.
-
- The @tagstack manages tag nesting and ensures valid HTML.
-=end
-
- class Parser
- class Attribute
- # flatten and use only one empty_arg
- def self.create attr
- attr = flatten attr
- return @@empty_attr if attr.empty?
- new attr
- end
-
- private_class_method :new
-
- # remove leading and trailing whitespace; concat lines
- def self.flatten attr
- attr.strip.gsub(/\n/, ' ')
- # -> ^ and $ can only match at begin and end now
- end
-
- ATTRIBUTE_SCAN = /
- (?!$) # don't match at end
- \s*
- ( # $1 = key
- [^=\s\]"\\]*
- (?:
- (?: \\. | "[^"\\]*(?:\\.[^"\\]*)*"? )
- [^=\s\]"\\]*
- )*
- )
- (?:
- =
- ( # $2 = value
- [^\s\]"\\]*
- (?:
- (?: \\. | "[^"\\]*(?:\\.[^"\\]*)*"? )
- [^\s\]"\\]*
- )*
- )?
- )?
- \s*
- /x
-
- def self.parse source
- source = source.dup
- # empty_tag: the tag looks like [... /]
- # slice!: this deletes the \s*/] at the end
- # \s+ because [url=http://rubybb.org/forum/] is NOT an empty tag.
- # In RubyBBCode, you can use [url=http://rubybb.org/forum/ /], and this has to be
- # interpreted correctly.
- empty_tag = source.sub!(/^:/, '=') or source.slice!(/\/$/)
- debug 'PARSE: ' + source.inspect + ' => ' + empty_tag.inspect
- #-> we have now an attr that's EITHER empty OR begins and ends with non-whitespace.
-
- attr = Hash.new
- attr[:flags] = []
- source.scan(ATTRIBUTE_SCAN) { |key, value|
- if not value
- attr[:flags] << unescape(key)
- else
- next if value.empty? and key.empty?
- attr[unescape(key)] = unescape(value)
- end
- }
- debug attr.inspect
-
- return empty_tag, attr
- end
-
- def self.unescape_char esc
- esc[1]
- end
-
- def self.unquote qt
- qt[1..-1].chomp('"').gsub(/\\./) { |esc| unescape_char esc }
- end
-
- def self.unescape str
- str.gsub(/ (\\.) | (" [^"\\]* (?:\\.[^"\\]*)* "?) /x) {
- if $1
- unescape_char $1
- else
- unquote $2
- end
- }
- end
-
- include Enumerable
- def each &block
- @args.each(&block)
- end
-
- attr_reader :source, :args, :value
-
- def initialize source
- @source = source
- debug 'Attribute#new(%p)' % source
- @empty_tag, @attr = Attribute.parse source
- @value = @attr[''].to_s
- end
-
- def empty?
- self == @@empty_attr
- end
-
- def empty_tag?
- @empty_tag
- end
-
- def [] *keys
- res = @attr[*keys]
- end
-
- def flags
- attr[:flags]
- end
-
- def to_s
- @attr
- end
-
- def inspect
- 'ATTR[' + @attr.inspect + (@empty_tag ? ' | empty tag' : '') + ']'
- end
- end
- class Attribute
- @@empty_attr = new ''
- end
- end
-
- class Parser
- def Parser.flatten str
- # replace mac & dos newlines with unix style
- str.gsub(/\r\n?/, "\n")
- end
-
- def initialize input = ''
- # input manager
- @scanner = StringScanner.new ''
- # output manager
- @encoder = Encoder.new
- @output = ''
- # tag manager
- @tagstack = TagStack.new(@encoder)
-
- @do_magic = true
- # set the input
- feed input
- end
-
- # if you want, you can feed a parser instance after creating,
- # or even feed it repeatedly.
- def feed food
- @scanner.string = Parser.flatten food
- end
-
- # parse through the string using parse_token
- def parse
- parse_token until @scanner.eos?
- @tagstack.close_all
- @output = parse_magic @encoder.output
- end
-
- def output
- @output
- end
-
- # ok, internals start here
- private
- # the default output functions. everything should use them or the tags.
- def add_text text = @scanner.matched
- @encoder.add_text text
- end
-
- # use this carefully
- def add_html html
- @encoder.add_html html
- end
-
- # highlights the text as error
- def add_garbage garbage
- add_html '<span class="error">' if DEBUG
- add_text garbage
- add_html '</span>' if DEBUG
- end
-
- # unknown and incorrectly nested tags are ignored and
- # sent as plaintext (garbage in - garbage out).
- # in debug mode, garbage is marked with lime background.
- def garbage_out start
- @scanner.pos = start
- garbage = @scanner.scan(/./m)
- debug 'GARBAGE: ' + garbage
- add_garbage garbage
- end
-
- # simple text; everything but [, \[ allowed
- SIMPLE_TEXT_SCAN_ = /
- [^\[\\]* # normal*
- (?: # (
- \\.? # special
- [^\[\\]* # normal*
- )* # )*
- /mx
- SIMPLE_TEXT_SCAN = /[^\[]+/
-
-=begin
-
- WHAT IS A TAG?
- ==============
-
- Tags in BBCode can be much more than just a simple [b].
- I use many terms here to differ the parts of each tag.
-
- Basic scheme:
- [ code ]
- TAG START TAG INFO TAG END
-
- Most tags need a second tag to close the range it opened.
- This is done with CLOSING TAGS:
- [/code]
- or by using empty tags that have no content and close themselfes:
- [url=winamp.com /]
- You surely know this from HTML.
- These slashes define the TAG KIND = normal|closing|empty and
- cannot be used together.
-
- Everything between [ and ] and expluding the slashes is called the
- TAG INFO. This info may contain:
- - TAG ID
- - TAG NAME including the tag id
- - attributes
-
- The TAG ID is the first char of the info:
-
- TAG | ID
- ----------+----
- [quote] | q
- [&plusmn] | &
- ["[b]"] | "
- [/url] | u
- [---] | -
-
- As you can see, the tag id shows the TAG TYPE, it can be a
- normal tag, a formatting tag or an entity.
- Therefor, the parser first scans the id to decide how to go
- on with parsing.
-=end
- # tag
- # TODO more complex expression allowing
- # [quote="[ladico]"] and [quote=\[ladico\]] to be correct tags
- TAG_BEGIN_SCAN = /
- \[ # tag start
- ( \/ )? # $1 = closing tag?
- ( [^\]] ) # $2 = tag id
- /x
- TAG_END_SCAN = /
- [^\]]* # rest that was not handled
- \]? # tag end
- /x
- CLOSE_TAG_SCAN = /
- ( [^\]]* ) # $1 = the rest of the tag info
- ( \/ )? # $2 = empty tag?
- \]? # tag end
- /x
- UNCLOSED_TAG_SCAN = / \[ /x
-
- CLASSIC_TAG_SCAN = / [a-z]* /ix
-
- SEPARATOR_TAG_SCAN = / \** /x
-
- FORMAT_TAG_SCAN = / -- -* /x
-
- QUOTED_SCAN = /
- ( # $1 = quoted text
- [^"\\]* # normal*
- (?: # (
- \\. # special
- [^"\\]* # normal*
- )* # )*
- )
- "? # end quote "
- /mx
-
- ENTITY_SCAN = /
- ( [^;\]]+ ) # $1 = entity code
- ;? # optional ending semicolon
- /ix
-
- SMILEY_SCAN = Smileys::SMILEY_PATTERN
-
- # this is the main parser loop that separates
- # text - everything until "["
- # from
- # tags - starting with "[", ending with "]"
- def parse_token
- if @scanner.scan(SIMPLE_TEXT_SCAN)
- add_text
- else
- handle_tag
- end
- end
-
- def handle_tag
- tag_start = @scanner.pos
-
- unless @scanner.scan TAG_BEGIN_SCAN
- garbage_out tag_start
- return
- end
-
- closing, id = @scanner[1], @scanner[2]
- #debug 'handle_tag(%p)' % @scanner.matched
-
- handled =
- case id
-
- when /[a-z]/i
- if @scanner.scan(CLASSIC_TAG_SCAN)
- if handle_classic_tag(id + @scanner.matched, closing)
- already_closed = true
- end
- end
-
- when '*'
- if @scanner.scan(SEPARATOR_TAG_SCAN)
- handle_asterisk tag_start, id + @scanner.matched
- true
- end
-
- when '-'
- if @scanner.scan(FORMAT_TAG_SCAN)
- #format = id + @scanner.matched
- @encoder.add_html "\n<hr>\n"
- true
- end
-
- when '"'
- if @scanner.scan(QUOTED_SCAN)
- @encoder.add_text unescape(@scanner[1])
- true
- end
-
- when '&'
- if @scanner.scan(ENTITY_SCAN)
- @encoder.add_entity @scanner[1]
- true
- end
-
- when Smileys::SMILEY_START_CHARSET
- @scanner.pos = @scanner.pos - 1 # (ungetch)
- if @scanner.scan(SMILEY_SCAN)
- @encoder.add_html Smileys.smiley_to_image(@scanner.matched)
- true
- end
-
- end # case
-
- return garbage_out(tag_start) unless handled
-
- @scanner.scan(TAG_END_SCAN) unless already_closed
- end
-
- ATTRIBUTES_SCAN = /
- (
- [^\]"\\]*
- (?:
- (?:
- \\.
- |
- "
- [^"\\]*
- (?:
- \\.
- [^"\\]*
- )*
- "?
- )
- [^\]"\\]*
- )*
- )
- \]?
- /x
-
- def handle_classic_tag name, closing
- debug 'TAG: ' + (closing ? '/' : '') + name
- # flatten
- name.downcase!
- tag_class = TAG_LIST[name]
- return unless tag_class
-
- #debug((opening ? 'OPEN ' : 'CLOSE ') + tag_class.name)
-
- # create an attribute object to handle it
- @scanner.scan(ATTRIBUTES_SCAN)
- #debug name + ':' + @scanner[1]
- attr = Attribute.create @scanner[1]
- #debug 'ATTRIBUTES %p ' % attr #unless attr.empty?
-
- #debug 'closing: %p; name=%s, attr=%p' % [closing, name, attr]
-
- # OPEN
- if not closing and tag = @tagstack.try_open_class(tag_class, attr)
- #debug 'opening'
- tag.do_open @scanner
- # this should be done by the tag itself.
- if attr.empty_tag?
- tag.handle_empty
- @tagstack.close_tag
- elsif tag.special_content?
- handle_special_content(tag)
- @tagstack.close_tag
- # # ignore asterisks directly after the opening; these are phpBBCode
- # elsif tag.respond_to? :asterisk
- # debug 'SKIP ASTERISKS: ' if @scanner.skip(ASTERISK_TAGS_SCAN)
- end
-
- # CLOSE
- elsif @tagstack.try_close_class(tag_class)
- #debug 'closing'
- # GARBAGE
- else
- return
- end
-
- true
- end
-
- def handle_asterisk tag_start, stars
- #debug 'ASTERISK: ' + stars.to_s
- # rule for asterisk tags: they belong to the last tag
- # that handles them. tags opened after this tag are closed.
- # if no open tag uses them, all are closed.
- tag = @tagstack.close_all_until { |tag| tag.respond_to? :asterisk }
- unless tag and tag.asterisk stars, @scanner
- garbage_out tag_start
- end
- end
-
- def handle_special_content tag
- scanned = @scanner.scan_until(tag.closing_tag)
- if scanned
- scanned.slice!(-(@scanner.matched.size)..-1)
- else
- scanned = @scanner.scan(/.*/m).to_s
- end
- #debug 'SPECIAL CONTENT: ' + scanned
- tag.handle_content(scanned)
- end
-
- def unescape text
- # input: correctly formatted quoted string (without the quotes)
- text.gsub(/\\(?:(["\\])|.)/) { $1 or $& }
- end
-
-
- # MAGIC FEAUTURES
-
- URL_PATTERN = /(?:(?:www|ftp)\.|(?>\w{3,}):\/\/)\S+/
- EMAIL_PATTERN = /(?>[\w\-_.]+)@[\w\-\.]+\.\w+/
-
- HAS_MAGIC = /[&@#{Smileys::SMILEY_START_CHARS}]|(?i:www|ftp)/
-
- MAGIC_PATTERN = Regexp.new('(\W|^)(%s)' %
- [Smileys::MAGIC_SMILEY_PATTERN, URL_PATTERN, EMAIL_PATTERN].map { |pattern|
- pattern.to_s
- }.join('|') )
-
- IS_SMILEY_PATTERN = Regexp.new('^%s' % Smileys::SMILEY_START_CHARSET.to_s )
- IS_URL_PATTERN = /^(?:(?i:www|ftp)\.|(?>\w+):\/\/)/
- URL_STARTS_WITH_PROTOCOL = /^\w+:\/\//
- IS_EMAIL_PATTERN = /^[\w\-_.]+@/
-
- def to_magic text
- # debug MAGIC_PATTERN.to_s
- text.gsub!(MAGIC_PATTERN) {
- magic = $2
- $1 + case magic
- when IS_SMILEY_PATTERN
- Smileys.smiley_to_img magic
- when IS_URL_PATTERN
- last = magic.slice_punctation! # no punctation in my URL
- href = magic
- href.insert(0, 'http://') unless magic =~ URL_STARTS_WITH_PROTOCOL
- '<a href="' + href + '">' + magic + '</a>' + last
- when IS_EMAIL_PATTERN
- last = magic.slice_punctation!
- '<a href="mailto:' + magic + '">' + magic + '</a>' + last
- else
- raise '{{{' + magic + '}}}'
- end
- }
- text
- end
-
- # handles smileys and urls
- def parse_magic html
- return html unless @do_magic
- scanner = StringScanner.new html
- out = ''
- while scanner.rest?
- if scanner.scan(/ < (?: a\s .*? <\/a> | pre\W .*? <\/pre> | [^>]* > ) /mx)
- out << scanner.matched
- elsif scanner.scan(/ [^<]+ /x)
- out << to_magic(scanner.matched)
-
- # this should never happen
- elsif scanner.scan(/./m)
- raise 'ERROR: else case reached'
- end
- end
- out
- end
- end # Parser
-end
-
-class String
- def slice_punctation!
- slice!(/[.:,!\?]+$/).to_s # return '' instead of nil
- end
-end
-
-#
-# = Grammar
-#
-# An implementation of common algorithms on grammars.
-#
-# This is used by Shinobu, a visualization tool for educating compiler-building.
-#
-# Thanks to Andreas Kunert for his wonderful LR(k) Pamphlet (German, see http://www.informatik.hu-berlin.de/~kunert/papers/lr-analyse), and Aho/Sethi/Ullman for their Dragon Book.
-#
-# Homepage:: http://shinobu.cYcnus.de (not existing yet)
-# Author:: murphy (Kornelius Kalnbach)
-# Copyright:: (cc) 2005 cYcnus
-# License:: GPL
-# Version:: 0.2.0 (2005-03-27)
-
-require 'set_hash'
-require 'ctype'
-require 'tools'
-require 'rules'
-require 'trace'
-
-require 'first'
-require 'follow'
-
-# = Grammar
-#
-# == Syntax
-#
-# === Rules
-#
-# Each line is a rule.
-# The syntax is
-#
-# left - right
-#
-# where +left+ and +right+ can be uppercase and lowercase letters,
-# and <code>-</code> can be any combination of <, >, - or whitespace.
-#
-# === Symbols
-#
-# Uppercase letters stand for meta symbols, lowercase for terminals.
-#
-# You can make epsilon-derivations by leaving <code><right></code> empty.
-#
-# === Example
-# S - Ac
-# A - Sc
-# A - b
-# A -
-class Grammar
-
- attr_reader :tracer
- # Creates a new Grammar.
- # If $trace is true, the algorithms explain (textual) what they do to $stdout.
- def initialize data, tracer = Tracer.new
- @tracer = tracer
- @rules = Rules.new
- @terminals, @meta_symbols = SortedSet.new, Array.new
- @start_symbol = nil
- add_rules data
- end
-
- attr_reader :meta_symbols, :terminals, :rules, :start_symbol
-
- alias_method :sigma, :terminals
- alias_method :alphabet, :terminals
- alias_method :variables, :meta_symbols
- alias_method :nonterminals, :meta_symbols
-
- # A string representation of the grammar for debugging.
- def inspect productions_too = false
- 'Grammar(meta symbols: %s; alphabet: %s; productions: [%s]; start symbol: %s)' %
- [
- meta_symbols.join(', '),
- terminals.join(', '),
- if productions_too
- @rules.inspect
- else
- @rules.size
- end,
- start_symbol
- ]
- end
-
- # Add rules to the grammar. +rules+ should be a String or respond to +scan+ in a similar way.
- #
- # Syntax: see Grammar.
- def add_rules grammar
- @rules = Rules.parse grammar do |rule|
- @start_symbol ||= rule.left
- @meta_symbols << rule.left
- @terminals.merge rule.right.split('').select { |s| terminal? s }
- end
- @meta_symbols.uniq!
- update
- end
-
- # Returns a hash acting as FIRST operator, so that
- # <code>first["ABC"]</code> is FIRST(ABC).
- # See http://en.wikipedia.org/wiki/LL_parser "Constructing an LL(1) parsing table" for details.
- def first
- first_operator
- end
-
- # Returns a hash acting as FOLLOW operator, so that
- # <code>first["A"]</code> is FOLLOW(A).
- # See http://en.wikipedia.org/wiki/LL_parser "Constructing an LL(1) parsing table" for details.
- def follow
- follow_operator
- end
-
- LLError = Class.new(Exception)
- LLErrorType1 = Class.new(LLError)
- LLErrorType2 = Class.new(LLError)
-
- # Tests if the grammar is LL(1).
- def ll1?
- begin
- for meta in @meta_symbols
- first_sets = @rules[meta].map { |alpha| first[alpha] }
- first_sets.inject(Set[]) do |already_used, another_first_set|
- unless already_used.disjoint? another_first_set
- raise LLErrorType1
- end
- already_used.merge another_first_set
- end
-
- if first[meta].include? EPSILON and not first[meta].disjoint? follow[meta]
- raise LLErrorType2
- end
- end
- rescue LLError
- false
- else
- true
- end
- end
-
-private
-
- def first_operator
- @first ||= FirstOperator.new self
- end
-
- def follow_operator
- @follow ||= FollowOperator.new self
- end
-
- def update
- @first = @follow = nil
- end
-
-end
-
-if $0 == __FILE__
- eval DATA.read, nil, $0, __LINE__+4
-end
-
-require 'test/unit'
-
-class TestCaseGrammar < Test::Unit::TestCase
-
- include Grammar::Symbols
-
- def fifo s
- Set[*s.split('')]
- end
-
- def test_fifo
- assert_equal Set[], fifo('')
- assert_equal Set[EPSILON, END_OF_INPUT, 'x', 'Y'], fifo('?xY$')
- end
-
- TEST_GRAMMAR_1 = <<-EOG
-S - ABCD
-A - a
-A -
-B - b
-B -
-C - c
-C -
-D - S
-D -
- EOG
-
- def test_symbols
- assert EPSILON
- assert END_OF_INPUT
- end
-
- def test_first_1
- g = Grammar.new TEST_GRAMMAR_1
-
- f = nil
- assert_nothing_raised { f = g.first }
- assert_equal(Set['a', EPSILON], f['A'])
- assert_equal(Set['b', EPSILON], f['B'])
- assert_equal(Set['c', EPSILON], f['C'])
- assert_equal(Set['a', 'b', 'c', EPSILON], f['D'])
- assert_equal(f['D'], f['S'])
- end
-
- def test_follow_1
- g = Grammar.new TEST_GRAMMAR_1
-
- f = nil
- assert_nothing_raised { f = g.follow }
- assert_equal(Set['a', 'b', 'c', END_OF_INPUT], f['A'])
- assert_equal(Set['a', 'b', 'c', END_OF_INPUT], f['B'])
- assert_equal(Set['a', 'b', 'c', END_OF_INPUT], f['C'])
- assert_equal(Set[END_OF_INPUT], f['D'])
- assert_equal(Set[END_OF_INPUT], f['S'])
- end
-
-
- TEST_GRAMMAR_2 = <<-EOG
-S - Ed
-E - EpT
-E - EmT
-E - T
-T - TuF
-T - TdF
-T - F
-F - i
-F - n
-F - aEz
- EOG
-
- def test_first_2
- g = Grammar.new TEST_GRAMMAR_2
-
- f = nil
- assert_nothing_raised { f = g.first }
- assert_equal(Set['a', 'n', 'i'], f['E'])
- assert_equal(Set['a', 'n', 'i'], f['F'])
- assert_equal(Set['a', 'n', 'i'], f['T'])
- assert_equal(Set['a', 'n', 'i'], f['S'])
- end
-
- def test_follow_2
- g = Grammar.new TEST_GRAMMAR_2
-
- f = nil
- assert_nothing_raised { f = g.follow }
- assert_equal(Set['m', 'd', 'z', 'p'], f['E'])
- assert_equal(Set['m', 'd', 'z', 'p', 'u'], f['F'])
- assert_equal(Set['m', 'd', 'z', 'p', 'u'], f['T'])
- assert_equal(Set[END_OF_INPUT], f['S'])
- end
-
- LLError = Grammar::LLError
-
- TEST_GRAMMAR_3 = <<-EOG
-E - TD
-D - pTD
-D -
-T - FS
-S - uFS
-S -
-S - p
-F - aEz
-F - i
- EOG
-
- NoError = Class.new(Exception)
-
- def test_first_3
- g = Grammar.new TEST_GRAMMAR_3
-
- # Grammar 3 is LL(1), so all first-sets must be disjoint.
- f = nil
- assert_nothing_raised { f = g.first }
- assert_equal(Set['a', 'i'], f['E'])
- assert_equal(Set[EPSILON, 'p'], f['D'])
- assert_equal(Set['a', 'i'], f['F'])
- assert_equal(Set['a', 'i'], f['T'])
- assert_equal(Set[EPSILON, 'u', 'p'], f['S'])
- for m in g.meta_symbols
- r = g.rules[m]
- firsts = r.map { |x| f[x] }.to_set
- assert_nothing_raised do
- firsts.inject(Set.new) do |already_used, another_first_set|
- raise LLError, 'not disjoint!' unless already_used.disjoint? another_first_set
- already_used.merge another_first_set
- end
- end
- end
- end
-
- def test_follow_3
- g = Grammar.new TEST_GRAMMAR_3
-
- # Grammar 3 is not LL(1), because epsilon is in FIRST(S),
- # but FIRST(S) and FOLLOW(S) are not disjoint.
- f = nil
- assert_nothing_raised { f = g.follow }
- assert_equal(Set['z', END_OF_INPUT], f['E'])
- assert_equal(Set['z', END_OF_INPUT], f['D'])
- assert_equal(Set['z', 'p', 'u', END_OF_INPUT], f['F'])
- assert_equal(Set['p', 'z', END_OF_INPUT], f['T'])
- assert_equal(Set['p', 'z', END_OF_INPUT], f['S'])
- for m in g.meta_symbols
- first_m = g.first[m]
- next unless first_m.include? EPSILON
- assert_raise(m == 'S' ? LLError : NoError) do
- if first_m.disjoint? f[m]
- raise NoError # this is fun :D
- else
- raise LLError
- end
- end
- end
- end
-
- TEST_GRAMMAR_3b = <<-EOG
-E - TD
-D - pTD
-D - PTD
-D -
-T - FS
-S - uFS
-S -
-F - aEz
-F - i
-P - p
- EOG
-
- def test_first_3b
- g = Grammar.new TEST_GRAMMAR_3b
-
- # Grammar 3b is NOT LL(1), since not all first-sets are disjoint.
- f = nil
- assert_nothing_raised { f = g.first }
- assert_equal(Set['a', 'i'], f['E'])
- assert_equal(Set[EPSILON, 'p'], f['D'])
- assert_equal(Set['p'], f['P'])
- assert_equal(Set['a', 'i'], f['F'])
- assert_equal(Set['a', 'i'], f['T'])
- assert_equal(Set[EPSILON, 'u'], f['S'])
- for m in g.meta_symbols
- r = g.rules[m]
- firsts = r.map { |x| f[x] }
- assert_raise(m == 'D' ? LLError : NoError) do
- firsts.inject(Set.new) do |already_used, another_first_set|
- raise LLError, 'not disjoint!' unless already_used.disjoint? another_first_set
- already_used.merge another_first_set
- end
- raise NoError
- end
- end
- end
-
- def test_follow_3b
- g = Grammar.new TEST_GRAMMAR_3b
-
- # Although Grammar 3b is NOT LL(1), the FOLLOW-condition is satisfied.
- f = nil
- assert_nothing_raised { f = g.follow }
- assert_equal(fifo('z$'), f['E'], 'E')
- assert_equal(fifo('z$'), f['D'], 'D')
- assert_equal(fifo('ai'), f['P'], 'P')
- assert_equal(fifo('z$pu'), f['F'], 'F')
- assert_equal(fifo('z$p'), f['T'], 'T')
- assert_equal(fifo('z$p'), f['S'], 'S')
- for m in g.meta_symbols
- first_m = g.first[m]
- next unless first_m.include? EPSILON
- assert_raise(NoError) do
- if first_m.disjoint? f[m]
- raise NoError # this is fun :D
- else
- raise LLError
- end
- end
- end
- end
-
- def test_ll1?
- assert_equal false, Grammar.new(TEST_GRAMMAR_3).ll1?, 'Grammar 3'
- assert_equal false, Grammar.new(TEST_GRAMMAR_3b).ll1?, 'Grammar 3b'
- end
-
- def test_new
- assert_nothing_raised { Grammar.new '' }
- assert_nothing_raised { Grammar.new TEST_GRAMMAR_1 }
- assert_nothing_raised { Grammar.new TEST_GRAMMAR_2 }
- assert_nothing_raised { Grammar.new TEST_GRAMMAR_3 }
- assert_nothing_raised { Grammar.new TEST_GRAMMAR_1 + TEST_GRAMMAR_2 + TEST_GRAMMAR_3 }
- assert_raise(ArgumentError) { Grammar.new 'S - ?' }
- end
-end
-
-# vim:foldmethod=syntax
-
-#!/usr/bin/env ruby
-
-require 'fox12'
-
-include Fox
-
-class Window < FXMainWindow
- def initialize(app)
- super(app, app.appName + ": First Set Calculation", nil, nil, DECOR_ALL, 0, 0, 800, 600, 0, 0)
-
- # {{{ menubar
- menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
-
- filemenu = FXMenuPane.new(self)
-
- FXMenuCommand.new(filemenu, "&Start\tCtl-S\tStart the application.", nil, getApp()).connect(SEL_COMMAND, method(:start))
- FXMenuCommand.new(filemenu, "&Quit\tAlt-F4\tQuit the application.", nil, getApp(), FXApp::ID_QUIT)
- FXMenuTitle.new(menubar, "&File", nil, filemenu)
- # }}} menubar
-
- # {{{ statusbar
- @statusbar = FXStatusBar.new(self, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|STATUSBAR_WITH_DRAGCORNER)
- # }}} statusbar
-
- # {{{ window content
- horizontalsplitt = FXSplitter.new(self, SPLITTER_VERTICAL|LAYOUT_SIDE_TOP|LAYOUT_FILL)
-
-
- @productions = FXList.new(horizontalsplitt, nil, 0, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FIX_HEIGHT|LIST_SINGLESELECT)
- @productions.height = 100
-
- @result = FXTable.new(horizontalsplitt, nil, 0, LAYOUT_FILL)
- @result.height = 200
- @result.setTableSize(2, 2, false)
- @result.rowHeaderWidth = 0
-
- header = @result.columnHeader
- header.setItemText 0, 'X'
- header.setItemText 1, 'FIRST(X)'
- for item in header
- item.justification = FXHeaderItem::CENTER_X
- end
-
- @debug = FXText.new(horizontalsplitt, nil, 0, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|LAYOUT_FIX_HEIGHT)
- @debug.height = 200
-
- # }}} window content
- end
-
- def load_grammar grammar
- @tracer = FirstTracer.new(self)
- @grammar = Grammar.new grammar, @tracer
- @rules_indexes = Hash.new
- @grammar.rules.each_with_index do |rule, i|
- @productions.appendItem rule.inspect
- @rules_indexes[rule] = i
- end
- end
-
- def create
- super
- show(PLACEMENT_SCREEN)
- end
-
- def rule rule
- @productions.selectItem @rules_indexes[rule]
- sleep 0.1
- end
-
- def iterate i
- setTitle i.to_s
- sleep 0.1
- end
-
- def missing what
- @debug.appendText what + "\n"
- sleep 0.1
- end
-
- def start sender, sel, pointer
- Thread.new do
- begin
- @grammar.first
- rescue => boom
- @debug.appendText [boom.to_s, *boom.backtrace].join("\n")
- end
- end
- end
-
-end
-
-$: << 'grammar'
-require 'grammar'
-
-require 'first_tracer'
-
-app = FXApp.new("Shinobu", "cYcnus")
-
-# fenster erzeugen
-window = Window.new app
-
-unless ARGV.empty?
- grammar = File.read(ARGV.first)
-else
- grammar = <<-EOG1
-Z --> S
-S --> Sb
-S --> bAa
-A --> aSc
-A --> a
-A --> aSb
- EOG1
-end
-
-window.load_grammar grammar
-
-app.create
-app.run
-
-require 'erb'
-require 'ftools'
-require 'yaml'
-require 'redcloth'
-
-module WhyTheLuckyStiff
- class Book
- attr_accessor :author, :title, :terms, :image, :teaser,
- :chapters, :expansion_paks, :encoding, :credits
- def [] x
- @lang.fetch(x) do
- warn warning = "[not translated: '#{x}'!]"
- warning
- end
- end
- end
-
- def Book::load( file_name )
- YAML::load( File.open( file_name ) )
- end
-
- class Section
- attr_accessor :index, :header, :content
- def initialize( i, h, c )
- @index, @header, @content = i, h, RedCloth::new( c.to_s )
- end
- end
-
- class Sidebar
- attr_accessor :title, :content
- end
-
- YAML::add_domain_type( 'whytheluckystiff.net,2003', 'sidebar' ) do |taguri, val|
- YAML::object_maker( Sidebar, 'title' => val.keys.first, 'content' => RedCloth::new( val.values.first ) )
- end
- class Chapter
- attr_accessor :index, :title, :sections
- def initialize( i, t, sects )
- @index = i
- @title = t
- i = 0
- @sections = sects.collect do |s|
- if s.respond_to?( :keys )
- i += 1
- Section.new( i, s.keys.first, s.values.first )
- else
- s
- end
- end
- end
- end
-
- YAML::add_domain_type( 'whytheluckystiff.net,2003', 'book' ) do |taguri, val|
- ['chapters', 'expansion_paks'].each do |chaptype|
- i = 0
- val[chaptype].collect! do |c|
- i += 1
- Chapter::new( i, c.keys.first, c.values.first )
- end
- end
- val['teaser'].collect! do |t|
- Section::new( 1, t.keys.first, t.values.first )
- end
- val['terms'] = RedCloth::new( val['terms'] )
- YAML::object_maker( Book, val )
- end
-
- class Image
- attr_accessor :file_name
- end
-
- YAML::add_domain_type( 'whytheluckystiff.net,2003', 'img' ) do |taguri, val|
- YAML::object_maker( Image, 'file_name' => "i/" + val )
- end
-end
-
-#
-# Convert the book to HTML
-#
-if __FILE__ == $0
- unless ARGV[0]
- puts "Usage: #{$0} [/path/to/save/html]"
- exit
- end
-
- site_path = ARGV[0]
- book = WhyTheLuckyStiff::Book::load( 'poignant.yml' )
- chapter = nil
-
- # Write index page
- index_tpl = ERB::new( File.open( 'index.erb' ).read )
- File.open( File.join( site_path, 'index.html' ), 'w' ) do |out|
- out << index_tpl.result
- end
-
- book.chapters = book.chapters[0,3] if ARGV.include? '-fast'
-
- # Write chapter pages
- chapter_tpl = ERB::new( File.open( 'chapter.erb' ).read )
- book.chapters.each do |chapter|
- File.open( File.join( site_path, "chapter-#{ chapter.index }.html" ), 'w' ) do |out|
- out << chapter_tpl.result
- end
- end
- exit if ARGV.include? '-fast'
-
- # Write expansion pak pages
- expak_tpl = ERB::new( File.open( 'expansion-pak.erb' ).read )
- book.expansion_paks.each do |pak|
- File.open( File.join( site_path, "expansion-pak-#{ pak.index }.html" ), 'w' ) do |out|
- out << expak_tpl.result( binding )
- end
- end
-
- # Write printable version
- print_tpl = ERB::new( File.open( 'print.erb' ).read )
- File.open( File.join( site_path, "print.html" ), 'w' ) do |out|
- out << print_tpl.result
- end
-
- # Copy css + images into site
- copy_list = ["guide.css"] +
- Dir["i/*"].find_all { |image| image =~ /\.(gif|jpg|png)$/ }
-
- File.makedirs( File.join( site_path, "i" ) )
- copy_list.each do |copy_file|
- File.copy( copy_file, File.join( site_path, copy_file ) )
- end
-end
-
-#!/usr/bin/env ruby
-
-require 'fox'
-begin
- require 'opengl'
-rescue LoadError
- require 'fox/missingdep'
- MSG = <<EOM
- Sorry, this example depends on the OpenGL extension. Please
- check the Ruby Application Archives for an appropriate
- download site.
-EOM
- missingDependency(MSG)
-end
-
-
-include Fox
-include Math
-
-Deg2Rad = Math::PI / 180
-
-D_MAX = 6
-SQUARE_SIZE = 2.0 / D_MAX
-SQUARE_DISTANCE = 4.0 / D_MAX
-AMPLITUDE = SQUARE_SIZE
-LAMBDA = D_MAX.to_f / 2
-
-class GLTestWindow < FXMainWindow
-
- # How often our timer will fire (in milliseconds)
- TIMER_INTERVAL = 500
-
- # Rotate the boxes when a timer message is received
- def onTimeout(sender, sel, ptr)
- @angle += 10.0
-# @size = 0.5 + 0.2 * Math.cos(Deg2Rad * @angle)
- drawScene()
- @timer = getApp().addTimeout(TIMER_INTERVAL, method(:onTimeout))
- end
-
- # Rotate the boxes when a chore message is received
- def onChore(sender, sel, ptr)
- @angle += 10.0
-# @angle %= 360.0
-# @size = 0.5 + 0.2 * Math.cos(Deg2Rad * @angle)
- drawScene()
- @chore = getApp().addChore(method(:onChore))
- end
-
- # Draw the GL scene
- def drawScene
- lightPosition = [15.0, 10.0, 5.0, 1.0]
- lightAmbient = [ 0.1, 0.1, 0.1, 1.0]
- lightDiffuse = [ 0.9, 0.9, 0.9, 1.0]
- redMaterial = [ 0.0, 0.0, 1.0, 1.0]
- blueMaterial = [ 0.0, 1.0, 0.0, 1.0]
-
- width = @glcanvas.width.to_f
- height = @glcanvas.height.to_f
- aspect = width/height
-
- # Make context current
- @glcanvas.makeCurrent()
-
- GL.Viewport(0, 0, @glcanvas.width, @glcanvas.height)
-
- GL.ClearColor(1.0/256, 0.0, 5.0/256, 1.0)
- GL.Clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT)
- GL.Enable(GL::DEPTH_TEST)
-
- GL.Disable(GL::DITHER)
-
- GL.MatrixMode(GL::PROJECTION)
- GL.LoadIdentity()
- GLU.Perspective(30.0, aspect, 1.0, 100.0)
-
- GL.MatrixMode(GL::MODELVIEW)
- GL.LoadIdentity()
- GLU.LookAt(5.0, 10.0, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
-
- GL.ShadeModel(GL::SMOOTH)
- GL.Light(GL::LIGHT0, GL::POSITION, lightPosition)
- GL.Light(GL::LIGHT0, GL::AMBIENT, lightAmbient)
- GL.Light(GL::LIGHT0, GL::DIFFUSE, lightDiffuse)
- GL.Enable(GL::LIGHT0)
- GL.Enable(GL::LIGHTING)
-
- GL.Rotated(0.1*@angle, 0.0, 1.0, 0.0)
- for x in -D_MAX..D_MAX
- for y in -D_MAX..D_MAX
- h1 = (x + y - 2).abs
- h2 = (y - x + 1).abs
- GL.PushMatrix
- c = [1, 0, 0, 1]
- GL.Material(GL::FRONT, GL::AMBIENT, c)
- GL.Material(GL::FRONT, GL::DIFFUSE, c)
-
- GL.Translated(
- y * SQUARE_DISTANCE,
- AMPLITUDE * h1,
- x * SQUARE_DISTANCE
- )
-
- GL.Begin(GL::TRIANGLE_STRIP)
- GL.Normal(1.0, 0.0, 0.0)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.End
-
- GL.PopMatrix
-
- GL.PushMatrix
- c = [0, 0, 1, 1]
- GL.Material(GL::FRONT, GL::AMBIENT, c)
- GL.Material(GL::FRONT, GL::DIFFUSE, c)
-
- GL.Translated(
- y * SQUARE_DISTANCE,
- AMPLITUDE * h2,
- x * SQUARE_DISTANCE
- )
-
- GL.Begin(GL::TRIANGLE_STRIP)
- GL.Normal(1.0, 0.0, 0.0)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.End
-
- GL.PopMatrix
-
- GL.PushMatrix
- c = [0.0 + (x/10.0), 0.0 + (y/10.0), 0, 1]
- GL.Material(GL::FRONT, GL::AMBIENT, c)
- GL.Material(GL::FRONT, GL::DIFFUSE, c)
-
- GL.Translated(
- y * SQUARE_DISTANCE,
- 0,
- x * SQUARE_DISTANCE
- )
-
- GL.Begin(GL::TRIANGLE_STRIP)
- GL.Normal(1.0, 0.0, 0.0)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.End
-
- GL.PopMatrix
- end
- end
-
- # Swap if it is double-buffered
- if @glvisual.isDoubleBuffer
- @glcanvas.swapBuffers
- end
-
- # Make context non-current
- @glcanvas.makeNonCurrent
- end
-
- def initialize(app)
- # Invoke the base class initializer
- super(app, "OpenGL Test Application", nil, nil, DECOR_ALL, 0, 0, 1024, 768)
-
- # Construct the main window elements
- frame = FXHorizontalFrame.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y)
- frame.padLeft, frame.padRight = 0, 0
- frame.padTop, frame.padBottom = 0, 0
-
- # Left pane to contain the glcanvas
- glcanvasFrame = FXVerticalFrame.new(frame,
- LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
- glcanvasFrame.padLeft, glcanvasFrame.padRight = 10, 10
- glcanvasFrame.padTop, glcanvasFrame.padBottom = 10, 10
-
- # Label above the glcanvas
- FXLabel.new(glcanvasFrame, "OpenGL Canvas Frame", nil,
- JUSTIFY_CENTER_X|LAYOUT_FILL_X)
-
- # Horizontal divider line
- FXHorizontalSeparator.new(glcanvasFrame, SEPARATOR_GROOVE|LAYOUT_FILL_X)
-
- # Drawing glcanvas
- glpanel = FXVerticalFrame.new(glcanvasFrame, (FRAME_SUNKEN|FRAME_THICK|
- LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT))
- glpanel.padLeft, glpanel.padRight = 0, 0
- glpanel.padTop, glpanel.padBottom = 0, 0
-
- # A visual to draw OpenGL
- @glvisual = FXGLVisual.new(getApp(), VISUAL_DOUBLEBUFFER)
-
- # Drawing glcanvas
- @glcanvas = FXGLCanvas.new(glpanel, @glvisual, nil, 0,
- LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
- @glcanvas.connect(SEL_PAINT) {
- drawScene
- }
- @glcanvas.connect(SEL_CONFIGURE) {
- if @glcanvas.makeCurrent
- GL.Viewport(0, 0, @glcanvas.width, @glcanvas.height)
- @glcanvas.makeNonCurrent
- end
- }
-
- # Right pane for the buttons
- buttonFrame = FXVerticalFrame.new(frame, LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
- buttonFrame.padLeft, buttonFrame.padRight = 10, 10
- buttonFrame.padTop, buttonFrame.padBottom = 10, 10
-
- # Label above the buttons
- FXLabel.new(buttonFrame, "Button Frame", nil,
- JUSTIFY_CENTER_X|LAYOUT_FILL_X)
-
- # Horizontal divider line
- FXHorizontalSeparator.new(buttonFrame, SEPARATOR_RIDGE|LAYOUT_FILL_X)
-
- # Spin according to timer
- spinTimerBtn = FXButton.new(buttonFrame,
- "Spin &Timer\tSpin using interval timers\nNote the app
- blocks until the interal has elapsed...", nil,
- nil, 0, FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
- spinTimerBtn.padLeft, spinTimerBtn.padRight = 10, 10
- spinTimerBtn.padTop, spinTimerBtn.padBottom = 5, 5
- spinTimerBtn.connect(SEL_COMMAND) {
- @spinning = true
- @timer = getApp().addTimeout(TIMER_INTERVAL, method(:onTimeout))
- }
- spinTimerBtn.connect(SEL_UPDATE) { |sender, sel, ptr|
- @spinning ? sender.disable : sender.enable
- }
-
- # Spin according to chore
- spinChoreBtn = FXButton.new(buttonFrame,
- "Spin &Chore\tSpin as fast as possible using chores\nNote even though the
- app is very responsive, it never blocks;\nthere is always something to
- do...", nil,
- nil, 0, FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
- spinChoreBtn.padLeft, spinChoreBtn.padRight = 10, 10
- spinChoreBtn.padTop, spinChoreBtn.padBottom = 5, 5
- spinChoreBtn.connect(SEL_COMMAND) {
- @spinning = true
- @chore = getApp().addChore(method(:onChore))
- }
- spinChoreBtn.connect(SEL_UPDATE) { |sender, sel, ptr|
- @spinning ? sender.disable : sender.enable
- }
-
- # Stop spinning
- stopBtn = FXButton.new(buttonFrame,
- "&Stop Spin\tStop this mad spinning, I'm getting dizzy", nil,
- nil, 0, FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
- stopBtn.padLeft, stopBtn.padRight = 10, 10
- stopBtn.padTop, stopBtn.padBottom = 5, 5
- stopBtn.connect(SEL_COMMAND) {
- @spinning = false
- if @timer
- getApp().removeTimeout(@timer)
- @timer = nil
- end
- if @chore
- getApp().removeChore(@chore)
- @chore = nil
- end
- }
- stopBtn.connect(SEL_UPDATE) { |sender, sel, ptr|
- @spinning ? sender.enable : sender.disable
- }
-
- # Exit button
- exitBtn = FXButton.new(buttonFrame, "&Exit\tExit the application", nil,
- getApp(), FXApp::ID_QUIT,
- FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
- exitBtn.padLeft, exitBtn.padRight = 10, 10
- exitBtn.padTop, exitBtn.padBottom = 5, 5
-
- # Make a tooltip
- FXTooltip.new(getApp())
-
- # Initialize private variables
- @spinning = false
- @chore = nil
- @timer = nil
- @angle = 0.0
- @size = 0.5
- end
-
- # Create and initialize
- def create
- super
- show(PLACEMENT_SCREEN)
- end
-end
-
-if __FILE__ == $0
- # Construct the application
- application = FXApp.new("GLTest", "FoxTest")
-
- # To ensure that the chores-based spin will run as fast as possible,
- # we can disable the chore in FXRuby's event loop that tries to schedule
- # other threads. This is OK for this program because there aren't any
- # other Ruby threads running.
-
- #application.disableThreads
-
- # Construct the main window
- GLTestWindow.new(application)
-
- # Create the app's windows
- application.create
-
- # Run the application
- application.run
-end
-
-class Facelet
- attr_accessor :color
- def initialize(color)
- @color = color
- end
-
- def to_s
- @color
- end
-end
-
-class Edge
- attr_accessor :facelets, :colors
-
- def initialize(facelets)
- @facelets = facelets
- @colors = @facelets.map { |fl| fl.color }
- end
-
- def apply(edge)
- @facelets.each_with_index { |fl, i|
- fl.color = edge.colors[i]
- }
- end
-
- def inspect
- "\n%s %s\n%s %s %s" % facelets
- end
-end
-
-class Side
- attr_reader :num, :facelets
- attr_accessor :sides
-
- def initialize(num)
- @num = num
- @sides = []
- @facelets = []
- @fl_by_side = {}
- end
-
- # facelets & sides
- # 0
- # 0 1 2
- # 3 3 4 5 1
- # 6 7 8
- # 2
-
- def facelets=(facelets)
- @facelets = facelets.map { |c| Facelet.new(c) }
- init_facelet 0, 3,0
- init_facelet 1, 0
- init_facelet 2, 0,1
- init_facelet 3, 3
- init_facelet 5, 1
- init_facelet 6, 2,3
- init_facelet 7, 2
- init_facelet 8, 1,2
- end
-
- def <=>(side)
- self.num <=> side.num
- end
-
- def init_facelet(pos, *side_nums)
- sides = side_nums.map { |num| @sides[num] }.sort
- @fl_by_side[sides] = pos
- end
-
- def []=(color, *sides)
- @facelets[@fl_by_side[sides.sort]].color = color
- end
-
- def values_at(*sides)
- sides.map { |sides| @facelets[@fl_by_side[sides.sort]] }
- end
-
- def inspect(range=nil)
- if range
- @facelets.values_at(*(range.to_a)).join(' ')
- else
- <<-EOS.gsub(/\d/) { |num| @facelets[num.to_i] }.gsub(/[ABCD]/) { |side| @sides[side[0]-?A].num.to_s }
- A
- 0 1 2
- D 3 4 5 B
- 6 7 8
- C
- EOS
- end
- end
-
- def get_edge(side)
- trio = (-1..1).map { |x| (side + x) % 4 }
- prev_side, this_side, next_side = @sides.values_at(*trio)
- e = Edge.new(
- self .values_at( [this_side], [this_side, next_side] ) +
- this_side.values_at( [self, prev_side], [self ], [self, next_side] )
- )
- #puts 'Edge created for side %d: ' % side + e.inspect
- e
- end
-
- def turn(dir)
- #p 'turn side %d in %d' % [num, dir]
- edges = (0..3).map { |n| get_edge n }
- for i in 0..3
- edges[i].apply edges[(i-dir) % 4]
- end
- end
-end
-
-class Cube
- def initialize
- @sides = []
- %w(left front right back top bottom).each_with_index { |side, i|
- eval("@sides[#{i}] = @#{side} = Side.new(#{i})")
- }
- @left.sides = [@top, @front, @bottom, @back]
- @front.sides = [@top, @right, @bottom, @left]
- @right.sides = [@top, @back, @bottom, @front]
- @back.sides = [@top, @left, @bottom, @right]
- @top.sides = [@back, @right, @front, @left]
- @bottom.sides = [@front, @right, @back, @left]
- end
-
- def read_facelets(fs)
- pattern = Regexp.new(<<-EOP.gsub(/\w/, '\w').gsub(/\s+/, '\s*'))
- (w w w)
- (w w w)
- (w w w)
-(r r r) (g g g) (b b b) (o o o)
-(r r r) (g g g) (b b b) (o o o)
-(r r r) (g g g) (b b b) (o o o)
- (y y y)
- (y y y)
- (y y y)
- EOP
- md = pattern.match(fs).to_a
-
- @top.facelets = parse_facelets(md.values_at(1,2,3))
- @left.facelets = parse_facelets(md.values_at(4,8,12))
- @front.facelets = parse_facelets(md.values_at(5,9,13))
- @right.facelets = parse_facelets(md.values_at(6,10,14))
- @back.facelets = parse_facelets(md.values_at(7,11,15))
- @bottom.facelets = parse_facelets(md.values_at(16,17,18))
- end
-
- def turn(side, dir)
- #p 'turn %d in %d' % [side, dir]
- @sides[side].turn(dir)
- #puts inspect
- end
-
- def inspect
- <<-EOF.gsub(/(\d):(\d)-(\d)/) { @sides[$1.to_i].inspect(Range.new($2.to_i, $3.to_i)) }
- 4:0-2
- 4:3-5
- 4:6-8
-0:0-2 1:0-2 2:0-2 3:0-2
-0:3-5 1:3-5 2:3-5 3:3-5
-0:6-8 1:6-8 2:6-8 3:6-8
- 5:0-2
- 5:3-5
- 5:6-8
- EOF
- end
-
-private
- def parse_facelets(rows)
- rows.join.delete(' ').split(//)
- end
-end
-
-#$stdin = DATA
-
-gets.to_i.times do |i|
- puts "Scenario ##{i+1}:"
- fs = ''
- 9.times { fs << gets }
- cube = Cube.new
- cube.read_facelets fs
- gets.to_i.times do |t|
- side, dir = gets.split.map {|s| s.to_i}
- cube.turn(side, dir)
- end
- puts cube.inspect
- puts
-end
-
-# 2004 by murphy <korny@cYcnus.de>
-# GPL
-class Scenario
- class TimePoint
- attr_reader :data
- def initialize *data
- @data = data
- end
-
- def [] i
- @data[i] or 0
- end
-
- include Comparable
- def <=> tp
- r = 0
- [@data.size, tp.data.size].max.times do |i|
- r = self[i] <=> tp[i]
- return r if r.nonzero?
- end
- 0
- end
-
- def - tp
- r = []
- [@data.size, tp.data.size].max.times do |i|
- r << self[i] - tp[i]
- end
- r
- end
-
- def inspect
- # 01/01/1800 00:00:00
- '%02d/%02d/%04d %02d:%02d:%02d' % @data.values_at(1, 2, 0, 3, 4, 5)
- end
- end
-
- ONE_HOUR = TimePoint.new 0, 0, 0, 1, 0, 0
-
- APPOINTMENT_PATTERN = /
- ( \d{4} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s
- ( \d{4} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} )
- /x
-
- def initialize io
- @team_size = io.gets.to_i
- @data = [ [TimePoint.new(1800, 01, 01, 00, 00, 00), @team_size] ]
- @team_size.times do # each team member
- io.gets.to_i.times do # each appointment
- m = APPOINTMENT_PATTERN.match io.gets
- @data << [TimePoint.new(*m.captures[0,6].map { |x| x.to_i }), -1]
- @data << [TimePoint.new(*m.captures[6,6].map { |x| x.to_i }), +1]
- end
- end
- @data << [TimePoint.new(2200, 01, 01, 00, 00, 00), -@team_size]
- end
-
- def print_time_plan
- n = 0
- appointment = nil
- no_appointment = true
- @data.sort_by { |x| x[0] }.each do |x|
- tp, action = *x
- n += action
- # at any time during the meeting, at least two team members need to be there
- # and at most one team member is allowed to be absent
- if n >= 2 and (@team_size - n) <= 1
- appointment ||= tp
- else
- if appointment
- # the meeting should be at least one hour in length
- if TimePoint.new(*(tp - appointment)) >= ONE_HOUR
- puts 'appointment possible from %p to %p' % [appointment, tp]
- no_appointment = false
- end
- appointment = false
- end
- end
- end
- puts 'no appointment possible' if no_appointment
- end
-end
-
-# read the data
-DATA.gets.to_i.times do |si| # each scenario
- puts 'Scenario #%d:' % (si + 1)
- sc = Scenario.new DATA
- sc.print_time_plan
- puts
-end
-
-#__END__
-2
-3
-3
-2002 06 28 15 00 00 2002 06 28 18 00 00 TUD Contest Practice Session
-2002 06 29 10 00 00 2002 06 29 15 00 00 TUD Contest
-2002 11 15 15 00 00 2002 11 17 23 00 00 NWERC Delft
-4
-2002 06 25 13 30 00 2002 06 25 15 30 00 FIFA World Cup Semifinal I
-2002 06 26 13 30 00 2002 06 26 15 30 00 FIFA World Cup Semifinal II
-2002 06 29 13 00 00 2002 06 29 15 00 00 FIFA World Cup Third Place
-2002 06 30 13 00 00 2002 06 30 15 00 00 FIFA World Cup Final
-1
-2002 06 01 00 00 00 2002 06 29 18 00 00 Preparation of Problem Set
-2
-1
-1800 01 01 00 00 00 2200 01 01 00 00 00 Solving Problem 8
-0
-
-require 'token_consts'
-require 'symbol'
-require 'ctype'
-require 'error'
-
-class Fixnum
- # Treat char as a digit and return it's value as Fixnum.
- # Returns nonsense for non-digits.
- # Examples:
- # <code>
- # RUBY_VERSION[0].digit == '1.8.2'[0].digit == 1
- # </code>
- #
- # <code>
- # ?6.digit == 6
- # </code>
- #
- # <code>
- # ?A.digit == 17
- # </code>
- def digit
- self - ?0
- end
-end
-
-##
-# Stellt einen einfachen Scanner fr die lexikalische Analyse der Sprache Pas-0 dar.
-#
-# @author Andreas Kunert
-# Ruby port by murphy
-class Scanner
-
- include TokenConsts
-
- attr_reader :line, :pos
-
- # To allow Scanner.new without parameters.
- DUMMY_INPUT = 'dummy file'
- def DUMMY_INPUT.getc
- nil
- end
-
- ##
- # Erzeugt einen Scanner, der als Eingabe das bergebene IO benutzt.
- def initialize input = DUMMY_INPUT
- @line = 1
- @pos = 0
-
- begin
- @input = input
- @next_char = @input.getc
- rescue IOError # TODO show the reason!
- Error.ioError
- raise
- end
- end
-
- ##
- # Liest das n
- def read_next_char
- begin
- @pos += 1
- @current_char = @next_char
- @next_char = @input.getc
- rescue IOError
- Error.ioError
- raise
- end
- end
-
- ##
- # Sucht das n
- # PascalSymbol-Objekt und gibt es zurck.
- # @see Symbol
- # @return das gefundene Symbol als PascalSymbol-Objekt
- def get_symbol
- current_symbol = nil
- until current_symbol
- read_next_char
-
- if @current_char.alpha?
- identifier = @current_char.chr
- while @next_char.alpha? or @next_char.digit?
- identifier << @next_char
- read_next_char
- end
- current_symbol = handle_identifier(identifier.upcase)
- elsif @current_char.digit?
- current_symbol = number
- else
- case @current_char
- when ?\s
- # ignore
- when ?\n
- new_line
- when nil
- current_symbol = PascalSymbol.new EOP
- when ?{
- comment
-
- when ?:
- if @next_char == ?=
- read_next_char
- current_symbol = PascalSymbol.new BECOMES
- else
- current_symbol = PascalSymbol.new COLON
- end
-
- when ?<
- if (@next_char == ?=)
- read_next_char
- current_symbol = PascalSymbol.new LEQSY
- elsif (@next_char == ?>)
- read_next_char
- current_symbol = PascalSymbol.new NEQSY
- else
- current_symbol = PascalSymbol.new LSSSY
- end
-
- when ?>
- if (@next_char == ?=)
- read_next_char
- current_symbol = PascalSymbol.new GEQSY
- else
- current_symbol = PascalSymbol.new GRTSY
- end
-
- when ?. then current_symbol = PascalSymbol.new PERIOD
- when ?( then current_symbol = PascalSymbol.new LPARENT
- when ?, then current_symbol = PascalSymbol.new COMMA
- when ?* then current_symbol = PascalSymbol.new TIMES
- when ?/ then current_symbol = PascalSymbol.new SLASH
- when ?+ then current_symbol = PascalSymbol.new PLUS
- when ?- then current_symbol = PascalSymbol.new MINUS
- when ?= then current_symbol = PascalSymbol.new EQLSY
- when ?) then current_symbol = PascalSymbol.new RPARENT
- when ?; then current_symbol = PascalSymbol.new SEMICOLON
- else
- Error.error(100, @line, @pos) if @current_char > ?\s
- end
- end
- end
- current_symbol
- end
-
-private
- ##
- # Versucht, in dem gegebenen String ein Schlsselwort zu erkennen.
- # Sollte dabei ein Keyword gefunden werden, so gibt er ein PascalSymbol-Objekt zurck, das
- # das entsprechende Keyword repr
- # einem SymbolIdent-Objekt (abgeleitet von PascalSymbol), das den String 1:1 enth
- # @see symbol
- # @return falls Keyword gefunden, zugeh
- def handle_identifier identifier
- if sym = KEYWORD_SYMBOLS[identifier]
- PascalSymbol.new sym
- else
- SymbolIdent.new identifier
- end
- end
-
- MAXINT = 2**31 - 1
- MAXINT_DIV_10 = MAXINT / 10
- MAXINT_MOD_10 = MAXINT % 10
- ##
- # Versucht, aus dem gegebenen Zeichen und den folgenden eine Zahl zusammenzusetzen.
- # Dabei wird der relativ intuitive Algorithmus benutzt, die endgltige Zahl bei
- # jeder weiteren Ziffer mit 10 zu multiplizieren und diese dann mit der Ziffer zu
- # addieren. Sonderf
- # <BR>
- # Treten dabei kein Punkt oder ein E auf, so gibt diese Methode ein SymbolIntCon-Objekt
- # zurck, ansonsten (reelle Zahl) ein SymbolRealCon-Objekt. Beide Symbole enthalten
- # jeweils die Zahlwerte.
- # <BR>
- # Anmerkung: Diese Funktion ist mit Hilfe der Java/Ruby-API deutlich leichter zu realisieren.
- # Sie wurde dennoch so implementiert, um den Algorithmus zu demonstrieren
- # @see symbol
- # @return SymbolIntcon- oder SymbolRealcon-Objekt, das den Zahlwert enth
- def number
- is_integer = true
- integer_too_long = false
- exponent = 0
- exp_counter = -1
- exp_sign = 1
-
- integer_mantisse = @current_char.digit
-
- while (@next_char.digit? and integer_mantisse < MAXINT_DIV_10) or
- (integer_mantisse == MAXINT_DIV_10 and @next_char.digit <= MAXINT_MOD_10)
- integer_mantisse *= 10
- integer_mantisse += @next_char.digit
- read_next_char
- end
-
- real_mantisse = integer_mantisse
-
- while @next_char.digit?
- integer_too_long = true
- real_mantisse *= 10
- real_mantisse += @next_char.digit
- read_next_char
- end
- if @next_char == ?.
- read_next_char
- is_integer = false
- unless @next_char.digit?
- Error.error 101, @line, @pos
- end
- while @next_char.digit?
- real_mantisse += @next_char.digit * (10 ** exp_counter)
- read_next_char
- exp_counter -= 1
- end
- end
- if @next_char == ?E
- is_integer = false
- read_next_char
- if @next_char == ?-
- exp_sign = -1
- read_next_char
- end
- unless @next_char.digit?
- Error.error 101, @line, @pos
- end
- while @next_char.digit?
- exponent *= 10
- exponent += @next_char.digit
- read_next_char
- end
- end
-
- if is_integer
- if integer_too_long
- Error.error 102, @line, @pos
- end
- SymbolIntcon.new integer_mantisse
- else
- SymbolRealcon.new real_mantisse * (10 ** (exp_sign * exponent))
- end
- end
-
- ##
- # Sorgt fr ein
- # Es werden einfach alle Zeichen bis zu einer schlie
- # und verworfen.
- def comment
- while @current_char != ?}
- forbid_eop
- new_line if @current_char == ?\n
- read_next_char
- end
- end
-
- def new_line
- @line += 1
- @pos = 0
- end
-
- def forbid_eop
- if eop?
- Error.error 103, @line, @pos
- end
- exit
- end
-
- def eop?
- @current_char.nil?
- end
-end
-
-##
-# L
-# Dieses erzeugt sich ein Scanner-Objekt und ruft an diesem kontinuierlich bis zum Dateiende
-# get_symbol auf.
-if $0 == __FILE__
- scan = Scanner.new(File.new(ARGV[0] || 'test.pas'))
- loop do
- c = scan.get_symbol
- puts c
- break if c.typ == TokenConsts::EOP
- end
-end
-# -*- ruby -*-
-
-# Local variables:
-# indent-tabs-mode: nil
-# ruby-indent-level: 4
-# End:
-
-# @@PLEAC@@_NAME
-# @@SKIP@@ Ruby
-
-# @@PLEAC@@_WEB
-# @@SKIP@@ http://www.ruby-lang.org
-
-
-# @@PLEAC@@_1.0
-string = '\n' # two characters, \ and an n
-string = 'Jon \'Maddog\' Orwant' # literal single quotes
-
-string = "\n" # a "newline" character
-string = "Jon \"Maddog\" Orwant" # literal double quotes
-
-string = %q/Jon 'Maddog' Orwant/ # literal single quotes
-
-string = %q[Jon 'Maddog' Orwant] # literal single quotes
-string = %q{Jon 'Maddog' Orwant} # literal single quotes
-string = %q(Jon 'Maddog' Orwant) # literal single quotes
-string = %q<Jon 'Maddog' Orwant> # literal single quotes
-
-a = <<"EOF"
-This is a multiline here document
-terminated by EOF on a line by itself
-EOF
-
-
-# @@PLEAC@@_1.1
-value = string[offset,count]
-value = string[offset..-1]
-
-string[offset,count] = newstring
-string[offset..-1] = newtail
-
-# in Ruby we can also specify intervals by their two offsets
-value = string[offset..offs2]
-string[offset..offs2] = newstring
-
-leading, s1, s2, trailing = data.unpack("A5 x3 A8 A8 A*")
-
-fivers = string.unpack("A5" * (string.length/5))
-
-chars = string.unpack("A1" * string.length)
-
-string = "This is what you have"
-# +012345678901234567890 Indexing forwards (left to right)
-# 109876543210987654321- Indexing backwards (right to left)
-# note that 0 means 10 or 20, etc. above
-
-first = string[0, 1] # "T"
-start = string[5, 2] # "is"
-rest = string[13..-1] # "you have"
-last = string[-1, 1] # "e"
-end_ = string[-4..-1] # "have"
-piece = string[-8, 3] # "you"
-
-string[5, 2] = "wasn't" # change "is" to "wasn't"
-string[-12..-1] = "ondrous" # "This wasn't wondrous"
-string[0, 1] = "" # delete first character
-string[-10..-1] = "" # delete last 10 characters
-
-if string[-10..-1] =~ /pattern/
- puts "Pattern matches in last 10 characters"
-end
-
-string[0, 5].gsub!(/is/, 'at')
-
-a = "make a hat"
-a[0, 1], a[-1, 1] = a[-1, 1], a[0, 1]
-
-a = "To be or not to be"
-b = a.unpack("x6 A6")
-
-b, c = a.unpack("x6 A2 X5 A2")
-puts "#{b}\n#{c}\n"
-
-def cut2fmt(*args)
- template = ''
- lastpos = 1
- for place in args
- template += "A" + (place - lastpos).to_s + " "
- lastpos = place
- end
- template += "A*"
- return template
-end
-
-fmt = cut2fmt(8, 14, 20, 26, 30)
-
-
-# @@PLEAC@@_1.2
-# careful! "b is true" doesn't mean "b != 0" (0 is true in Ruby)
-# thus no problem of "defined" later since only nil is false
-# the following sets to `c' if `b' is nil or false
-a = b || c
-
-# if you need Perl's behaviour (setting to `c' if `b' is 0) the most
-# effective way is to use Numeric#nonzero? (thanks to Dave Thomas!)
-a = b.nonzero? || c
-
-# you will still want to use defined? in order to test
-# for scope existence of a given object
-a = defined?(b) ? b : c
-
-dir = ARGV.shift || "/tmp"
-
-
-# @@PLEAC@@_1.3
-v1, v2 = v2, v1
-
-alpha, beta, production = %w(January March August)
-alpha, beta, production = beta, production, alpha
-
-
-# @@PLEAC@@_1.4
-num = char[0]
-char = num.chr
-
-# Ruby also supports having a char from character constant
-num = ?r
-
-char = sprintf("%c", num)
-printf("Number %d is character %c\n", num, num)
-
-ascii = string.unpack("C*")
-string = ascii.pack("C*")
-
-hal = "HAL"
-ascii = hal.unpack("C*")
-# We can't use Array#each since we can't mutate a Fixnum
-ascii.collect! { |i|
- i + 1 # add one to each ASCII value
-}
-ibm = ascii.pack("C*")
-puts ibm
-
-
-# @@PLEAC@@_1.5
-array = string.split('')
-
-array = string.unpack("C*")
-
-string.scan(/./) { |b|
- # do something with b
-}
-
-string = "an apple a day"
-print "unique chars are: ", string.split('').uniq.sort, "\n"
-
-sum = 0
-for ascval in string.unpack("C*") # or use Array#each for a pure OO style :)
- sum += ascval
-end
-puts "sum is #{sum & 0xffffffff}" # since Ruby will go Bignum if necessary
-
-# @@INCLUDE@@ include/ruby/slowcat.rb
-
-
-# @@PLEAC@@_1.6
-revbytes = string.reverse
-
-revwords = string.split(" ").reverse.join(" ")
-
-revwords = string.split(/(\s+)/).reverse.join
-
-# using the fact that IO is Enumerable, you can directly "select" it
-long_palindromes = File.open("/usr/share/dict/words").
- select { |w| w.chomp!; w.reverse == w && w.length > 5 }
-
-
-# @@PLEAC@@_1.7
-while string.sub!("\t+") { ' ' * ($&.length * 8 - $`.length % 8) }
-end
-
-
-# @@PLEAC@@_1.8
-'You owe #{debt} to me'.gsub(/\#{(\w+)}/) { eval($1) }
-
-rows, cols = 24, 80
-text = %q(I am #{rows} high and #{cols} long)
-text.gsub!(/\#{(\w+)}/) { eval("#{$1}") }
-puts text
-
-'I am 17 years old'.gsub(/\d+/) { 2 * $&.to_i }
-
-
-# @@PLEAC@@_1.9
-e = "bo peep".upcase
-e.downcase!
-e.capitalize!
-
-"thIS is a loNG liNE".gsub!(/\w+/) { $&.capitalize }
-
-
-# @@PLEAC@@_1.10
-"I have #{n+1} guanacos."
-print "I have ", n+1, " guanacos."
-
-
-# @@PLEAC@@_1.11
-var = <<'EOF'.gsub(/^\s+/, '')
- your text
- goes here
-EOF
-
-
-# @@PLEAC@@_1.12
-string = "Folding and splicing is the work of an editor,\n"+
- "not a mere collection of silicon\n"+
- "and\n"+
- "mobile electrons!"
-
-def wrap(str, max_size)
- all = []
- line = ''
- for l in str.split
- if (line+l).length >= max_size
- all.push(line)
- line = ''
- end
- line += line == '' ? l : ' ' + l
- end
- all.push(line).join("\n")
-end
-
-print wrap(string, 20)
-#=> Folding and
-#=> splicing is the
-#=> work of an editor,
-#=> not a mere
-#=> collection of
-#=> silicon and mobile
-#=> electrons!
-
-
-# @@PLEAC@@_1.13
-string = %q(Mom said, "Don't do that.")
-string.gsub(/['"]/) { '\\'+$& }
-string.gsub(/['"]/, '\&\&')
-string.gsub(/[^A-Z]/) { '\\'+$& }
-"is a test!".gsub(/\W/) { '\\'+$& } # no function like quotemeta?
-
-
-# @@PLEAC@@_1.14
-string.strip!
-
-
-# @@PLEAC@@_1.15
-def parse_csv(text)
- new = text.scan(/"([^\"\\]*(?:\\.[^\"\\]*)*)",?|([^,]+),?|,/)
- new << nil if text[-1] == ?,
- new.flatten.compact
-end
-
-line = %q<XYZZY,"","O'Reilly, Inc","Wall, Larry","a \"glug\" bit,",5,"Error, Core Dumped">
-fields = parse_csv(line)
-fields.each_with_index { |v,i|
- print "#{i} : #{v}\n";
-}
-
-
-# @@PLEAC@@_1.16
-# Use the soundex.rb Library from Michael Neumann.
-# http://www.s-direktnet.de/homepages/neumann/rb_prgs/Soundex.rb
-require 'Soundex'
-
-code = Text::Soundex.soundex(string)
-codes = Text::Soundex.soundex(array)
-
-# substitution function for getpwent():
-# returns an array of user entries,
-# each entry contains the username and the full name
-def login_names
- result = []
- File.open("/etc/passwd") { |file|
- file.each_line { |line|
- next if line.match(/^#/)
- cols = line.split(":")
- result.push([cols[0], cols[4]])
- }
- }
- result
-end
-
-puts "Lookup user: "
-user = STDIN.gets
-user.chomp!
-exit unless user
-name_code = Text::Soundex.soundex(user)
-
-splitter = Regexp.new('(\w+)[^,]*\b(\w+)')
-for username, fullname in login_names do
- firstname, lastname = splitter.match(fullname)[1,2]
- if name_code == Text::Soundex.soundex(username)
- || name_code == Text::Soundex.soundex(firstname)
- || name_code == Text::Soundex.soundex(lastname)
- then
- puts "#{username}: #{firstname} #{lastname}"
- end
-end
-
-
-# @@PLEAC@@_1.17
-# @@INCLUDE@@ include/ruby/fixstyle.rb
-
-
-# @@PLEAC@@_1.18
-# @@INCLUDE@@ include/ruby/psgrep.rb
-
-
-# @@PLEAC@@_2.1
-# Matz tells that you can use Integer() for strict checked conversion.
-Integer("abc")
-#=> `Integer': invalid value for Integer: "abc" (ArgumentError)
-Integer("567")
-#=> 567
-
-# You may use Float() for floating point stuff
-Integer("56.7")
-#=> `Integer': invalid value for Integer: "56.7" (ArgumentError)
-Float("56.7")
-#=> 56.7
-
-# You may also use a regexp for that
-if string =~ /^[+-]?\d+$/
- p 'is an integer'
-else
- p 'is not'
-end
-
-if string =~ /^-?(?:\d+(?:\.\d*)?|\.\d+)$/
- p 'is a decimal number'
-else
- p 'is not'
-end
-
-
-# @@PLEAC@@_2.2
-# equal(num1, num2, accuracy) : returns true if num1 and num2 are
-# equal to accuracy number of decimal places
-def equal(i, j, a)
- sprintf("%.#{a}g", i) == sprintf("%.#{a}g", j)
-end
-
-wage = 536 # $5.36/hour
-week = 40 * wage # $214.40
-printf("One week's wage is: \$%.2f\n", week/100.0)
-
-
-# @@PLEAC@@_2.3
-num.round # rounds to integer
-
-a = 0.255
-b = sprintf("%.2f", a)
-print "Unrounded: #{a}\nRounded: #{b}\n"
-printf "Unrounded: #{a}\nRounded: %.2f\n", a
-
-print "number\tint\tfloor\tceil\n"
-a = [ 3.3 , 3.5 , 3.7, -3.3 ]
-for n in a
- printf("% .1f\t% .1f\t% .1f\t% .1f\n", # at least I don't fake my output :)
- n, n.to_i, n.floor, n.ceil)
-end
-
-
-# @@PLEAC@@_2.4
-def dec2bin(n)
- [n].pack("N").unpack("B32")[0].sub(/^0+(?=\d)/, '')
-end
-
-def bin2dec(n)
- [("0"*32+n.to_s)[-32..-1]].pack("B32").unpack("N")[0]
-end
-
-
-# @@PLEAC@@_2.5
-for i in x .. y
- # i is set to every integer from x to y, inclusive
-end
-
-x.step(y,7) { |i|
- # i is set to every integer from x to y, stepsize = 7
-}
-
-print "Infancy is: "
-(0..2).each { |i|
- print i, " "
-}
-print "\n"
-
-
-# @@PLEAC@@_2.6
-# We can add conversion methods to the Integer class,
-# this makes a roman number just a representation for normal numbers.
-class Integer
-
- @@romanlist = [["M", 1000],
- ["CM", 900],
- ["D", 500],
- ["CD", 400],
- ["C", 100],
- ["XC", 90],
- ["L", 50],
- ["XL", 40],
- ["X", 10],
- ["IX", 9],
- ["V", 5],
- ["IV", 4],
- ["I", 1]]
-
- def to_roman
- remains = self
- roman = ""
- for sym, num in @@romanlist
- while remains >= num
- remains -= num
- roman << sym
- end
- end
- roman
- end
-
- def Integer.from_roman(roman)
- ustr = roman.upcase
- sum = 0
- for entry in @@romanlist
- sym, num = entry[0], entry[1]
- while sym == ustr[0, sym.length]
- sum += num
- ustr.slice!(0, sym.length)
- end
- end
- sum
- end
-
-end
-
-
-roman_fifteen = 15.to_roman
-puts "Roman for fifteen is #{roman_fifteen}"
-i = Integer.from_roman(roman_fifteen)
-puts "Converted back, #{roman_fifteen} is #{i}"
-
-# check
-for i in (1..3900)
- r = i.to_roman
- j = Integer.from_roman(r)
- if i != j
- puts "error: #{i} : #{r} - #{j}"
- end
-end
-
-
-# @@PLEAC@@_2.7
-random = rand(y-x+1)+x
-
-chars = ["A".."Z","a".."z","0".."9"].collect { |r| r.to_a }.join + %q(!@$%^&*)
-password = (1..8).collect { chars[rand(chars.size)] }.pack("C*")
-
-
-# @@PLEAC@@_2.8
-srand # uses a combination of the time, the process id, and a sequence number
-srand(val) # for repeatable behaviour
-
-
-# @@PLEAC@@_2.9
-# from the randomr lib:
-# http://raa.ruby-lang.org/project/randomr/
-----> http://raa.ruby-lang.org/project/randomr/
-
-require 'random/mersenne_twister'
-mers = Random::MersenneTwister.new 123456789
-puts mers.rand(0) # 0.550321932544541
-puts mers.rand(10) # 2
-
-# using online sources of random data via the realrand package:
-# http://raa.ruby-lang.org/project/realrand/
-# **Note**
-# The following online services are used in this package:
-# http://www.random.org - source: atmospheric noise
-# http://www.fourmilab.ch/hotbits - source: radioactive decay timings
-# http://random.hd.org - source: entropy from local and network noise
-# Please visit the sites and respect the rules of each service.
-
-require 'random/online'
-
-generator1 = Random::RandomOrg.new
-puts generator1.randbyte(5).join(",")
-puts generator1.randnum(10, 1, 6).join(",") # Roll dice 10 times.
-
-generator2 = Random::FourmiLab.new
-puts generator2.randbyte(5).join(",")
-# randnum is not supported.
-
-generator3 = Random::EntropyPool.new
-puts generator3.randbyte(5).join(",")
-# randnum is not supported.
-
-
-# @@PLEAC@@_2.10
-def gaussian_rand
- begin
- u1 = 2 * rand() - 1
- u2 = 2 * rand() - 1
- w = u1*u1 + u2*u2
- end while (w >= 1)
- w = Math.sqrt((-2*Math.log(w))/w)
- [ u2*w, u1*w ]
-end
-
-mean = 25
-sdev = 2
-salary = gaussian_rand[0] * sdev + mean
-printf("You have been hired at \$%.2f\n", salary)
-
-
-# @@PLEAC@@_2.11
-def deg2rad(d)
- (d/180.0)*Math::PI
-end
-
-def rad2deg(r)
- (r/Math::PI)*180
-end
-
-
-# @@PLEAC@@_2.12
-sin_val = Math.sin(angle)
-cos_val = Math.cos(angle)
-tan_val = Math.tan(angle)
-
-# AFAIK Ruby's Math module doesn't provide acos/asin
-# While we're at it, let's also define missing hyperbolic functions
-module Math
- def Math.asin(x)
- atan2(x, sqrt(1 - x**2))
- end
- def Math.acos(x)
- atan2(sqrt(1 - x**2), x)
- end
- def Math.atan(x)
- atan2(x, 1)
- end
- def Math.sinh(x)
- (exp(x) - exp(-x)) / 2
- end
- def Math.cosh(x)
- (exp(x) + exp(-x)) / 2
- end
- def Math.tanh(x)
- sinh(x) / cosh(x)
- end
-end
-
-# The support for Complex numbers is not built-in
-y = Math.acos(3.7)
-#=> in `sqrt': square root for negative number (ArgumentError)
-
-# There is an implementation of Complex numbers in 'complex.rb' in current
-# Ruby distro, but it doesn't support atan2 with complex args, so it doesn't
-# solve this problem.
-
-
-# @@PLEAC@@_2.13
-log_e = Math.log(val)
-log_10 = Math.log10(val)
-
-def log_base(base, val)
- Math.log(val)/Math.log(base)
-end
-
-answer = log_base(10, 10_000)
-puts "log10(10,000) = #{answer}"
-
-
-# @@PLEAC@@_2.14
-require 'matrix.rb'
-
-a = Matrix[[3, 2, 3], [5, 9, 8]]
-b = Matrix[[4, 7], [9, 3], [8, 1]]
-c = a * b
-
-a.row_size
-a.column_size
-
-c.det
-a.transpose
-
-
-# @@PLEAC@@_2.15
-require 'complex.rb'
-require 'rational.rb'
-
-a = Complex(3, 5) # 3 + 5i
-b = Complex(2, -2) # 2 - 2i
-puts "c = #{a*b}"
-
-c = a * b
-d = 3 + 4*Complex::I
-
-printf "sqrt(#{d}) = %s\n", Math.sqrt(d)
-
-
-# @@PLEAC@@_2.16
-number = hexadecimal.hex
-number = octal.oct
-
-print "Gimme a number in decimal, octal, or hex: "
-num = gets.chomp
-exit unless defined?(num)
-num = num.oct if num =~ /^0/ # does both oct and hex
-printf "%d %x %o\n", num, num, num
-
-print "Enter file permission in octal: "
-permissions = gets.chomp
-raise "Exiting ...\n" unless defined?(permissions)
-puts "The decimal value is #{permissions.oct}"
-
-
-# @@PLEAC@@_2.17
-def commify(n)
- n.to_s =~ /([^\.]*)(\..*)?/
- int, dec = $1.reverse, $2 ? $2 : ""
- while int.gsub!(/(,|\.|^)(\d{3})(\d)/, '\1\2,\3')
- end
- int.reverse + dec
-end
-
-
-# @@PLEAC@@_2.18
-printf "It took %d hour%s\n", time, time == 1 ? "" : "s"
-
-# dunno if an equivalent to Lingua::EN::Inflect exists...
-
-
-# @@PLEAC@@_2.19
-#-----------------------------
-#!/usr/bin/ruby
-# bigfact - calculating prime factors
-def factorize(orig)
- factors = {}
- factors.default = 0 # return 0 instead nil if key not found in hash
- n = orig
- i = 2
- sqi = 4 # square of i
- while sqi <= n do
- while n.modulo(i) == 0 do
- n /= i
- factors[i] += 1
- # puts "Found factor #{i}"
- end
- # we take advantage of the fact that (i +1)**2 = i**2 + 2*i +1
- sqi += 2 * i + 1
- i += 1
- end
-
- if (n != 1) && (n != orig)
- factors[n] += 1
- end
- factors
-end
-
-def printfactorhash(orig, factorcount)
- print format("%-10d ", orig)
- if factorcount.length == 0
- print "PRIME"
- else
- # sorts after number, because the hash keys are numbers
- factorcount.sort.each { |factor,exponent|
- print factor
- if exponent > 1
- print "**", exponent
- end
- print " "
- }
- end
- puts
-end
-
-for arg in ARGV
- n = arg.to_i
- mfactors = factorize(n)
- printfactorhash(n, mfactors)
-end
-#-----------------------------
-
-
-# @@PLEAC@@_3.0
-puts Time.now
-
-print "Today is day ", Time.now.yday, " of the current year.\n"
-print "Today is day ", Time.now.day, " of the current month.\n"
-
-
-# @@PLEAC@@_3.1
-day, month, year = Time.now.day, Time.now.month, Time.now.year
-# or
-day, month, year = Time.now.to_a[3..5]
-
-tl = Time.now.localtime
-printf("The current date is %04d %02d %02d\n", tl.year, tl.month, tl.day)
-
-Time.now.localtime.strftime("%Y-%m-%d")
-
-
-# @@PLEAC@@_3.2
-Time.local(year, month, day, hour, minute, second).tv_sec
-Time.gm(year, month, day, hour, minute, second).tv_sec
-
-
-# @@PLEAC@@_3.3
-sec, min, hour, day, month, year, wday, yday, isdst, zone = Time.at(epoch_secs).to_a
-
-
-# @@PLEAC@@_3.4
-when_ = now + difference # now -> Time ; difference -> Numeric (delta in seconds)
-then_ = now - difference
-
-
-# @@PLEAC@@_3.5
-bree = 361535725
-nat = 96201950
-
-difference = bree - nat
-puts "There were #{difference} seconds between Nat and Bree"
-
-seconds = difference % 60
-difference = (difference - seconds) / 60
-minutes = difference % 60
-difference = (difference - minutes) / 60
-hours = difference % 24
-difference = (difference - hours) / 24
-days = difference % 7
-weeks = (difference - days) / 7
-
-puts "(#{weeks} weeks, #{days} days, #{hours}:#{minutes}:#{seconds})"
-
-
-# @@PLEAC@@_3.6
-monthday, weekday, yearday = date.mday, date.wday, date.yday
-
-# AFAIK the week number is not just a division since week boundaries are on sundays
-weeknum = d.strftime("%U").to_i + 1
-
-year = 1981
-month = "jun" # or `6' if you want to emulate a broken language
-day = 16
-t = Time.mktime(year, month, day)
-print "#{month}/#{day}/#{year} was a ", t.strftime("%A"), "\n"
-
-
-# @@PLEAC@@_3.7
-yyyy, mm, dd = $1, $2, $3 if "1998-06-25" =~ /(\d+)-(\d+)-(\d+)/
-
-epoch_seconds = Time.mktime(yyyy, mm, dd).tv_sec
-
-# dunno an equivalent to Date::Manip#ParseDate
-
-
-# @@PLEAC@@_3.8
-string = Time.at(epoch_secs)
-Time.at(1234567890).gmtime # gives: Fri Feb 13 23:31:30 UTC 2009
-
-time = Time.mktime(1973, "jan", 18, 3, 45, 50)
-print "In localtime it gives: ", time.localtime, "\n"
-
-
-# @@PLEAC@@_3.9
-# Ruby provides micro-seconds in Time object
-Time.now.usec
-
-# Ruby gives the seconds in floating format when substracting two Time objects
-before = Time.now
-line = gets
-elapsed = Time.now - before
-puts "You took #{elapsed} seconds."
-
-# On my Celeron-400 with Linux-2.2.19-14mdk, average for three execs are:
-# This Ruby version: average 0.00321 sec
-# Cookbook's Perl version: average 0.00981 sec
-size = 500
-number_of_times = 100
-total_time = 0
-number_of_times.times {
- # populate array
- array = []
- size.times { array << rand }
- # sort it
- begin_ = Time.now
- array.sort!
- time = Time.now - begin_
- total_time += time
-}
-printf "On average, sorting %d random numbers takes %.5f seconds\n",
- size, (total_time/Float(number_of_times))
-
-
-# @@PLEAC@@_3.10
-sleep(0.005) # Ruby is definitely not as broken as Perl :)
-# (may be interrupted by sending the process a SIGALRM)
-
-
-# @@PLEAC@@_3.11
-#!/usr/bin/ruby -w
-# hopdelta - feed mail header, produce lines
-# showing delay at each hop.
-require 'time'
-class MailHopDelta
-
- def initialize(mail)
- @head = mail.gsub(/\n\s+/,' ')
- @topline = %w-Sender Recipient Time Delta-
- @start_from = mail.match(/^From.*\@([^\s>]*)/)[1]
- @date = Time.parse(mail.match(/^Date:\s+(.*)/)[1])
- end
-
- def out(line)
- "%-20.20s %-20.20s %-20.20s %s" % line
- end
-
- def hop_date(day)
- day.strftime("%I:%M:%S %Y/%m/%d")
- end
-
- def puts_hops
- puts out(@topline)
- puts out(['Start', @start_from, hop_date(@date),''])
- @head.split(/\n/).reverse.grep(/^Received:/).each do |hop|
- hop.gsub!(/\bon (.*?) (id.*)/,'; \1')
- whence = hop.match(/;\s+(.*)$/)[1]
- unless whence
- warn "Bad received line: #{hop}"
- next
- end
- from = $+ if hop =~ /from\s+(\S+)|\((.*?)\)/
- by = $1 if hop =~ /by\s+(\S+\.\S+)/
- next unless now = Time.parse(whence).localtime
- delta = now - @date
- puts out([from, by, hop_date(now), hop_time(delta)])
- @date = now
- end
- end
-
- def hop_time(secs)
- sign = secs < 0 ? -1 : 1
- days, secs = secs.abs.divmod(60 * 60 * 24)
- hours,secs = secs.abs.divmod(60 * 60)
- mins, secs = secs.abs.divmod(60)
- rtn = "%3ds" % [secs * sign]
- rtn << "%3dm" % [mins * sign] if mins != 0
- rtn << "%3dh" % [hours * sign] if hours != 0
- rtn << "%3dd" % [days * sign] if days != 0
- rtn
- end
-end
-
-$/ = ""
-mail = MailHopDelta.new(ARGF.gets).puts_hops
-
-
-# @@PLEAC@@_4.0
-single_level = [ "this", "that", "the", "other" ]
-
-# Ruby directly supports nested arrays
-double_level = [ "this", "that", [ "the", "other" ] ]
-still_single_level = [ "this", "that", [ "the", "other" ] ].flatten
-
-
-# @@PLEAC@@_4.1
-a = [ "quick", "brown", "fox" ]
-a = %w(Why are you teasing me?)
-
-lines = <<"END_OF_HERE_DOC".gsub(/^\s*(.+)/, '\1')
- The boy stood on the burning deck,
- It was as hot as glass.
-END_OF_HERE_DOC
-
-bigarray = IO.readlines("mydatafile").collect { |l| l.chomp }
-
-name = "Gandalf"
-banner = %Q(Speak, #{name}, and welcome!)
-
-host_info = `host #{his_host}`
-
-%x(ps #{$$})
-
-banner = 'Costs only $4.95'.split(' ')
-
-rax = %w! ( ) < > { } [ ] !
-
-
-# @@PLEAC@@_4.2
-def commify_series(a)
- a.size == 0 ? '' :
- a.size == 1 ? a[0] :
- a.size == 2 ? a.join(' and ') :
- a[0..-2].join(', ') + ', and ' + a[-1]
-end
-
-array = [ "red", "yellow", "green" ]
-
-print "I have ", array, " marbles\n"
-# -> I have redyellowgreen marbles
-
-# But unlike Perl:
-print "I have #{array} marbles\n"
-# -> I have redyellowgreen marbles
-# So, needs:
-print "I have #{array.join(' ')} marbles\n"
-# -> I have red yellow green marbles
-
-def commify_series(a)
- sepchar = a.select { |p| p =~ /,/ } != [] ? '; ' : ', '
- a.size == 0 ? '' :
- a.size == 1 ? a[0] :
- a.size == 2 ? a.join(' and ') :
- a[0..-2].join(sepchar) + sepchar + 'and ' + a[-1]
-end
-
-
-# @@PLEAC@@_4.3
-# (note: AFAIK Ruby doesn't allow gory change of Array length)
-# grow the array by assigning nil to past the end of array
-ary[new_size-1] = nil
-# shrink the array by slicing it down
-ary.slice!(new_size..-1)
-# init the array with given size
-Array.new(number_of_elems)
-# assign to an element past the original end enlarges the array
-ary[index_new_last_elem] = value
-
-def what_about_that_array(a)
- print "The array now has ", a.size, " elements.\n"
- # Index of last element is not really interesting in Ruby
- print "Element #3 is `#{a[3]}'.\n"
-end
-people = %w(Crosby Stills Nash Young)
-what_about_that_array(people)
-
-
-# @@PLEAC@@_4.4
-# OO style
-bad_users.each { |user|
- complain(user)
-}
-# or, functional style
-for user in bad_users
- complain(user)
-end
-
-for var in ENV.keys.sort
- puts "#{var}=#{ENV[var]}"
-end
-
-for user in all_users
- disk_space = get_usage(user)
- if (disk_space > MAX_QUOTA)
- complain(user)
- end
-end
-
-for l in IO.popen("who").readlines
- print l if l =~ /^gc/
-end
-
-# we can mimic the obfuscated Perl way
-while fh.gets # $_ is set to the line just read
- chomp # $_ has a trailing \n removed, if it had one
- split.each { |w| # $_ is split on whitespace
- # but $_ is not set to each chunk as in Perl
- print w.reverse
- }
-end
-# ...or use a cleaner way
-for l in fh.readlines
- l.chomp.split.each { |w| print w.reverse }
-end
-
-# same drawback as in problem 1.4, we can't mutate a Numeric...
-array.collect! { |v| v - 1 }
-
-a = [ .5, 3 ]; b = [ 0, 1 ]
-for ary in [ a, b ]
- ary.collect! { |v| v * 7 }
-end
-puts "#{a.join(' ')} #{b.join(' ')}"
-
-# we can mutate Strings, cool; we need a trick for the scalar
-for ary in [ [ scalar ], array, hash.values ]
- ary.each { |v| v.strip! } # String#strip rules :)
-end
-
-
-# @@PLEAC@@_4.5
-# not relevant in Ruby since we have always references
-for item in array
- # do somethingh with item
-end
-
-
-# @@PLEAC@@_4.6
-unique = list.uniq
-
-# generate a list of users logged in, removing duplicates
-users = `who`.collect { |l| l =~ /(\w+)/; $1 }.sort.uniq
-puts("users logged in: #{commify_series(users)}") # see 4.2 for commify_series
-
-
-# @@PLEAC@@_4.7
-a - b
-# [ 1, 1, 2, 2, 3, 3, 3, 4, 5 ] - [ 1, 2, 4 ] -> [3, 5]
-
-
-# @@PLEAC@@_4.8
-union = a | b
-intersection = a & b
-difference = a - b
-
-
-# @@PLEAC@@_4.9
-array1.concat(array2)
-# if you will assign to another object, better use:
-new_ary = array1 + array2
-
-members = [ "Time", "Flies" ]
-initiates = [ "An", "Arrow" ]
-members += initiates
-
-members = [ "Time", "Flies" ]
-initiates = [ "An", "Arrow" ]
-members[2,0] = [ "Like", initiates ].flatten
-
-members[0] = "Fruit"
-members[3,2] = "A", "Banana"
-
-
-# @@PLEAC@@_4.10
-reversed = ary.reverse
-
-ary.reverse_each { |e|
- # do something with e
-}
-
-descending = ary.sort.reverse
-descending = ary.sort { |a,b| b <=> a }
-
-
-# @@PLEAC@@_4.11
-# remove n elements from front of ary (shift n)
-front = ary.slice!(0, n)
-
-# remove n elements from the end of ary (pop n)
-end_ = ary.slice!(-n .. -1)
-
-# let's extend the Array class, to make that useful
-class Array
- def shift2()
- slice!(0 .. 1) # more symetric with pop2...
- end
- def pop2()
- slice!(-2 .. -1)
- end
-end
-
-friends = %w(Peter Paul Mary Jim Tim)
-this, that = friends.shift2
-
-beverages = %w(Dew Jolt Cola Sprite Fresca)
-pair = beverages.pop2
-
-
-# @@PLEAC@@_4.12
-# use Enumerable#detect (or the synonym Enumerable#find)
-highest_eng = employees.detect { |emp| emp.category == 'engineer' }
-
-
-# @@PLEAC@@_4.13
-# use Enumerable#select (or the synonym Enumerable#find_all)
-bigs = nums.select { |i| i > 1_000_000 }
-pigs = users.keys.select { |k| users[k] > 1e7 }
-
-matching = `who`.select { |u| u =~ /^gnat / }
-
-engineers = employees.select { |e| e.position == 'Engineer' }
-
-secondary_assistance = applicants.select { |a|
- a.income >= 26_000 && a.income < 30_000
-}
-
-
-# @@PLEAC@@_4.14
-# normally you would have an array of Numeric (Float or
-# Fixnum or Bignum), so you would use:
-sorted = unsorted.sort
-# if you have strings representing Integers or Floats
-# you may specify another sort method:
-sorted = unsorted.sort { |a,b| a.to_f <=> b.to_f }
-
-# let's use the list of my own PID's
-`ps ux`.split("\n")[1..-1].
- select { |i| i =~ /^#{ENV['USER']}/ }.
- collect { |i| i.split[1] }.
- sort { |a,b| a.to_i <=> b.to_i }.each { |i| puts i }
-puts "Select a process ID to kill:"
-pid = gets.chomp
-raise "Exiting ... \n" unless pid && pid =~ /^\d+$/
-Process.kill('TERM', pid.to_i)
-sleep 2
-Process.kill('KILL', pid.to_i)
-
-descending = unsorted.sort { |a,b| b.to_f <=> a.to_f }
-
-
-# @@PLEAC@@_4.15
-ordered = unordered.sort { |a,b| compare(a,b) }
-
-precomputed = unordered.collect { |e| [compute, e] }
-ordered_precomputed = precomputed.sort { |a,b| a[0] <=> b[0] }
-ordered = ordered_precomputed.collect { |e| e[1] }
-
-ordered = unordered.collect { |e| [compute, e] }.
- sort { |a,b| a[0] <=> b[0] }.
- collect { |e| e[1] }
-
-for employee in employees.sort { |a,b| a.name <=> b.name }
- print employee.name, " earns \$ ", employee.salary, "\n"
-end
-
-# Beware! `0' is true in Ruby.
-# For chaining comparisons, you may use Numeric#nonzero?, which
-# returns num if num is not zero, nil otherwise
-sorted = employees.sort { |a,b| (a.name <=> b.name).nonzero? || b.age <=> a.age }
-
-users = []
-# getpwent is not wrapped in Ruby... let's fallback
-IO.readlines('/etc/passwd').each { |u| users << u.split(':') }
-users.sort! { |a,b| a[0] <=> b[0] }
-for user in users
- puts user[0]
-end
-
-sorted = names.sort { |a,b| a[1, 1] <=> b[1, 1] }
-sorted = strings.sort { |a,b| a.length <=> b.length }
-
-# let's show only the compact version
-ordered = strings.collect { |e| [e.length, e] }.
- sort { |a,b| a[0] <=> b[0] }.
- collect { |e| e[1] }
-
-ordered = strings.collect { |e| [/\d+/.match(e)[0].to_i, e] }.
- sort { |a,b| a[0] <=> b[0] }.
- collect { |e| e[1] }
-
-print `cat /etc/passwd`.collect { |e| [e, e.split(':').indexes(3,2,0)].flatten }.
- sort { |a,b| (a[1] <=> b[1]).nonzero? || (a[2] <=> b[2]).nonzero? || a[3] <=> b[3] }.
- collect { |e| e[0] }
-
-
-# @@PLEAC@@_4.16
-circular.unshift(circular.pop) # the last shall be first
-circular.push(circular.shift) # and vice versa
-
-def grab_and_rotate(l)
- l.push(ret = l.shift)
- ret
-end
-
-processes = [1, 2, 3, 4, 5]
-while (1)
- process = grab_and_rotate(processes)
- puts "Handling process #{process}"
- sleep 1
-end
-
-
-# @@PLEAC@@_4.17
-def fisher_yates_shuffle(a)
- (a.size-1).downto(1) { |i|
- j = rand(i+1)
- a[i], a[j] = a[j], a[i] if i != j
- }
-end
-
-def naive_shuffle(a)
- for i in 0...a.size
- j = rand(a.size)
- a[i], a[j] = a[j], a[i]
- end
-end
-
-
-# @@PLEAC@@_4.18
-#!/usr/bin/env ruby
-# example 4-2 words
-# words - gather lines, present in colums
-
-# class to encapsulate the word formatting from the input
-class WordFormatter
- def initialize(cols)
- @cols = cols
- end
-
- # helper to return the length of the longest word in the wordlist
- def maxlen(wordlist)
- max = 1
- for word in wordlist
- if word.length > max
- max = word.length
- end
- end
- max
- end
-
- # process the wordlist and print it formmated into columns
- def output(wordlist)
- collen = maxlen(wordlist) + 1
- columns = @cols / collen
- columns = 1 if columns == 0
- rows = (wordlist.length + columns - 1) / columns
- # now process each item, picking out proper piece for this position
- 0.upto(rows * columns - 1) { |item|
- target = (item % columns) * rows + (item / columns)
- eol = ((item+1) % columns == 0)
- piece = wordlist[target] || ""
- piece = piece.ljust(collen) unless eol
- print piece
- puts if eol
- }
- # no need to finish it up, because eol is always true for the last element
- end
-end
-
-# get nr of chars that fit in window or console, see PLEAC 15.4
-# not portable -- linux only (?)
-def getWinCharWidth()
- buf = "\0" * 8
- $stdout.ioctl(0x5413, buf)
- ws_row, ws_col, ws_xpixel, ws_ypixel = buf.unpack("$4")
- ws_col || 80
-rescue
- 80
-end
-
-# main program
-cols = getWinCharWidth()
-formatter = WordFormatter.new(cols)
-words = readlines()
-words.collect! { |line|
- line.chomp
-}
-formatter.output(words)
-
-
-# @@PLEAC@@_4.19
-# In ruby, Fixnum's are automatically converted to Bignum's when
-# needed, so there is no need for an extra module
-def factorial(n)
- s = 1
- while n > 0
- s *= n
- n -= 1
- end
- s
-end
-
-puts factorial(500)
-
-#---------------------------------------------------------
-# Example 4-3. tsc-permute
-# tsc_permute: permute each word of input
-def permute(items, perms)
- unless items.length > 0
- puts perms.join(" ")
- else
- for i in items
- newitems = items.dup
- newperms = perms.dup
- newperms.unshift(newitems.delete(i))
- permute(newitems, newperms)
- end
- end
-end
-# In ruby the main program must be after all definitions it is using
-permute(ARGV, [])
-
-#---------------------------------------------------------
-# mjd_permute: permute each word of input
-
-def factorial(n)
- s = 1
- while n > 0
- s *= n
- n -= 1
- end
- s
-end
-
-# we use a class with a class variable store the private cache
-# for the results of the factorial function.
-class Factorial
- @@fact = [ 1 ]
- def Factorial.compute(n)
- if @@fact[n]
- @@fact[n]
- else
- @@fact[n] = n * Factorial.compute(n - 1)
- end
- end
-end
-
-#---------------------------------------------------------
-# Example 4-4- mjd-permute
-# n2pat(n, len): produce the N-th pattern of length len
-
-# We must use a lower case letter as parameter N, otherwise it is
-# handled as constant Length is the length of the resulting
-# array, not the index of the last element (length -1) like in
-# the perl example.
-def n2pat(n, length)
- pat = []
- i = 1
- while i <= length
- pat.push(n % i)
- n /= i
- i += 1
- end
- pat
-end
-
-# pat2perm(pat): turn pattern returned by n2pat() into
-# permutation of integers.
-def pat2perm(pat)
- source = (0 .. pat.length - 1).to_a
- perm = []
- perm.push(source.slice!(pat.pop)) while pat.length > 0
- perm
-end
-
-def n2perm(n, len)
- pat2perm(n2pat(n,len))
-end
-
-# In ruby the main program must be after all definitions
-while gets
- data = split
- # the perl solution has used $#data, which is length-1
- num_permutations = Factorial.compute(data.length())
- 0.upto(num_permutations - 1) do |i|
- # in ruby we can not use an array as selector for an array
- # but by exchanging the two arrays, we can use the collect method
- # which returns an array with the result of all block invocations
- permutation = n2perm(i, data.length).collect {
- |j| data[j]
- }
- puts permutation.join(" ")
- end
-end
-
-
-# @@PLEAC@@_5.0
-age = { "Nat", 24,
- "Jules", 25,
- "Josh", 17 }
-
-age["Nat"] = 24
-age["Jules"] = 25
-age["Josh"] = 17
-
-food_color = {
- "Apple" => "red",
- "Banana" => "yellow",
- "Lemon" => "yellow",
- "Carrot" => "orange"
- }
-
-# In Ruby, you cannot avoid the double or simple quoting
-# while manipulatin hashes
-
-
-# @@PLEAC@@_5.1
-hash[key] = value
-
-food_color["Raspberry"] = "pink"
-puts "Known foods:", food_color.keys
-
-
-# @@PLEAC@@_5.2
-# does hash have a value for key ?
-if (hash.has_key?(key))
- # it exists
-else
- # it doesn't
-end
-
-[ "Banana", "Martini" ].each { |name|
- print name, " is a ", food_color.has_key?(name) ? "food" : "drink", "\n"
-}
-
-age = {}
-age['Toddler'] = 3
-age['Unborn'] = 0
-age['Phantasm'] = nil
-
-for thing in ['Toddler', 'Unborn', 'Phantasm', 'Relic']
- print "#{thing}: "
- print "Has-key " if age.has_key?(thing)
- print "True " if age[thing]
- print "Nonzero " if age[thing] && age[thing].nonzero?
- print "\n"
-end
-
-#=>
-# Toddler: Has-key True Nonzero
-# Unborn: Has-key True
-# Phantasm: Has-key
-# Relic:
-
-# You use Hash#has_key? when you use Perl's exists -> it checks
-# for existence of a key in a hash.
-# All Numeric are "True" in ruby, so the test doesn't have the
-# same semantics as in Perl; you would use Numeric#nonzero? to
-# achieve the same semantics (false if 0, true otherwise).
-
-
-# @@PLEAC@@_5.3
-food_color.delete("Banana")
-
-
-# @@PLEAC@@_5.4
-hash.each { |key, value|
- # do something with key and value
-}
-
-hash.each_key { |key|
- # do something with key
-}
-
-food_color.each { |food, color|
- puts "#{food} is #{color}"
-}
-
-food_color.each_key { |food|
- puts "#{food} is #{food_color[food]}"
-}
-
-# IMO this demonstrates that OO style is by far more readable
-food_color.keys.sort.each { |food|
- puts "#{food} is #{food_color[food]}."
-}
-
-#-----------------------------
-#!/usr/bin/ruby
-# countfrom - count number of messages from each sender
-
-# Default value is 0
-from = Hash.new(0)
-while gets
- /^From: (.*)/ and from[$1] += 1
-end
-
-# More useful to sort by number of received mail by person
-from.sort {|a,b| b[1]<=>a[1]}.each { |v|
- puts "#{v[1]}: #{v[0]}"
-}
-#-----------------------------
-
-
-# @@PLEAC@@_5.5
-# You may use the built-in 'inspect' method this way:
-p hash
-
-# Or do it the Cookbook way:
-hash.each { |k,v| puts "#{k} => #{v}" }
-
-# Sorted by keys
-hash.sort.each { |e| puts "#{e[0]} => #{e[1]}" }
-# Sorted by values
-hash.sort{|a,b| a[1]<=>b[1]}.each { |e| puts "#{e[0]} => #{e[1]}" }
-
-
-# @@PLEAC@@_5.7
-ttys = Hash.new
-for i in `who`
- user, tty = i.split
- (ttys[user] ||= []) << tty # see problems_ruby for more infos
-end
-ttys.keys.sort.each { |k|
- puts "#{k}: #{commify_series(ttys[k])}" # from 4.2
-}
-
-
-# @@PLEAC@@_5.8
-surname = { "Mickey" => "Mantle", "Babe" => "Ruth" }
-puts surname.index("Mantle")
-
-# If you really needed to 'invert' the whole hash, use Hash#invert
-
-#-----------------------------
-#!/usr/bin/ruby -w
-# foodfind - find match for food or color
-
-given = ARGV.shift or raise "usage: foodfind food_or_color"
-
-color = {
- "Apple" => "red",
- "Banana" => "yellow",
- "Lemon" => "yellow",
- "Carrot" => "orange",
-}
-
-if (color.has_key?(given))
- puts "#{given} is a food with color #{color[given]}."
-end
-if (color.has_value?(given))
- puts "#{color.index(given)} is a food with color #{given}."
-end
-#-----------------------------
-
-
-# @@PLEAC@@_5.9
-# Sorted by keys (Hash#sort gives an Array of pairs made of each key,value)
-food_color.sort.each { |f|
- puts "#{f[0]} is #{f[1]}."
-}
-
-# Sorted by values
-food_color.sort { |a,b| a[1] <=> b[1] }.each { |f|
- puts "#{f[0]} is #{f[1]}."
-}
-
-# Sorted by length of values
-food_color.sort { |a,b| a[1].length <=> b[1].length }.each { |f|
- puts "#{f[0]} is #{f[1]}."
-}
-
-
-# @@PLEAC@@_5.10
-merged = a.clone.update(b) # because Hash#update changes object in place
-
-drink_color = { "Galliano" => "yellow", "Mai Tai" => "blue" }
-ingested_color = drink_color.clone.update(food_color)
-
-substance_color = {}
-for i in [ food_color, drink_color ]
- i.each_key { |k|
- if substance_color.has_key?(k)
- puts "Warning: #{k} seen twice. Using the first definition."
- next
- end
- substance_color[k] = 1
- }
-end
-
-
-# @@PLEAC@@_5.11
-common = hash1.keys & hash2.keys
-
-this_not_that = hash1.keys - hash2.keys
-
-
-# @@PLEAC@@_5.12
-# no problem here, Ruby handles any kind of object for key-ing
-# (it takes Object#hash, which defaults to Object#id)
-
-
-# @@PLEAC@@_5.13
-# AFAIK, not possible in Ruby
-
-
-# @@PLEAC@@_5.14
-# Be careful, the following is possible only because Fixnum objects are
-# special (documentation says: there is effectively only one Fixnum object
-# instance for any given integer value).
-count = Hash.new(0)
-array.each { |e|
- count[e] += 1
-}
-
-
-# @@PLEAC@@_5.15
-father = {
- "Cain" , "Adam",
- "Abel" , "Adam",
- "Seth" , "Adam",
- "Enoch" , "Cain",
- "Irad" , "Enoch",
- "Mehujael" , "Irad",
- "Methusael" , "Mehujael",
- "Lamech" , "Methusael",
- "Jabal" , "Lamech",
- "Jubal" , "Lamech",
- "Tubalcain" , "Lamech",
- "Enos" , "Seth",
-}
-
-while gets
- chomp
- begin
- print $_, " "
- end while $_ = father[$_]
- puts
-end
-
-children = {}
-father.each { |k,v|
- (children[v] ||= []) << k
-}
-while gets
- chomp
- puts "#{$_} begat #{(children[$_] || ['Nobody']).join(', ')}.\n"
-end
-
-includes = {}
-files.each { |f|
- begin
- for l in IO.readlines(f)
- next unless l =~ /^\s*#\s*include\s*<([^>]+)>/
- (includes[$1] ||= []) << f
- end
- rescue SystemCallError
- $stderr.puts "#$! (skipping)"
- end
-}
-
-include_free = includes.values.flatten.uniq - includes.keys
-
-
-# @@PLEAC@@_5.16
-# dutree - print sorted intented rendition of du output
-#% dutree
-#% dutree /usr
-#% dutree -a
-#% dutree -a /bin
-
-# The DuNode class collects all information about a directory,
-# and provides some convenience methods
-class DuNode
-
- attr_reader :name
- attr_accessor :size
- attr_accessor :kids
-
- def initialize(name)
- @name = name
- @kids = []
- @size = 0
- end
-
- # support for sorting nodes with side
- def size_compare(node2)
- @size <=> node2.size
- end
-
- def basename
- @name.sub(/.*\//, "")
- end
-
- #returns substring before last "/", nil if not there
- def parent
- p = @name.sub(/\/[^\/]+$/,"")
- if p == @name
- nil
- else
- p
- end
- end
-
-end
-
-# The DuTree does the acdtual work of
-# getting the input, parsing it, builging up a tree
-# and format it for output
-class Dutree
-
- attr_reader :topdir
-
- def initialize
- @nodes = Hash.new
- @dirsizes = Hash.new(0)
- @kids = Hash.new([])
- end
-
- # get a node by name, create it if it does not exist yet
- def get_create_node(name)
- if @nodes.has_key?(name)
- @nodes[name]
- else
- node = DuNode.new(name)
- @nodes[name] = node
- node
- end
- end
-
- # run du, read in input, save sizes and kids
- # stores last directory read in instance variable topdir
- def input(arguments)
- name = ""
- cmd = "du " + arguments.join(" ")
- IO.popen(cmd) { |pipe|
- pipe.each { |line|
- size, name = line.chomp.split(/\s+/, 2)
- node = get_create_node(name)
- node.size = size.to_i
- @nodes[name] = node
- parent = node.parent
- if parent
- get_create_node(parent).kids.push(node)
- end
- }
- }
- @topdir = @nodes[name]
- end
-
- # figure out how much is taken in each directory
- # that isn't stored in the subdirectories. Add a new
- # fake kid called "." containing that much.
- def get_dots(node)
- cursize = node.size
- for kid in node.kids
- cursize -= kid.size
- get_dots(kid)
- end
- if node.size != cursize
- newnode = get_create_node(node.name + "/.")
- newnode.size = cursize
- node.kids.push(newnode)
- end
- end
-
- # recursively output everything
- # passing padding and number width as well
- # on recursive calls
- def output(node, prefix="", width=0)
- line = sprintf("%#{width}d %s", node.size, node.basename)
- puts(prefix + line)
- prefix += line.sub(/\d /, "| ")
- prefix.gsub!(/[^|]/, " ")
- if node.kids.length > 0 # not a bachelor node
- kids = node.kids
- kids.sort! { |a,b|
- b.size_compare(a)
- }
- width = kids[0].size.to_s.length
- for kid in kids
- output(kid, prefix, width)
- end
- end
- end
-
-end
-
-tree = Dutree.new
-tree.input(ARGV)
-tree.get_dots(tree.topdir)
-tree.output(tree.topdir)
-
-
-# @@PLEAC@@_6.0
-# The verbose version are match, sub, gsub, sub! and gsub!;
-# pattern needs to be a Regexp object; it yields a MatchData
-# object.
-pattern.match(string)
-string.sub(pattern, replacement)
-string.gsub(pattern, replacement)
-# As usual in Ruby, sub! does the same as sub but also modifies
-# the object, the same for gsub!/gsub.
-
-# Sugared syntax yields the position of the match (or nil if no
-# match). Note that the object at the right of the operator needs
-# not to be a Regexp object (it can be a String). The "dont
-# match" operator yields true or false.
-meadow =~ /sheep/ # position of the match, nil if no match
-meadow !~ /sheep/ # true if doesn't match, false if it does
-# There is no sugared version for the substitution
-
-meadow =~ /\bovines?\b/i and print "Here be sheep!"
-
-string = "good food"
-string.sub!(/o*/, 'e')
-
-# % echo ababacaca | ruby -ne 'puts $& if /(a|ba|b)+(a|ac)+/'
-# ababa
-
-# The "global" (or "multiple") match is handled by String#scan
-scan (/(\d+)/) {
- puts "Found number #{$1}"
-}
-
-# String#scan yields an Array if not used with a block
-numbers = scan(/\d+/)
-
-digits = "123456789"
-nonlap = digits.scan(/(\d\d\d)/)
-yeslap = digits.scan(/(?=(\d\d\d))/)
-puts "Non-overlapping: #{nonlap.join(' ')}"
-puts "Overlapping: #{yeslap.join(' ')}";
-# Non-overlapping: 123 456 789
-# Overlapping: 123 234 345 456 567 678 789
-
-string = "And little lambs eat ivy"
-string =~ /l[^s]*s/
-puts "(#$`) (#$&) (#$')"
-# (And ) (little lambs) ( eat ivy)
-
-
-# @@PLEAC@@_6.1
-# Ruby doesn't have the same problem:
-dst = src.sub('this', 'that')
-
-progname = $0.sub('^.*/', '')
-
-bindirs = %w(/usr/bin /bin /usr/local/bin)
-libdirs = bindirs.map { |l| l.sub('bin', 'lib') }
-
-
-# @@PLEAC@@_6.3
-/\S+/ # as many non-whitespace bytes as possible
-/[A-Za-z'-]+/ # as many letters, apostrophes, and hyphens
-
-/\b([A-Za-z]+)\b/ # usually best
-/\s([A-Za-z]+)\s/ # fails at ends or w/ punctuation
-
-
-# @@PLEAC@@_6.4
-require 'socket'
-str = 'www.ruby-lang.org and www.rubygarden.org'
-re = /
- ( # capture the hostname in $1
- (?: # these parens for grouping only
- (?! [-_] ) # lookahead for neither underscore nor dash
- [\w-] + # hostname component
- \. # and the domain dot
- ) + # now repeat that whole thing a bunch of times
- [A-Za-z] # next must be a letter
- [\w-] + # now trailing domain part
- ) # end of $1 capture
- /x # /x for nice formatting
-
-str.gsub! re do # pass a block to execute replacement
- host = TCPsocket.gethostbyname($1)
- "#{$1} [#{host[3]}]"
-end
-
-puts str
-#-----------------------------
-# to match whitespace or #-characters in an extended re you need to escape
-# them.
-
-foo = 42
-str = 'blah #foo# blah'
-str.gsub! %r/ # replace
- \# # a pound sign
- (\w+) # the variable name
- \# # another pound sign
- /x do
- eval $1 # with the value of a local variable
- end
-puts str # => blah 42 blah
-
-
-# @@PLEAC@@_6.5
-# The 'g' modifier doesn't exist in Ruby, a regexp can't be used
-# directly in a while loop; instead, use String#scan { |match| .. }
-fish = 'One fish two fish red fish blue fish'
-WANT = 3
-count = 0
-fish.scan(/(\w+)\s+fish\b/i) {
- if (count += 1) == WANT
- puts "The third fish is a #{$1} one."
- end
-}
-
-if fish =~ /(?:\w+\s+fish\s+){2}(\w+)\s+fish/i
- puts "The third fish is a #{$1} one."
-end
-
-pond = 'One fish two fish red fish blue fish'
-# String#scan without a block gives an array of matches, each match
-# being an array of all the specified groups
-colors = pond.scan(/(\w+)\s+fish\b/i).flatten # get all matches
-color = colors[2] # then the one we want
-# or without a temporary array
-color = pond.scan(/(\w+)\s+fish\b/i).flatten[2] # just grab element 3
-puts "The third fish in the pond is #{color}."
-
-count = 0
-fishes = 'One fish two fish red fish blue fish'
-evens = fishes.scan(/(\w+)\s+fish\b/i).select { (count+=1) % 2 == 0 }
-print "Even numbered fish are #{evens.join(' ')}."
-
-count = 0
-fishes.gsub(/
- \b # makes next \w more efficient
- ( \w+ ) # this is what we\'ll be changing
- (
- \s+ fish \b
- )
- /x) {
- if (count += 1) == 4
- 'sushi' + $2
- else
- $1 + $2
- end
-}
-
-pond = 'One fish two fish red fish blue fish swim here.'
-puts "Last fish is #{pond.scan(/\b(\w+)\s+fish\b/i).flatten[-1]}"
-
-/
- A # find some pattern A
- (?! # mustn\'t be able to find
- .* # something
- A # and A
- )
- $ # through the end of the string
-/x
-
-# The "s" perl modifier is "m" in Ruby (not very nice since there is
-# also an "m" in perl..)
-pond = "One fish two fish red fish blue fish swim here."
-if (pond =~ /
- \b ( \w+) \s+ fish \b
- (?! .* \b fish \b )
- /mix)
- puts "Last fish is #{$1}."
-else
- puts "Failed!"
-end
-
-
-# @@PLEAC@@_6.6
-#-----------------------------
-#!/usr/bin/ruby -w
-# killtags - very bad html killer
-$/ = nil; # each read is whole file
-while file = gets() do
- file.gsub!(/<.*?>/m,''); # strip tags (terribly)
- puts file # print file to STDOUT
-end
-#-----------------------------
-#!/usr/bin/ruby -w
-#headerfy - change certain chapter headers to html
-$/ = ''
-while file = gets() do
- pattern = /
- \A # start of record
- ( # capture in $1
- Chapter # text string
- \s+ # mandatory whitespace
- \d+ # decimal number
- \s* # optional whitespace
- : # a real colon
- . * # anything not a newline till end of line
- )
- /x
- puts file.gsub(pattern,'<H1>\1</H1>')
-end
-#-----------------------------
-#% ruby -00pe "gsub!(/\A(Chapter\s+\d+\s*:.*)/,'<H1>\1</H1>')" datafile
-
-#!/usr/bin/ruby -w
-#-----------------------------
-for file in ARGV
- file = File.open(ARGV.shift)
- while file.gets('') do # each read is a paragraph
- print "chunk #{$.} in $ARGV has <<#{$1}>>\n" while /^START(.*?)^END/m
- end # /m activates the multiline mode
-end
-#-----------------------------
-
-# @@PLEAC@@_6.7
-#-----------------------------
-$/ = nil;
-file = File.open("datafile")
-chunks = file.gets.split(/pattern/)
-#-----------------------------
-# .Ch, .Se and .Ss divide chunks of STDIN
-chunks = gets(nil).split(/^\.(Ch|Se|Ss)$/)
-print "I read #{chunks.size} chunks.\n"
-#-----------------------------
-
-
-# @@PLEAC@@_6.8
-while gets
- if ~/BEGIN/ .. ~/END/
- # line falls between BEGIN and END inclusive
- end
-end
-
-while gets
- if ($. == firstnum) .. ($. == lastnum)
- # operate between firstnum and lastnum line number
- end
-end
-
-# in ruby versions prior to 1.8, the above two conditional
-# expressions could be shortened to:
-# if /BEGIN/ .. /END/
-# and
-# if firstnum .. lastnum
-# but these now only work this way from the command line
-
-#-----------------------------
-
-while gets
- if ~/BEGIN/ ... ~/END/
- # line falls between BEGIN and END on different lines
- end
-end
-
-while gets
- if ($. == first) ... ($. == last)
- # operate between first and last line number on different lines
- end
-end
-
-#-----------------------------
-# command-line to print lines 15 through 17 inclusive (see below)
-ruby -ne 'print if 15 .. 17' datafile
-
-# print out all <XMP> .. </XMP> displays from HTML doc
-while gets
- print if ~%r#<XMP>#i .. ~%r#</XMP>#i;
-end
-
-# same, but as shell command
-# ruby -ne 'print if %r#<XMP>#i .. %r#</XMP>#i' document.html
-#-----------------------------
-# ruby -ne 'BEGIN { $top=3; $bottom=5 }; \
-# print if $top .. $bottom' /etc/passwd # FAILS
-# ruby -ne 'BEGIN { $top=3; $bottom=5 }; \
-# print if $. == $top .. $. == $bottom' /etc/passwd # works
-# ruby -ne 'print if 3 .. 5' /etc/passwd # also works
-#-----------------------------
-print if ~/begin/ .. ~/end/;
-print if ~/begin/ ... ~/end/;
-#-----------------------------
-while gets
- $in_header = $. == 1 .. ~/^$/ ? true : false
- $in_body = ~/^$/ .. ARGF.eof ? true : false
-end
-#-----------------------------
-seen = {}
-ARGF.each do |line|
- next unless line =~ /^From:?\s/i .. line =~ /^$/;
- line.scan(%r/([^<>(),;\s]+\@[^<>(),;\s]+)/).each do |addr|
- puts addr unless seen[addr]
- seen[addr] ||= 1
- end
-end
-
-
-# @@PLEAC@@_6.9
-def glob2pat(globstr)
- patmap = {
- '*' => '.*',
- '?' => '.',
- '[' => '[',
- ']' => ']',
- }
- globstr.gsub!(/(.)/) { |c| patmap[c] || Regexp::escape(c) }
- '^' + globstr + '$'
-end
-
-
-# @@PLEAC@@_6.10
-# avoid interpolating patterns like this if the pattern
-# isn't going to change:
-pattern = ARGV.shift
-ARGF.each do |line|
- print line if line =~ /#{pattern}/
-end
-
-# the above creates a new regex each iteration. Instead,
-# use the /o modifier so the regex is compiled only once
-
-pattern = ARGV.shift
-ARGF.each do |line|
- print line if line =~ /#{pattern}/o
-end
-
-#-----------------------------
-
-#!/usr/bin/ruby
-# popgrep1 - grep for abbreviations of places that say "pop"
-# version 1: slow but obvious way
-popstates = %w(CO ON MI WI MN)
-ARGF.each do |line|
- popstates.each do |state|
- if line =~ /\b#{state}\b/
- print line
- last
- end
- end
-end
-
-#-----------------------------
-#!/usr/bin/ruby
-# popgrep2 - grep for abbreviations of places that say "pop"
-# version 2: eval strings; fast but hard to quote
-popstates = %w(CO ON MI WI MN)
-code = "ARGF.each do |line|\n"
-popstates.each do |state|
- code += "\tif line =~ /\\b#{state}\\b/; print(line); next; end\n"
-end
-code += "end\n"
-print "CODE IS\n---\n#{code}\n---\n" if false # turn on for debugging
-eval code
-
-# CODE IS
-# ---
-# ARGF.each do |line|
-# if line =~ /\bCO\b/; print(line); next; end
-# if line =~ /\bON\b/; print(line); next; end
-# if line =~ /\bMI\b/; print(line); next; end
-# if line =~ /\bWI\b/; print(line); next; end
-# if line =~ /\bMN\b/; print(line); next; end
-# end
-#
-# ---
-
-## alternatively, the same idea as above but compiling
-## to a case statement: (not in perlcookbook)
-#!/usr/bin/ruby -w
-# popgrep2.5 - grep for abbreviations of places that say "pop"
-# version 2.5: eval strings; fast but hard to quote
-popstates = %w(CO ON MI WI MN)
-code = "ARGF.each do |line|\n case line\n"
-popstates.each do |state|
- code += " when /\\b#{state}\\b/ : print line\n"
-end
-code += " end\nend\n"
-print "CODE IS\n---\n#{code}\n---\n" if false # turn on for debugging
-eval code
-
-# CODE IS
-# ---
-# ARGF.each do |line|
-# case line
-# when /\bCO\b/ : print line
-# when /\bON\b/ : print line
-# when /\bMI\b/ : print line
-# when /\bWI\b/ : print line
-# when /\bMN\b/ : print line
-# end
-# end
-#
-# ---
-
-# Note: (above) Ruby 1.8+ allows the 'when EXP : EXPR' on one line
-# with the colon separator.
-
-#-----------------------------
-#!/usr/bin/ruby
-# popgrep3 - grep for abbreviations of places that say "pop"
-# version3: build a match_any function
-popstates = %w(CO ON MI WI MN)
-expr = popstates.map{|e|"line =~ /\\b#{e}\\b/"}.join('||')
-eval "def match_any(line); #{expr};end"
-ARGF.each do |line|
- print line if match_any(line)
-end
-#-----------------------------
-
-## building a match_all function is a trivial
-## substitution of && for ||
-## here is a generalized example:
-#!/usr/bin/ruby -w
-## grepauth - print lines that mention both foo and bar
-class MultiMatch
- def initialize(*patterns)
- _any = build_match('||',patterns)
- _all = build_match('&&',patterns)
- eval "def match_any(line);#{_any};end\n"
- eval "def match_all(line);#{_all};end\n"
- end
- def build_match(sym,args)
- args.map{|e|"line =~ /#{e}/"}.join(sym)
- end
-end
-
-mm = MultiMatch.new('foo','bar')
-ARGF.each do |line|
- print line if mm.match_all(line)
-end
-#-----------------------------
-
-#!/usr/bin/ruby
-# popgrep4 - grep for abbreviations of places that say "pop"
-# version4: pretty fast, but simple: compile all re's first:
-popstates = %w(CO ON MI WI MN)
-popstates = popstates.map{|re| %r/\b#{re}\b/}
-ARGF.each do |line|
- popstates.each do |state_re|
- if line =~ state_re
- print line
- break
- end
- end
-end
-
-## speeds trials on the jargon file(412): 26006 lines, 1.3MB
-## popgrep1 => 7.040s
-## popgrep2 => 0.656s
-## popgrep2.5 => 0.633s
-## popgrep3 => 0.675s
-## popgrep4 => 1.027s
-
-# unless speed is criticial, the technique in popgrep4 is a
-# reasonable balance between speed and logical simplicity.
-
-
-# @@PLEAC@@_6.11
-begin
- print "Pattern? "
- pat = $stdin.gets.chomp
- Regexp.new(pat)
-rescue
- warn "Invalid Pattern"
- retry
-end
-
-
-# @@PLEAC@@_6.13
-# uses the 'amatch' extension found on:
-# http://raa.ruby-lang.org/project/amatch/
-require 'amatch'
-matcher = Amatch.new('balast')
-#$relative, $distance = 0, 1
-File.open('/usr/share/dict/words').each_line do |line|
- print line if matcher.search(line) <= 1
-end
-__END__
-#CODE
-ballast
-ballasts
-balustrade
-balustrades
-blast
-blasted
-blaster
-blasters
-blasting
-blasts
-
-
-# @@PLEAC@@_6.14
-str.scan(/\G(\d)/).each do |token|
- puts "found #{token}"
-end
-#-----------------------------
-n = " 49 here"
-n.gsub!(/\G /,'0')
-puts n
-#-----------------------------
-str = "3,4,5,9,120"
-str.scan(/\G,?(\d+)/).each do |num|
- puts "Found number: #{num}"
-end
-#-----------------------------
-# Ruby doesn't have the String.pos or a /c re modifier like Perl
-# But it does have StringScanner in the standard library (strscn)
-# which allows similar functionality:
-
-require 'strscan'
-text = 'the year 1752 lost 10 days on the 3rd of September'
-sc = StringScanner.new(text)
-while sc.scan(/.*?(\d+)/)
- print "found: #{sc[1]}\n"
-end
-if sc.scan(/\S+/)
- puts "Found #{sc[0]} after last number"
-end
-#-----------------------------
-# assuming continuing from above:
-puts "The position in 'text' is: #{sc.pos}"
-sc.pos = 30
-puts "The position in 'text' is: #{sc.pos}"
-
-
-# @@PLEAC@@_6.15
-#-----------------------------
-# greedy pattern
-str.gsub!(/<.*>/m,'') # not good
-
-# non-greedy (minimal) pattern
-str.gsub!(/<.*?>/m,'') # not great
-
-
-#-----------------------------
-#<b><i>this</i> and <i>that</i> are important</b> Oh, <b><i>me too!</i></b>
-#-----------------------------
-%r{ <b><i>(.*?)</i></b> }mx
-#-----------------------------
-%r/BEGIN((?:(?!BEGIN).)*)END/
-#-----------------------------
-%r{ <b><i>( (?: (?!</b>|</i>). )* ) </i></b> }mx
-#-----------------------------
-%r{ <b><i>( (?: (?!</[ib]>). )* ) </i></b> }mx
-#-----------------------------
-%r{
- <b><i>
- [^<]* # stuff not possibly bad, and not possibly the end.
- (?:
- # at this point, we can have '<' if not part of something bad
- (?! </?[ib]> ) # what we can't have
- < # okay, so match the '<'
- [^<]* # and continue with more safe stuff
- ) *
- </i></b>
- }mx
-
-
-# @@PLEAC@@_6.16
-#-----------------------------
-$/ = ""
-ARGF.each do |para|
- para.scan %r/
- \b # start at word boundary
- (\S+) # find chunk of non-whitespace
- \b # until a word boundary
- (
- \s+ # followed by whitespace
- \1 # and that same chunk again
- \b # and a word boundary
- ) + # one or more times
- /xi do
- puts "dup word '#{$1}' at paragraph #{$.}"
- end
-end
-#-----------------------------
-astr = 'nobody'
-bstr = 'bodysnatcher'
-if "#{astr} #{bstr}" =~ /^(\w+)(\w+) \2(\w+)$/
- print "#{$2} overlaps in #{$1}-#{$2}-#{$3}"
-end
-#-----------------------------
-#!/usr/bin/ruby -w
-# prime_pattern -- find prime factors of argument using patterns
-ARGV << 180
-cap = 'o' * ARGV.shift
-while cap =~ /^(oo+?)\1+$/
- print $1.size, " "
- cap.gsub!(/#{$1}/,'o')
-end
-puts cap.size
-#-----------------------------
-#diophantine
-# solve for 12x + 15y + 16z = 281, maximizing x
-if ('o' * 281).match(/^(o*)\1{11}(o*)\2{14}(o*)\3{15}$/)
- x, y, z = $1.size, $2.size, $3.size
- puts "One solution is: x=#{x}; y=#{y}; z=#{z}"
-else
- puts "No solution."
-end
-# => One solution is: x=17; y=3; z=2
-
-#-----------------------------
-# using different quantifiers:
-('o' * 281).match(/^(o+)\1{11}(o+)\2{14}(o+)\3{15}$/)
-# => One solution is: x=17; y=3; z=2
-
-('o' * 281).match(/^(o*?)\1{11}(o*)\2{14}(o*)\3{15}$/)
-# => One solution is: x=0; y=7; z=11
-
-('o' * 281).match(/^(o+?)\1{11}(o*)\2{14}(o*)\3{15}$/)
-# => One solution is: x=1; y=3; z=14
-
-
-# @@PLEAC@@_6.17
-# alpha OR beta
-%r/alpha|beta/
-
-# alpha AND beta
-%r/(?=.*alpha)(?=.*beta)/m
-
-# alpha AND beta, no overlap
-%r/alpha.*beta|beta.*alpha/m
-
-# NOT beta
-%r/^(?:(?!beta).)*$/m
-
-# NOT bad BUT good
-%r/(?=(?:(?!BAD).)*$)GOOD/m
-#-----------------------------
-
-if !(string =~ /pattern/) # ugly
- something()
-end
-
-if string !~ /pattern/ # preferred
- something()
-end
-
-
-#-----------------------------
-if string =~ /pat1/ && string =~ /pat2/
- something()
-end
-#-----------------------------
-if string =~ /pat1/ || string =~ /pat2/
- something()
-end
-#-----------------------------
-#!/usr/bin/ruby -w
-# minigrep - trivial grep
-pat = ARGV.shift
-ARGF.each do |line|
- print line if line =~ /#{pat}/o
-end
-#-----------------------------
- "labelled" =~ /^(?=.*bell)(?=.*lab)/m
-#-----------------------------
-$string =~ /bell/ && $string =~ /lab/
-#-----------------------------
-$murray_hill = "blah bell blah "
-if $murray_hill =~ %r{
- ^ # start of string
- (?= # zero-width lookahead
- .* # any amount of intervening stuff
- bell # the desired bell string
- ) # rewind, since we were only looking
- (?= # and do the same thing
- .* # any amount of intervening stuff
- lab # and the lab part
- )
- }mx # /m means . can match newline
-
- print "Looks like Bell Labs might be in Murray Hill!\n";
-end
-#-----------------------------
-"labelled" =~ /(?:^.*bell.*lab)|(?:^.*lab.*bell)/
-#-----------------------------
-$brand = "labelled";
-if $brand =~ %r{
- (?: # non-capturing grouper
- ^ .*? # any amount of stuff at the front
- bell # look for a bell
- .*? # followed by any amount of anything
- lab # look for a lab
- ) # end grouper
- | # otherwise, try the other direction
- (?: # non-capturing grouper
- ^ .*? # any amount of stuff at the front
- lab # look for a lab
- .*? # followed by any amount of anything
- bell # followed by a bell
- ) # end grouper
- }mx # /m means . can match newline
- print "Our brand has bell and lab separate.\n";
-end
-#-----------------------------
-$map =~ /^(?:(?!waldo).)*$/s
-#-----------------------------
-$map = "the great baldo"
-if $map =~ %r{
- ^ # start of string
- (?: # non-capturing grouper
- (?! # look ahead negation
- waldo # is he ahead of us now?
- ) # is so, the negation failed
- . # any character (cuzza /s)
- ) * # repeat that grouping 0 or more
- $ # through the end of the string
- }mx # /m means . can match newline
- print "There's no waldo here!\n";
-end
-=begin
- 7:15am up 206 days, 13:30, 4 users, load average: 1.04, 1.07, 1.04
-
-USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
-
-tchrist tty1 5:16pm 36days 24:43 0.03s xinit
-
-tchrist tty2 5:19pm 6days 0.43s 0.43s -tcsh
-
-tchrist ttyp0 chthon 7:58am 3days 23.44s 0.44s -tcsh
-
-gnat ttyS4 coprolith 2:01pm 13:36m 0.30s 0.30s -tcsh
-=end
-#% w | minigrep '^(?!.*ttyp).*tchrist'
-#-----------------------------
-%r{
- ^ # anchored to the start
- (?! # zero-width look-ahead assertion
- .* # any amount of anything (faster than .*?)
- ttyp # the string you don't want to find
- ) # end look-ahead negation; rewind to start
- .* # any amount of anything (faster than .*?)
- tchrist # now try to find Tom
-}x
-#-----------------------------
-#% w | grep tchrist | grep -v ttyp
-#-----------------------------
-#% grep -i 'pattern' files
-#% minigrep '(?i)pattern' files
-#-----------------------------
-
-
-# @@PLEAC@@_6.20
-ans = $stdin.gets.chomp
-re = %r/^#{Regexp.quote(ans)}/
-case
- when "SEND" =~ re : puts "Action is send"
- when "STOP" =~ re : puts "Action is stop"
- when "ABORT" =~ re : puts "Action is abort"
- when "EDIT" =~ re : puts "Action is edit"
-end
-#-----------------------------
-require 'abbrev'
-table = Abbrev.abbrev %w-send stop abort edit-
-loop do
- print "Action: "
- ans = $stdin.gets.chomp
- puts "Action for #{ans} is #{table[ans.downcase]}"
-end
-
-
-#-----------------------------
-# dummy values are defined for 'file', 'PAGER', and
-# the 'invoke_editor' and 'deliver_message' methods
-# do not do anything interesting in this example.
-#!/usr/bin/ruby -w
-require 'abbrev'
-
-file = 'pleac_ruby.data'
-PAGER = 'less'
-
-def invoke_editor
- puts "invoking editor"
-end
-
-def deliver_message
- puts "delivering message"
-end
-
-actions = {
- 'edit' => self.method(:invoke_editor),
- 'send' => self.method(:deliver_message),
- 'list' => proc {system(PAGER, file)},
- 'abort' => proc {puts "See ya!"; exit},
- "" => proc {puts "Unknown Command"}
-}
-
-dtable = Abbrev.abbrev(actions.keys)
-loop do
- print "Action: "
- ans = $stdin.gets.chomp.delete(" \t")
- actions[ dtable[ans.downcase] || "" ].call
-end
-
-
-# @@PLEAC@@_6.19
-#-----------------------------
-# basically, the Perl Cookbook categorizes this as an
-# unsolvable problem ...
-#-----------------------------
-1 while addr.gsub!(/\([^()]*\)/,'')
-#-----------------------------
-Dear someuser@host.com,
-
-Please confirm the mail address you gave us Wed May 6 09:38:41
-MDT 1998 by replying to this message. Include the string
-"Rumpelstiltskin" in that reply, but spelled in reverse; that is,
-start with "Nik...". Once this is done, your confirmed address will
-be entered into our records.
-
-
-# @@PLEAC@@_6.21
-#-----------------------------
-#% gunzip -c ~/mail/archive.gz | urlify > archive.urlified
-#-----------------------------
-#% urlify ~/mail/*.inbox > ~/allmail.urlified
-#-----------------------------
-#!/usr/bin/ruby -w
-# urlify - wrap HTML links around URL-like constructs
-
-urls = '(https?|telnet|gopher|file|wais|ftp)';
-ltrs = '\w';
-gunk = '/#~:.?+=&%@!\-';
-punc = '.:?\-';
-any = "#{ltrs}#{gunk}#{punc}";
-
-ARGF.each do |line|
- line.gsub! %r/
- \b # start at word boundary
- ( # begin $1 {
- #{urls} : # need resource and a colon
- [#{any}] +? # followed by on or more
- # of any valid character, but
- # be conservative and take only
- # what you need to....
- ) # end $1 }
- (?= # look-ahead non-consumptive assertion
- [#{punc}]* # either 0 or more punctuation
- [^#{any}] # followed by a non-url char
- | # or else
- $ # then end of the string
- )
- /iox do
- %Q|<A HREF="#{$1}">#{$1}</A>|
- end
- print line
-end
-
-
-# @@PLEAC@@_6.23
-%r/^m*(d?c{0,3}|c[dm])(l?x{0,3}|x[lc])(v?i{0,3}|i[vx])$/i
-#-----------------------------
-str.sub!(/(\S+)(\s+)(\S+)/, '\3\2\1')
-#-----------------------------
-%r/(\w+)\s*=\s*(.*)\s*$/ # keyword is $1, value is $2
-#-----------------------------
-%r/.{80,}/
-#-----------------------------
-%r|(\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+)|
-#-----------------------------
-str.gsub!(%r|/usr/bin|,'/usr/local/bin')
-#-----------------------------
-str.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/){ $1.hex.chr }
-#-----------------------------
-str.gsub!(%r{
- /\* # Match the opening delimiter
- .*? # Match a minimal number of characters
- \*/ # Match the closing delimiter
-}xm,'')
-#-----------------------------
-str.sub!(/^\s+/, '')
-str.sub!(/\s+$/, '')
-
-# but really, in Ruby we'd just do:
-str.strip!
-#-----------------------------
-str.gsub!(/\\n/,"\n")
-#-----------------------------
-str.sub!(/^.*::/, '')
-#-----------------------------
-%r/^([01]?\d\d|2[0-4]\d|25[0-5])\.([01]?\d\d|2[0-4]\d|25[0-5])\.
- ([01]?\d\d|2[0-4]\d|25[0-5])\.([01]?\d\d|2[0-4]\d|25[0-5])$/x
-#-----------------------------
-str.sub!(%r|^.*/|, '')
-#-----------------------------
-cols = ( (ENV['TERMCAP'] || " ") =~ /:co#(\d+):/ ) ? $1 : 80;
-#-----------------------------
-name = " #{$0} #{ARGV}".gsub(%r| /\S+/|, ' ')
-#-----------------------------
-require 'rbconfig'
-include Config
-raise "This isn't Linux" unless CONFIG['target_os'] =~ /linux/i;
-#-----------------------------
-str.gsub!(%r/\n\s+/, ' ')
-#-----------------------------
-nums = str.scan(/(\d+\.?\d*|\.\d+)/)
-#-----------------------------
-capwords = str.scan(%r/(\b[^\Wa-z0-9_]+\b)/)
-#-----------------------------
-lowords = str.scan(%r/(\b[^\WA-Z0-9_]+\b)/)
-#-----------------------------
-icwords = str.scan(%r/(\b[^\Wa-z0-9_][^\WA-Z0-9_]*\b)/)
-#-----------------------------
-links = str.scan(%r/<A[^>]+?HREF\s*=\s*["']?([^'" >]+?)[ '"]?>/mi)
-#-----------------------------
-initial = str =~ /^\S+\s+(\S)\S*\s+\S/ ? $1 : ""
-#-----------------------------
-str.gsub!(%r/"([^"]*)"/, %q-``\1''-)
-#-----------------------------
-
-$/ = ""
-sentences = []
-ARGF.each do |para|
- para.gsub!(/\n/, ' ')
- para.gsub!(/ {3,}/,' ')
- sentences << para.scan(/(\S.*?[!?.])(?= |\Z)/)
-end
-
-#-----------------------------
-%r/(\d{4})-(\d\d)-(\d\d)/ # YYYY in $1, MM in $2, DD in $3
-#-----------------------------
-%r/ ^
- (?:
- 1 \s (?: \d\d\d \s)? # 1, or 1 and area code
- | # ... or ...
- \(\d\d\d\) \s # area code with parens
- | # ... or ...
- (?: \+\d\d?\d? \s)? # optional +country code
- \d\d\d ([\s\-]) # and area code
- )
- \d\d\d (\s|\1) # prefix (and area code separator)
- \d\d\d\d # exchange
- $
- /x
-#-----------------------------
-%r/\boh\s+my\s+gh?o(d(dess(es)?|s?)|odness|sh)\b/i
-#-----------------------------
-lines = []
-lines << $1 while input.sub!(/^([^\012\015]*)(\012\015?|\015\012?)/,'')
-
-
-# @@PLEAC@@_7.0
-# An IO object being Enumerable, we can use 'each' directly on it
-File.open("/usr/local/widgets/data").each { |line|
- puts line if line =~ /blue/
-}
-
-logfile = File.new("/var/log/rubylog.txt", "w")
-mysub($stdin, logfile)
-
-# The method IO#readline is similar to IO#gets
-# but throws an exception when it reaches EOF
-f = File.new("bla.txt")
-begin
- while (line = f.readline)
- line.chomp
- $stdout.print line if line =~ /blue/
- end
-rescue EOFError
- f.close
-end
-
-while $stdin.gets # reads from STDIN
- unless (/\d/)
- $stderr.puts "No digit found." # writes to STDERR
- end
- puts "Read: #{$_}" # writes to STDOUT
-end
-
-logfile = File.new("/tmp/log", "w")
-
-logfile.close
-
-# $defout (or its synonym '$>') is the destination of output
-# for Kernel#print, Kernel#puts, and family functions
-logfile = File.new("log.txt", "w")
-old = $defout
-$defout = logfile # switch to logfile for output
-puts "Countdown initiated ..."
-$defout = old # return to original output
-puts "You have 30 seconds to reach minimum safety distance."
-
-
-# @@PLEAC@@_7.1
-source = File.new(path, "r") # open file "path" for reading only
-sink = File.new(path, "w") # open file "path" for writing only
-
-source = File.open(path, File::RDONLY) # open file "path" for reading only
-sink = File.open(path, File::WRONLY) # open file "path" for writing only
-
-file = File.open(path, "r+") # open "path" for reading and writing
-file = File.open(path, flags) # open "path" with the flags "flags" (see examples below for flags)
-
-# open file "path" read only
-file = File.open(path, "r")
-file = File.open(path, File::RDONLY)
-
-# open file "path" write only, create it if it does not exist
-# truncate it to zero length if it exists
-file = File.open(path, "w")
-file = File.open(path, File::WRONLY|File::TRUNC|File::CREAT)
-file = File.open(path, File::WRONLY|File::TRUNC|File::CREAT, 0666) # with permission 0666
-
-# open file "path" write only, fails if file exists
-file = File.open(path, File::WRONLY|File::EXCL|File::CREAT)
-file = File.open(path, File::WRONLY|File::EXCL|File::CREAT, 0666)
-
-# open file "path" for appending
-file = File.open(path, "a")
-file = File.open(path, File::WRONLY|File::APPEND|File::CREAT)
-file = File.open(path, File::WRONLY|File::APPEND|File::CREAT, 0666)
-
-# open file "path" for appending only when file exists
-file = File.open(path, File::WRONLY|File::APPEND)
-
-# open file "path" for reading and writing
-file = File.open(path, "r+")
-file = File.open(path, File::RDWR)
-
-# open file for reading and writing, create a new file if it does not exist
-file = File.open(path, File::RDWR|File::CREAT)
-file = File.open(path, File::RDWR|File::CREAT, 0600)
-
-# open file "path" reading and writing, fails if file exists
-file = File.open(path, File::RDWR|File::EXCL|File::CREAT)
-file = File.open(path, File::RDWR|File::EXCL|File::CREAT, 0600)
-
-
-# @@PLEAC@@_7.2
-# No problem with Ruby since the filename doesn't contain characters with
-# special meaning; like Perl's sysopen
-File.open(filename, 'r')
-
-
-# @@PLEAC@@_7.3
-File.expand_path('~root/tmp')
-#=> "/root/tmp"
-File.expand_path('~rpcuser')
-#=> "/var/lib/nfs"
-
-# To expand ~/.. it explicitely needs the environment variable HOME
-File.expand_path('~/tmp')
-#=> "/home/gc/tmp"
-
-
-# @@PLEAC@@_7.4
-# The exception raised in Ruby reports the filename
-File.open('afile')
-
-
-# @@PLEAC@@_7.5
-# Standard Ruby distribution provides the following useful extension
-require 'tempfile'
-# With the Tempfile class, the file is automatically deleted on garbage
-# collection, so you won't need to remove it, later on.
-tf = Tempfile.new('tmp') # a name is required to create the filename
-
-# If you need to pass the filename to an external program you can use
-# File#path, but don't forget to File#flush in order to flush anything
-# living in some buffer somewhere.
-tf.flush
-system("/usr/bin/dowhatever #{tf.path}")
-
-fh = Tempfile.new('tmp')
-fh.sync = true # autoflushes
-10.times { |i| fh.puts i }
-fh.rewind
-puts 'Tmp file has: ', fh.readlines
-
-
-# @@PLEAC@@_7.6
-while (DATA.gets) do
- # process the line
-end
-__END__
-# your data goes here
-# __DATA__ doesn't exist in Ruby
-
-#CODE
-# get info about the script (size, date of last modification)
-kilosize = DATA.stat.size / 1024
-last_modif = DATA.stat.mtime
-puts "<P>Script size is #{kilosize}"
-puts "<P>Last script update: #{last_modif}"
-__END__
-# DO NOT REMOVE THE PRECEEDING LINE.
-# Everything else in this file will be ignored.
-#CODE
-
-
-# @@PLEAC@@_7.7
-while line = gets do
- # do something with line.
-end
-
-# or
-while gets do
- # do something with $_
-end
-
-# or more rubyish
-$stdun.each do |line|
- # do stuff with line
-end
-
-
-# ARGF may makes this more easy
-# this is skipped if ARGV.size==0
-ARGV.each do |filename|
- # closing and exception handling are done by the block
- open(filename) do |fd|
- fd.each do |line|
- # do stuff with line
- end
- end rescue abort("can't open %s" % filename)
-end
-
-# globbing is done in the Dir module
-ARGV = Dir["*.[Cch]"] if ARGV.empty?
-
-# note: optparse is the preferred way to handle this
-if (ARGV[0] == '-c')
- chop_first += 1
- ARGV.shift
-end
-
-
-# processing numerical options
-if ARGV[0] =~ /^-(\d+)$/
- columns = $1
- ARGV.shift
-end
-
-# again, better to use optparse:
-require 'optparse'
-nostdout = 0
-append = 0
-unbuffer = 0
-ignore_ints = 0
-ARGV.options do |opt|
- opt.on('-n') { nostdout +=1 }
- opt.on('-a') { append +=1 }
- opt.on('-u') { unbuffer +=1 }
- opt.on('-i') { ignore_ints +=1 }
- opt.parse!
-end or abort("usage: " + __FILE__ + " [-ainu] [filenames]")
-
-# no need to do undef $/, we have File.read
-str = File.read(ARGV[0])
-
-# again we have File.read
-str = File.read(ARGV[0])
-
-# not sure what this should do:
-# I believe open the file, print filename, lineno and line:
-ARGF.each_with_index do |line, idx|
- print ARGF.filename, ":", idx, ";", line
-end
-
-# print all the lines in every file passed via command line that contains login
-ARGF.each do |line|
- puts line if line =~ /login/
-end
-#
-# even this would fit
-#%ruby -ne "print if /f/" 2.log
-#
-
-ARGF.each { |l| puts l.downcase! }
-
-#------------------
-#!/usr/bin/ruby -p
-# just like perl's -p
-$_.downcase!
-#
-
-# I don't know who should I trust.
-# perl's version splits on \w+ while python's on \w.
-
-chunks = 0
-
-File.read(ARGV[0]).split.each do |word|
- next if word =~ /^#/
- break if ["__DATA__", "__END__"].member? word
- chunks += 1
-end
-
-print "Found ", chunks, " chunks\n"
-
-
-# @@PLEAC@@_7.8
-old = File.open(old_file)
-new = File.open(new_file, "w")
-while old.gets do
- # change $_, then...
- new.print $_
-end
-old.close
-new.close
-File.rename(old_file, "old.orig")
-File.rename(new_file, old_file)
-
-while old.gets do
- if $. == 20 then # we are at the 20th line
- new.puts "Extra line 1"
- new.puts "Extra line 2"
- end
- new.print $_
-end
-
-while old.gets do
- next if 20..30 # skip the 20th line to the 30th
- # Ruby (and Perl) permit to write if 20..30
- # instead of if (20 <= $.) and ($. <= 30)
- new.print $_
-end
-
-
-# @@PLEAC@@_7.9
-#% ruby -i.orig -pe 'FILTER COMMAND' file1 file2 file3 ...
-#
-#-----------------------------
-##!/usr/bin/ruby -i.orig -p
-# filter commands go here
-#-----------------------------
-
-#% ruby -pi.orig -e 'gsub!(/DATE/){Time.now)'
-
-# effectively becomes:
-ARGV << 'I'
-oldfile = ""
-while gets
- if ARGF.filename != oldfile
- newfile = ARGF.filename
- File.rename(newfile, newfile + ".orig")
- $stdout = File.open(newfile,'w')
- oldfile = newfile
- end
- gsub!(/DATE/){Time.now}
- print
-end
-$stdout = STDOUT
-#-----------------------------
-#% ruby -i.old -pe 'gsub!(%r{\bhisvar\b}, 'hervar')' *.[Cchy]
-
-#-----------------------------
-# set up to iterate over the *.c files in the current directory,
-# editing in place and saving the old file with a .orig extension
-$-i = '.orig' # set up -i mode
-ARGV.replace(Dir['*.[Cchy]'])
-while gets
- if $. == 1
- print "This line should appear at the top of each file\n"
- end
- gsub!(/\b(p)earl\b/i, '\1erl') # Correct typos, preserving case
- print
- ARGF.close if ARGF.eof
-end
-
-
-# @@PLEAC@@_7.10
-File.open('itest', 'r+') do |f| # open file for update
- lines = f.readlines # read into array of lines
- lines.each do |it| # modify lines
- it.gsub!(/foo/, 'QQQ')
- end
- f.pos = 0 # back to start
- f.print lines # write out modified lines
- f.truncate(f.pos) # truncate to new length
-end # file is automatically closed
-#-----------------------------
-File.open('itest', 'r+') do |f|
- out = ""
- f.each do |line|
- out << line.gsub(/DATE/) {Time.now}
- end
- f.pos = 0
- f.print out
- f.truncate(f.pos)
-end
-
-# @@PLEAC@@_7.11
-File.open('infile', 'r+') do |f|
- f.flock File::LOCK_EX
- # update file
-end
-#-----------------------------
-File::LOCK_SH # shared lock (for reading)
-File::LOCK_EX # exclusive lock (for writing)
-File::LOCK_NB # non-blocking request
-File::LOCK_UN # free lock
-#-----------------------------
-unless f.flock File::LOCK_EX | File::LOCK_NB
- warn "can't get immediate lock: blocking ..."
- f.flock File::LOCK_EX
-end
-#-----------------------------
-File.open('numfile', File::RDWR|File::CREAT) do |f|
- f.flock(File::LOCK_EX)
- num = f.gets.to_i || 0
- f.pos = 0
- f.truncate 0
- f.puts num + 1q
-end
-
-
-# @@PLEAC@@_7.12
-output_handle.sync = true
-# Please note that like in Perl, $stderr is already unbuffered
-#-----------------------------
-#!/usr/bin/ruby -w
-# seeme - demo stdio output buffering
-$stdout.sync = ARGV.size > 0
-print "Now you don't see it..."
-sleep 2
-puts "now you do"
-#-----------------------------
-$stderr.sync = true
-afile.sync = false
-#-----------------------------
-# assume 'remote_con' is an interactive socket handle,
-# but 'disk_file' is a handle to a regular file.
-remote_con.sync = true # unbuffer for clarity
-disk_file.sync = false # buffered for speed
-#-----------------------------
-require 'socket'
-sock = TCPSocket.new('www.ruby-lang.org', 80)
-sock.sync = true
-sock.puts "GET /en/ HTTP/1.0 \n\n"
-resp = sock.read
-print "DOC IS: #{resp}\n"
-
-
-# @@PLEAC@@_7.13
-#-----------------------------
-# assumes fh1, fh2, fh2 are oen IO objects
-nfound = select([$stdin, fh1, fh2, fh3], nil, nil, 0)
-nfound[0].each do |file|
- case file
- when fh1
- # do something with fh1
- when fh2
- # do something with fh2
- when fh3
- # do something with fh3
- end
-end
-#-----------------------------
-input_files = []
-# repeat next line for all in-files to poll
-input_files << fh1
-if nfound = select(input_files, nil, nil, 0)
- # input ready on files in nfound[0]
-end
-
-
-# @@PLEAC@@_8.0
-#-----------------------------
-# datafile is a file or IO object
-datafile.readlines.each { |line|
- line.chomp!
- size = line.length
- puts size
-}
-#-----------------------------
-datafile.readlines.each { |line|
- puts line.chomp!.length
-}
-#-----------------------------
-lines = datafile.readlines
-#-----------------------------
-whole_file = file.read
-#-----------------------------
-# ruby -040 -e 'word = gets; puts "First word is #{word}"'
-#-----------------------------
-# ruby -ne 'BEGIN { $/="%%\n" }; $_.chomp; puts $_ if( $_=~/Unix/i)' fortune.dat
-#-----------------------------
-handle.print "one", "two", "three" # "onetwothree"
-puts "Baa baa black sheep." # sent to $stdout
-#-----------------------------
-buffer = handle.read(4096)
-rv = buffer.length
-#-----------------------------
-handle.truncate(length)
-open("/tmp#{$$}.pid", 'w') { |handle| handle.truncate(length) }
-#-----------------------------
-pos = datafile.pos # tell is an alias of pos
-puts "I'm #{pos} bytes from the start of datafile"
-#-----------------------------
-logfile.seek(0, IO::SEEK_END)
-datafile.seek(pos) # IO::SEEK_SET is the default
-out.seek(-20, IO::SEEK_CUR)
-#-----------------------------
-written = datafile.syswrite(mystring)
-raise RunTimeError unless written == mystring.length
-block = infile.sysread(256) # no equivalent to perl offset parameter in sysread
-puts "only read #{block.length} bytes" if 256 != block.length
-#-----------------------------
-pos = handle.sysseek(0, IO::SEEK_CUR) # don't change position
-
-
-# @@PLEAC@@_8.1
-while (line = fh.gets)
- line.chomp!
- nextline = nil
- line.gsub!(/\\$/) { |match| nextline = fh.gets; '' }
- if (nextline != nil)
- line += nextline
- redo
- end
- # process full record in line here
-end
-#-----------------------------
-# DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) \
-# $(TEXINFOS) $(INFOS) $(MANS) $(DATA)
-# DEP_DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) \
-# $(TEXINFOS) $(INFO_DEPS) $(MANS) $(DATA) \
-# $(EXTRA_DIST)
-#-----------------------------
-line.gsub!(/\\\s*$/, '') {
- # as before
-}
-
-
-# @@PLEAC@@_8.2
-#-----------------------------
-count = `wc -l < #{filename}`
-fail "wc failed: #{$?}" if $? != 0
-count.chomp!
-#-----------------------------
-count = 0
-File.open(file, 'r') { |fh|
- count += 1 while fh.gets
-}
-# count now holds the number of lines read
-#-----------------------------
-count = 0
-while (chunk = file.sysread(2**16))
- count += chunk.count("\n")
-end rescue EOFError
-#-----------------------------
-File.open(filename,'r') { |fh|
- count += 1 while fh.gets
-}
-# count now holds the number of lines read
-#-----------------------------
-# As ruby doesn't quite have an equivalent to using a for
-# statement as in perl, I threw this in
-count = File.readlines(filename).size
-#-----------------------------
-1 while file.gets
-count = $.
-#-----------------------------
-$/ = ''
-open(filename, 'r') { |fh|
- 1 while fh.gets
- para_count = $.
-} rescue fail("can't open #{filename}: $!")
-#-----------------------------
-
-
-# ^^PLEAC^^_8.3
-#-----------------------------
-while (gets)
- split.each { |chunk|
- # do something with chunk
- }
-end
-#-----------------------------
-while (gets)
- gsub(/(\w[\w'-]*)/) { |word|
- # do something with word
- }
-end
-#-----------------------------
-# Make a word frequency count
-# normally hashes can be created using {} or just Hash.new
-# but we want the default value of an entry to be 0 instead
-# of nil. (nil can't be incremented)
-seen = Hash.new(0)
-while (gets)
- gsub(/(\w[\w'-]*)/) { |word|
- seen[word.downcase] += 1
- }
-end
-# output hash in a descending numeric sort of its values
-seen.sort { |a,b| b[1] <=> a[1] }.each do |k,v|
- printf("%5d %s\n", v, k )
-end
-
-#-----------------------------
-# Line frequency count
-seen = Hash.new(0)
-while (gets)
- seen[$_.downcase] += 1
-end
-seen.sort { |a,b| b[1] <=> a[1] }.each do |k,v|
- printf("%5d %s\n", v, k )
-end
-#-----------------------------
-
-
-# @@PLEAC@@_8.4
-#-----------------------------
-# instead of file handle FILE, we can just
-# use a string containing the filename
-File.readlines(file).each { |line|
- # do something with line
-}
-#-----------------------------
-File.readlines(file).reverse_each { |line|
- # do something with line
-}
-#-----------------------------
-# the variable lines might have been created
-# this way
-# lines = File.readlines(file)
-#
-# normally one would use the reverse_each, but
-# if you insist on using a numerical index to
-# iterate over the lines array...
-(lines.size - 1).downto(0) { |i|
- line = lines[i]
-}
-#-----------------------------
-# the second readlines argument is a the
-# record separator $/, just like perl, a blank
-# separator splits the records into paragraphs
-File.readlines(file, '').each { |paragraph|
- # do something with paragraph
- puts "->Paragraph #{paragraph}"
-}
-#-----------------------------
-
-
-# @@PLEAC@@_8.6
-
-$/ = "%\n";
-srand;
-
-File.open('/usr/share/fortune/humorists').each do |line|
- adage = line if rand($.) < 1
-end
-
-puts adage;
-
-
-# @@PLEAC@@_8.10
-begin
- fh = File.open(file, "r+")
- addr = fh.tell unless fh.eof while fh.gets
- fh.truncate(addr)
-rescue SystemCallError
- $stderr.puts "#$!"
-end
-
-
-# @@PLEAC@@_9.0
-entry = File.stat("/usr/bin/vi")
-entry = File.stat("/usr/bin")
-entry = File.stat(INFILE)
-
-entry = File.stat("/usr/bin/vi")
-ctime = entry.ctime
-size = entry.size
-
-f = File.open(filename, "r")
-
-## There is no -T equivalent in Ruby, but we can still test emptiness
-if test(?s, filename)
- puts "#{filename} doesn't have text in it."
- exit
-end
-
-Dir.new("/usr/bin").each do |filename|
- puts "Inside /usr/bin is something called #{filename}"
-end
-
-
-# @@PLEAC@@_9.1
-file = File.stat("filename")
-readtime, writetime = file.atime, file.mtime
-file.utime(readtime, writetime)
-
-SECONDS_PER_DAY = 60 * 60 * 24
-file = File.stat("filename")
-atime, mtime = file.atime, file.mtime
-
-atime -= 7 * SECONDS_PER_DAY
-mtime -= 7 * SECONDS_PER_DAY
-
-File.utime(atime, mtime, file)
-mtime = File.stat(file).mtime
-File.utime(Time.new, mtime, file)
-File.utime(Time.new, File.stat("testfile").mtime, file)
-
-#-----------------------------
-#!/usr/bin/ruby -w
-## uvi - vi a file without changing it's access times
-
-if ARGV.length != 1
- puts "usage: uvi filename"
- exit
-end
-file = ARGV[0]
-atime, mtime = File.stat(file).atime, File.stat(file).mtime
-system(ENV["EDITOR"] || "vi", file)
-File.utime(atime, mtime, file)
-#-----------------------------
-
-
-# @@PLEAC@@_9.2
-File.unlink(FILENAME)
-
-err_flg = false
-filenames.each do |file|
- begin
- File.unlink(file)
- rescue
- err_flg = $!
- end
-end
-err_flg and raise "Couldn't unlink all of #{filenames.join(" ")}: #{err_flg}"
-
-File.unlink(file)
-
-count = filenames.length
-filenames.each do |file|
- begin
- File.unlink(file)
- rescue
- count -= 1
- end
-end
-if count != filenames.length
- STDERR.puts "could only delete #{count} of #{filenames.length} files"
-end
-
-
-# @@PLEAC@@_9.3
-require "ftools"
-File.copy(oldfile, newfile)
-
-infile = File.open(oldfile, "r")
-outfile = File.open(newfile, "w")
-
-blksize = infile.stat.blksize
-# This doesn't handle partial writes or ^Z
-# like the Perl version does.
-while (line = infile.read(blksize))
- outfile.write(line)
-end
-
-infile.close
-outfile.close
-
-system("cp #{oldfile} #{newfile}") # unix
-system("copy #{oldfile} #{newfile}") # dos, vms
-
-require "ftools"
-File.copy("datafile.dat", "datafile.bak")
-File.move("datafile.new", "datafile.dat")
-
-
-# @@PLEAC@@_9.4
-$seen = {} # must use global var to be seen inside of method below
-
-def do_my_thing(filename)
- dev, ino = File.stat(filename).dev, File.stat(filename).ino
- unless $seen[[dev, ino]]
- # do something with $filename because we haven't
- # seen it before
- end
- $seen[[dev, ino]] = $seen[[dev, ino]].to_i + 1
-end
-
-files.each do |filename|
- dev, ino = File.stat(filename).dev, File.stat(filename).ino
- if !$seen.has_key?([dev, ino])
- $seen[[dev, ino]] = []
- end
- $seen[[dev, ino]].push(filename)
-end
-
-$seen.keys.sort.each do |devino|
- ino, dev = devino
- if $seen[devino].length > 1
- # $seen[devino] is a list of filenames for the same file
- end
-end
-
-
-# @@PLEAC@@_9.5
-Dir.open(dirname) do |dir|
- dir.each do |file|
- # do something with dirname/file
- puts file
- end
-end
-# Dir.close is automatic
-
-# No -T equivalent in Ruby
-
-dir.each do |file|
- next if file =~ /^\.\.?$/
- # ...
-end
-
-def plainfiles(dir)
- dh = Dir.open(dir)
- dh.entries.grep(/^[^.]/).
- map {|file| "#{dir}/#{file}"}.
- find_all {|file| test(?f, file)}.
- sort
-end
-
-
-# @@PLEAC@@_9.6
-list = Dir.glob("*.c")
-
-dir = Dir.open(path)
-files = dir.entries.grep(/\.c$/)
-dir.close
-
-files = Dir.glob("*.c")
-files = Dir.open(path).entries.grep(/\.[ch]$/i)
-
-dir = Dir.new(path)
-files = dir.entries.grep(/\.[ch]$/i)
-
-begin
- d = Dir.open(dir)
-rescue Errno::ENOENT
- raise "Couldn't open #{dir} for reading: #{$!}"
-end
-
-files = []
-d.each do |file|
- puts file
- next unless file =~ /\.[ch]$/i
-
- filename = "#{dir}/#{file}"
- # There is no -T equivalent in Ruby, but we can still test emptiness
- files.push(filename) if test(?s, filename)
-end
-
-dirs.entries.grep(/^\d+$/).
- map { |file| [file, "#{path}/#{file}"]} .
- select { |file| test(?d, file[1]) }.
- sort { |a,b| a[0] <=> b[0] }.
- map { |file| file[1] }
-
-
-# @@PLEAC@@_9.7
-require 'find'
-Find.find(dirlist) do |file|
- # do whatever
-end
-
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-Find.find(*argv) do |file|
- print file, (test(?d, file) ? "/\n" : "\n")
-end
-
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-sum = 0
-Find.find(*argv) do |file|
- size = test(?s, file) || 0
- sum += size
-end
-puts "#{argv.join(' ')} contains #{sum} bytes"
-
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-saved_size, saved_name = -1, ""
-Find.find(*argv) do |file|
- size = test(?s, file) || 0
- next unless test(?f, file) && size > saved_size
- saved_size = size
- saved_name = file
-end
-puts "Biggest file #{saved_name} in #{argv.join(' ')} is #{saved_size}"
-
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-age, name = nil
-Find.find(*argv) do |file|
- mtime = File.stat(file).mtime
- next if age && age > mtime
- age = mtime
- name = file
-end
-puts "#{name} #{age}"
-
-#-----------------------------
-#!/usr/bin/ruby -w
-# fdirs - find all directories
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-File.find(*argv) { |file| puts file if test(?d, file) }
-#-----------------------------
-
-
-# @@PLEAC@@_9.8
-require 'fileutils'
-
-puts "Usage #{$0} dir ..." if ARGV.empty?
-ARGV.each do |dir|
- FileUtils.rmtree(dir)
-end
-
-
-# @@PLEAC@@_9.9
-require 'ftools'
-names.each do |file|
- newname = file
- begin
- File.move(file, newname)
- rescue Errno::EPERM
- $stderr.puts "Couldn't rename #{file} to #{newname}: #{$!}"
- end
-end
-
-require 'ftools'
-op = ARGV.empty? ? (raise "Usage: rename expr [files]\n") : ARGV.shift
-argv = ARGV.empty? ? $stdin.readlines.map { |f| f.chomp } : ARGV
-argv.each do |file|
- was = file
- file = eval("file.#{op}")
- File.move(was, file) unless was == file
-end
-
-
-# @@PLEAC@@_9.10
-base = File.basename(path)
-dir = File.dirname(path)
-# ruby has no fileparse equivalent
-dir, base = File.split(path)
-ext = base.scan(/\..*$/).to_s
-
-path = '/usr/lib/libc.a'
-file = File.basename(path)
-dir = File.dirname(path)
-
-puts "dir is #{dir}, file is #{file}"
-# dir is /usr/lib, file is libc.a
-
-path = '/usr/lib/libc.a'
-dir, filename = File.split(path)
-name, ext = filename.split(/(?=\.)/)
-puts "dir is #{dir}, name is #{name}, ext is #{ext}"
-# NOTE: The Ruby code prints
-# dir is /usr/lib, name is libc, extension is .a
-# while the Perl code prints a '/' after the directory name
-# dir is /usr/lib/, name is libc, extension is .a
-
-# No fileparse_set_fstype() equivalent in ruby
-
-def extension(path)
- ext = path.scan(/\..*$/).to_s
- ext.sub(/^\./, "")
-end
-
-
-# @@PLEAC@@_9.11
-#-----------------------------
-#!/usr/bin/ruby -w
-# symirror - build spectral forest of symlinks
-
-require 'find'
-require 'fileutils'
-
-raise "usage: #{$0} realdir mirrordir" unless ARGV.size == 2
-
-srcdir,dstdir = ARGV
-srcmode = File::stat(srcdir).mode
-Dir.mkdir(dstdir, srcmode & 07777) unless test(?d, dstdir)
-
-# fix relative paths
-Dir.chdir(srcdir) {srcdir = Dir.pwd}
-Dir.chdir(dstdir) {dstdir = Dir.pwd}
-
-Find.find(srcdir) do |srcfile|
- if test(?d, srcfile)
- dest = srcfile.sub(/^#{srcdir}/, dstdir)
- dmode = File::stat(srcfile).mode & 07777
- Dir.mkdir(dest, dmode) unless test(?d, dest)
- a = Dir["#{srcfile}/*"].reject{|f| test(?d, f)}
- FileUtils.ln_s(a, dest)
- end
-end
-
-
-# @@PLEAC@@_9.12
-# we use the Getopt/Declare library here for convenience:
-# http://raa.ruby-lang.org/project/getoptdeclare/
-#-----------------------------
-#!/usr/bin/ruby -w
-# lst - list sorted directory contents (depth first)
-
-require 'find'
-require 'etc'
-require "Getopt/Declare"
-
-# Note: in the option-spec below there must by at least one hard
-# tab in between each -option and its description. For example
-# -i <tab> read from stdin
-
-opts = Getopt::Declare.new(<<'EOPARAM')
- ============
- Input Format:
- -i read from stdin
- ============
- Output Format:
- -l long listing
- -r reverse listing
- ============
- Sort on: (one of)
- -m mtime (modify time - default)
- {$sort_criteria = :mtime}
- -u atime (access time)
- {$sort_criteria = :atime}
- -c ctime (inode change time)
- {$sort_criteria = :ctime}
- -s size
- {$sort_criteria = :size}
- [mutex: -m -u -c -s]
-
-EOPARAM
-
-$sort_criteria ||= :mtime
-files = {}
-DIRS = opts['-i'] ? $stdin.readlines.map{|f|f.chomp!} : ARGV
-DIRS.each do |dir|
- Find.find(dir) do |ent|
- files[ent] = File::stat(ent)
- end
-end
-entries = files.keys.sort_by{|f| files[f].send($sort_criteria)}
-entries = entries.reverse unless opts['-r']
-
-entries.each do |ent|
- unless opts['-l']
- puts ent
- next
- end
- stats = files[ent]
- ftime = stats.send($sort_criteria == :size ? :mtime : $sort_criteria)
- printf "%6d %04o %6d %8s %8s %8d %s %s\n",
- stats.ino,
- stats.mode & 07777,
- stats.nlink,
- ETC::PASSWD[stats.uid].name,
- ETC::GROUP[stats.gid].name,
- stats.size,
- ftime.strftime("%a %b %d %H:%M:%S %Y"),
- ent
-end
-
-
-# @@PLEAC@@_10.0
-def hello
- $greeted += 1 # in Ruby, a variable beginning with $ is global (can be any type of course)
- puts "hi there!"
-end
-
-# We need to initialize $greeted before it can be used, because "+=" is waiting a Numeric object
-$greeted = 0
-hello # note that appending () is optional to function calls with no parameters
-
-
-# @@PLEAC@@_10.1
-# In Ruby, parameters are named anyway
-def hypotenuse(side1, side2)
- Math.sqrt(side1**2 + side2**2) # the sqrt function comes from the Math module
-end
-diag = hypotenuse(3, 4)
-
-puts hypotenuse(3, 4)
-
-a = [3, 4]
-print hypotenuse(*a) # the star operator will magically convert an Array into a "tuple"
-
-both = men + women
-
-# In Ruby, all objects are references, so the same problem arises; we then return a new object
-nums = [1.4, 3.5, 6.7]
-def int_all(n)
- n.collect { |v| v.to_i }
-end
-ints = int_all(nums)
-
-nums = [1.4, 3.5, 6.7]
-def trunc_em(n)
- n.collect! { |v| v.to_i } # the bang-version of collect modifies the object
-end
-trunc_em(nums)
-
-# Ruby has two chomp version:
-# ``chomp'' chomps the record separator and returns what's expected
-# ``chomp!'' does the same but also modifies the parameter object
-
-
-# @@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/bench/example.rubylex b/bench/example.rubylex
deleted file mode 100644
index b3cdfbe..0000000
--- a/bench/example.rubylex
+++ /dev/null
Binary files differ
diff --git a/bench/example.scheme b/bench/example.scheme
deleted file mode 100644
index 4cb9c18..0000000
--- a/bench/example.scheme
+++ /dev/null
@@ -1,38 +0,0 @@
-
-("")
-(string=? "K. Harper, M.D." ;; Taken from Section 6.3.3. (Symbols) of the R5RS
- (symbol->string
- (string->symbol "K. Harper, M.D.")))
-;; BEGIN Factorial
-(define factorial
- (lambda (n)
- (if (= n 1)
- 1
- (* n (factorial (- n 1))))))
-;; END Factorial
-
- ;; BEGIN Square
- (define square
- (lambda (n) ;; My first lambda
- (if (= n 0)
- 0
- ;; BEGIN Recursive_Call
- (+ (square (- n 1))
- (- (+ n n) 1)))))
- ;; END Recursive_Call
- ;; END Square
-
-;;LIST OF NUMBERS
-(#b-1111 #xffa12 #o755 #o-755 +i -i +2i -2i 3+4i 1.6440287493492101i+2 1.344 3/4 #i23/70)
-
-;;a vector
-#('(1 2 3) #\\a 3 #t #f)
-
-;;macros (USELESS AND INCORRECT, JUST TO CHECK THAT IDENTIFIERS ARE RECOGNIZED RIGHT)
-(syntax-case ()
- ((_ name field ...)
- (with-syntax
- ((constructor (gen-id (syntax name) "make-" (syntax name)))
- (predicate (gen-id (syntax name) (syntax name) "?"))
- ((access ...)
- (map (lambda (x) (gen-id x "set-" (syntax name) "-" x "!")))))))) \ No newline at end of file
diff --git a/bench/example.xhtml b/bench/example.xhtml
deleted file mode 100644
index a08cf75..0000000
--- a/bench/example.xhtml
+++ /dev/null
@@ -1,376 +0,0 @@
-<html>
- <head>
- <script lang="javascript" type="text/javascript">
- // <!--
- function toggleVisible(element) {
- if (element.style.display == 'block') {
- element.style.display = 'none';
- } else {
- element.style.display = 'block';
- }
- return false;
- }
- // -->
- </script>
- <title>Error</title>
- <style>
- .path {
- padding: 5px;
- font-size: 140%;
- background: #ddd;
- }
- .error {
- padding: 5px;
- padding-top: 15px;
- font-size: 140%;
- color: #f00;
- }
- .load {
- padding: 5px;
- color: #555;
- }
- .source {
- border: 1px solid #ccc;
- padding: 10px;
- margin-top: 10px; margin-bottom: 10px;
- }
- h2 {
- padding-left: 5px;
- background: #eee;
- }
- </style>
- </head>
- <body>
- <h1>Error</h1>
-
-<?r
- if Run.mode == :debug
- require 'cgi'
-?>
- <?r for error, path in @context.rendering_errors ?>
- <div class="path"><strong>Path:</strong> #{path}</div>
- <div class="error"><strong>#{CGI.escapeHTML(error.to_s)}</strong></div>
- <div class="load">
- <strong><a href="#{request.uri}">Reload</a></strong> this page.
- Go to the <strong><a href="#{request.referer}">referer</a></strong> or the <strong><a href="/">home page</a></strong>.
- </div>
- <div class="source">
- <?r
- extract = error.source_extract.split("\n")
- ?>
- In file <b>'#{error.hot_file}'</b> #{error.hot_file =~ /\.xhtml$/ ? '(line numbering is aproximate due to template transformation)' : nil}:
- <br /><br />
- <?r
- extract.each_with_index do |line, idx|
- line = sanitize(line)
- if 5 == idx
- ?>
- <div style="background: #eee">#{line}</div>
- <?r else ?>
- <div>#{line}</div>
- <?r
- end
- end
- ?>
- </div>
- <h2><a href="#" onclick="return toggleVisible(document.getElementById('trace'));">Stack Trace</a></h2>
- <div id="trace" style="display: none;">
- <?r error.backtrace.zip(error.source_for_backtrace).each_with_index do |step,step_idx| ?>
- <div><a href="#" onclick="return toggleVisible(document.getElementById('trace_#{step_idx}'));">#{sanitize(step.first)}</a></div>
- <div class="source" id="trace_#{step_idx}" style="display: none;">
- <?r
- extract = step.last.split("\n")
- extract.each_with_index do |line, idx|
- line = sanitize(line)
- if 5 == idx
- ?>
- <div style="background: #eee">#{line}</div>
- <?r else ?>
- <div>#{line}</div>
- <?r
- end
- end
- ?>
- </div>
-
-
- <?r end ?>
- </div>
- <?r end ?>
-
- <h2><a href="#" onclick="document.getElementById('request').style.display = 'block'; return false">Request</a></h2>
- <div id="request" style="display: none">
- <p><strong>Parameters:</strong> #{request.params.reject{ |k,v| k == :__RELOADED__ }.inspect}</p>
- <p><strong>Cookies:</strong> #{request.cookies.inspect}</p>
- <p><strong>Headers:</strong><br />#{request.headers.collect { |k, v| "#{k} => #{v}" }.join('<br />')}</p>
- </div>
-
- <h2><a href="#" onclick="document.getElementById('response').style.display = 'block'; return false">Response</a></h2>
- <div id="response" style="display: none">
- <p><strong>Headers:</strong> #{request.response_headers.inspect}</p>
- <p><strong>Cookies:</strong> #{request.response_cookies.inspect}</p>
- </div>
-
- <h2><a href="#" onclick="document.getElementById('session').style.display = 'block'; return false">Session</a></h2>
- <div id="session" style="display: none">
- <p><strong>Values:</strong> #{session.inspect}</p>
- </div>
-
- <br /><br />
- Powered by <a href="http://www.nitrohq.com">Nitro</a> version #{Nitro::Version}
-<?r end ?>
- </body>
-</html>
-<SystemPage>
- <?r base = "#{@base}/%base%" ?>
- <h1><a href="/"> Home</a> > <a href="#@base">System</a> > <a href="#{base}/list">#{"%plural%".humanize}</a> > Edit #{"%name%".humanize} </h1>
- <?r if @all ?>
- <a href="#{request.uri.gsub(/\/all$/, '')}">Show editable</a>
- #{form_for @obj, :action => "#{base}/save", :cancel => "#{base}/list", :all => true}
- <?r else ?>
- <a href="#{request.uri}/all">Show all</a>
- #{form_for @obj, :action => "#{base}/save", :cancel => "#{base}/list"}
- <?r end ?>
-</SystemPage>
-#{form_for(@%name%)}
-<SystemPage>
- <?r base = "#{@base}/%base%" ?>
- <h1>#{"%plural%".humanize}</h1>
- <h2><a href="#{base}/new">New #{"%name%".humanize}</a></h2>
- <form action="search">
- Search #{"%plural%".humanize}: <input type="text" name="q" />&nbsp;<input type="submit" value="Search" />
- </form>
- <table>
- <?r for obj in @list ?>
- <tr>
- <td width="100%"><a href="#{base}/edit/#{obj.oid}">#{obj.to_s}</a></td>
- <?r if obj.respond_to?(:update_time) ?>
- <td nowrap="1">#{obj.update_time.stamp(:db)}</td>
- <?r end ?>
- <td><a href="#{base}/edit/#{obj.oid}">edit</a></td>
- <td><a href="#{base}/delete/#{obj.oid}">del</a></td>
- </tr>
- <?r end ?>
- </table>
-</SystemPage>
-<SystemPage>
- <?r base = "#{@base}/%base%" ?>
- <h1><a href="/"> Home</a> > <a href="#@base">System</a> > #{"%plural%".humanize}</h1>
- <a href="#{base}/new">New #{"%name%".humanize}</a>
- <p>
- <form action="#{base}/search">
- Search #{"%plural%".humanize}: <input type="text" name="q" />&nbsp;<input type="submit" value="Search" />
- </form>
- </p>
- <table>
- <?r for obj in @list ?>
- <tr>
- <td width="100%"><a href="#{base}/edit/#{obj.oid}">#(obj.to_s)</a></td>
- <?r if obj.respond_to?(:update_time) ?>
- <td nowrap="1">#{obj.update_time.stamp(:db)}</td>
- <?r end ?>
- <td><a href="#{base}/edit/#{obj.oid}">edit</a></td>
- <td><a href="#{base}/delete/#{obj.oid}" onclick="confirm('Are you sure?')">del</a></td>
- </tr>
- <?r end ?>
- </table>
- <div class="pager" if="@pager and @pager.navigation?">
- #{@pager.navigation}
- </div>
-</SystemPage>
-<SystemPage>
- <?r base = "#{@base}/%base%" ?>
- <h1><a href="/"> Home</a> > <a href="#@base">System</a> > <a href="#{base}/list">#{"%plural%".humanize}</a> > New #{"%name%".humanize}</h1>
- <?r if @all ?>
- <a href="#{request.uri.gsub(/\/all$/, '')}">Show editable</a>
- #{form_for @obj, :action => "#{base}/save", :cancel => "#{base}/list", :all => true, :enctype => "multipart/form-data"}
- <?r else ?>
- <a href="#{request.uri}/all">Show all</a>
- #{form_for @obj, :action => "#{base}/save", :cancel => "#{base}/list", :enctype => "multipart/form-data"}
- <?r end ?>
-</SystemPage>
-<SystemPage>
- <?r base = "#{@base}/%base%" ?>
- <h1><a href="/"> Home</a> > <a href="#@base">System</a> > <a href="#{base}/list">#{"%plural%".humanize}</a> > Search for '#@query'</h1>
- <p>
- <form action="#{base}/search">
- Search #{"%plural%".humanize}: <input type="text" name="q" />&nbsp;<input type="submit" value="Search" />
- </form>
- </p>
- <?r if @list.nil? ?>
- <p>Search method is not implemented for this object</p>
- <?r else ?>
- <table>
- <?r for obj in @list ?>
- <tr>
- <td width="100%"><a href="#{base}/edit/#{obj.oid}">#(obj.to_s)</a></td>
- <?r if obj.respond_to?(:update_time) ?>
- <td nowrap="1">#{obj.update_time.stamp(:db)}</td>
- <?r end ?>
- <td><a href="#{base}/edit/#{obj.oid}">edit</a></td>
- <td><a href="#{base}/delete/#{obj.oid}">del</a></td>
- </tr>
- <?r end ?>
- </table>
- <div class="pager" if="@pager and @pager.navigation?">
- #{@pager.navigation}
- </div>
- <?r end ?>
-</SystemPage>
-<SystemPage>
- <?r base = "#{@base}/%base%" ?>
- <h1>View %name%</h1>
- <h2><a href="#{base}/list">List of %plural%</a></h2>
- <code>
- #{@obj.to_yaml}
- </code>
-</SystemPage>
-<strong>Access denied</strong>
-<SystemPage>
- <?r base = "#{@base}/%base%" ?>
- <h1><a href='/'>Home</a> > System</h1>
-
- <h2>Og managed classes</h2>
-
- <table>
- <tr>
- <th>Class</th>
- <th>Count</th>
- <th colspan="2">Cleanup</th>
- <th>Properties</th>
- </tr>
- <?r for c in @classes ?>
- <tr>
- <td><a href="#@base/#{Scaffolding.class_to_path(c).plural}/list">#{c.name}</a></td>
- <td>#{c.count}</td>
- <td><a href="delete_all/#{c.name}" onclick="return confirm('Delete all instances?')">delete</a></td>
- <td><a href="destroy/#{c.name}" onclick="return confirm('Drop the schema?')">destroy</a></td>
- <td width="100%">#{c.properties.values.join(', ')}</td>
- </tr>
- <?r end ?>
- </table>
-
- <h2>System configuration</h2>
-
- <table width="100%">
- <tr>
- <th>Name</th>
- <th>Value</th>
- <th>Type</th>
- <th>Description</th>
- </tr>
- <?r for s in @settings ?>
- <tr>
- <td>#{s.owner}.<strong>#{s.name}</strong></td>
- <td>#{s.value.inspect}</td>
- <td>#{s.type}</td>
- <td>#{s.options[:doc]}</td>
- </tr>
- <?r end ?>
- </table>
-</SystemPage>
-
-<b><?r $include1 = true ?></b>
-<b><?r $include2 = true ?></b>
-<html>
- <b>Test</b>
-
-<?r @tflag = true ?>
-
-<render href="blog/inc1" />
-<render href='blog/inc2' />
-
-</html>
-<html>hello</html>
-Hello #{username}
-
-how do you feel?
-
-Here is your <b>Token</b>: #{token}
-<Page title="Questions and Tips by Tags">
- <div id="left">
- <?r if @tags ?>
- <h1>Questions with Tags: #{@tags.join(" ")}</h1>
-
- <?r if @questions && @questions.size > 0 ?>
- <?r if @qtags ?>
- Too many results for that Tag, please reduce the number by using one of the following Tags:
- #{cloud_of(@qtags)}
- <?r end ?>
- <div class="results">
- <?r @questions.each do |q| ?>
- <h2><a href="/question/#{q.oid}">#{q.question}</a></h2>
- <p>
- <?r excerpt = excerpt_with_words(q.text, @tags) ?>
- #{excerpt}
- </p>
- <p style="float:right;">#{q.answers.size.to_i} answers</p>
- <?r end ?>
- </div>
- <div class="pager">
- #{@qpager.navigation}
- </div>
- <?r else ?>
- <div class="results_none">
- <h2>no question with this/these tag(s) found</h2>
- <p><a href="/ask">Ask a question here.</a></p>
- </div>
- <?r end ?>
-
- <?r if @tips && @tips.size > 0 ?>
- <h1>Tips with Tags: #{@tags.join(" ")}</h1>
- <?r if @ttags ?>
- Too many results for that Tag, please reduce the number by using one of the following Tags:
- #{cloud_of(@ttags)}
- <?r end ?>
- <div class="results">
- <?r @tips.each do |t| ?>
- <h2><a href="/tip/#{t.oid}">#{t.title}</a></h2>
- <p>
- <?r excerpt = excerpt_with_words(t.text, @tags) ?>
- #{excerpt}
- </p>
- <?r end ?>
- </div>
- <div class="pager">
- #{@tpager.navigation}
- </div>
- <?r end ?>
-
- <?r if @tutorials && @tutorials.size > 0 ?>
- <h1>Tutorials with Tags: #{@tags.join(" ")}</h1>
- <?r if @tuttags ?>
- Too many results for that Tag, please reduce the number by using one of the following Tags:
- #{cloud_of(@tuttags)}
- <?r end ?>
- <div class="results">
- <?r @tutorials.each do |t| ?>
- <h2><a href="/tutorial/#{t.oid}">#{t.title}</a></h2>
- <p>
- <?r excerpt = excerpt_with_words(t.text, @tags) ?>
- #{excerpt}
- </p>
- <?r end ?>
- </div>
- <div class="pager">
- #{@tpager.navigation}
- </div>
- <?r end ?>
-
-
- <?r else ?>
- <div class="cloud">
- <?r
- sum = all_tags.inject(0) { |sum, t| sum + t.popularity.to_i }
- ?>
- <?r all_tags.each do |t| ?>
- <a href="/tags/#{t.name}" style="font-size:#{(1+((t.popularity.to_i/sum.to_f)*2)).to_s[0..3]}em;">#{t.name}</a>
- <?r end ?>
- </div> <!-- #cloud -->
- <?r end ?>
- </div> <!-- #left -->
-
- <render href="/right" />
-</Page>
-
-<!-- Copyright © 2006 Kashia Buch (kashia@vfemail.net), Fabian Buch (fabian@fabian-buch.de). All rights reserved. -->
diff --git a/bench/example.xml b/bench/example.xml
deleted file mode 100644
index ba1bb6a..0000000
--- a/bench/example.xml
+++ /dev/null
@@ -1,28137 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Ada" version="1.04" kateversion="2.1" section="Sources" extensions="*.adb;*.ads;*.ada;*.a" mimetype="text/x-adasrc">
- <highlighting>
- <list name="keywords">
- <item> abort </item>
- <item> abs </item>
- <item> abstract </item>
- <item> accept </item>
- <item> access </item>
- <item> aliased </item>
- <item> all </item>
- <item> and </item>
- <item> array </item>
- <item> at </item>
- <item> begin </item>
- <item> body </item>
- <item> constant </item>
- <item> declare </item>
- <item> delay </item>
- <item> delta </item>
- <item> digits </item>
- <item> do </item>
- <item> else </item>
- <item> elsif </item>
- <item> end </item>
- <item> entry </item>
- <item> exception </item>
- <item> exit </item>
- <item> for </item>
- <item> function </item>
- <item> generic </item>
- <item> goto </item>
- <item> in </item>
- <item> is </item>
- <item> limited </item>
- <item> mod </item>
- <item> new </item>
- <item> not </item>
- <item> null </item>
- <item> of </item>
- <item> or </item>
- <item> others </item>
- <item> out </item>
- <item> package </item>
- <item> pragma </item>
- <item> private </item>
- <item> procedure </item>
- <item> protected </item>
- <item> raise </item>
- <item> range </item>
- <item> rem </item>
- <item> record </item>
- <item> renames </item>
- <item> requeue </item>
- <item> return </item>
- <item> reverse </item>
- <item> separate </item>
- <item> subtype </item>
- <item> tagged </item>
- <item> task </item>
- <item> terminate </item>
- <item> then </item>
- <item> type </item>
- <item> until </item>
- <item> use </item>
- <item> when </item>
- <item> while </item>
- <item> with </item>
- <item> xor </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Default">
- <RegExpr attribute="Keyword" context="#stay" String="^\s*if " insensitive="TRUE" beginRegion="Region1"/>
- <StringDetect attribute="Keyword" context="#stay" String="end if" insensitive="TRUE" endRegion="Region1"/>
- <RegExpr attribute="Keyword" context="#stay" String="^\s*case " insensitive="TRUE" beginRegion="Region2"/>
- <StringDetect attribute="Keyword" context="#stay" String="end case" insensitive="TRUE" endRegion="Region2"/>
- <RegExpr attribute="Keyword" context="#stay" String="\sloop\s+" insensitive="TRUE" beginRegion="Region3"/>
- <RegExpr attribute="Keyword" context="#stay" String="\sloop$" insensitive="TRUE" beginRegion="Region3"/>
- <StringDetect attribute="Keyword" context="#stay" String="end loop;" insensitive="TRUE" endRegion="Region3"/>
- <RegExpr attribute="Keyword" context="#stay" String="\sselect\s+" insensitive="TRUE" beginRegion="Region4"/>
- <RegExpr attribute="Keyword" context="#stay" String="\sselect$" insensitive="TRUE" beginRegion="Region4"/>
- <StringDetect attribute="Keyword" context="#stay" String="end select;" insensitive="TRUE" endRegion="Region4"/>
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <Float attribute="Float" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- <RegExpr attribute="Char" context="#stay" String="'.'"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="Comment" char="-" char1="-"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Comment"/>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="Decimal" defStyleNum="dsDecVal" />
- <itemData name="Base-N" defStyleNum="dsBaseN" />
- <itemData name="Float" defStyleNum="dsFloat" />
- <itemData name="Char" defStyleNum="dsChar" />
- <itemData name="String" defStyleNum="dsString" />
- <itemData name="Comment" defStyleNum="dsComment" />
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="--" />
- </comments>
- <keywords casesensitive="0" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Asm6502" version="1.03" kateversion="2.1" section="Sources" extensions="*.asm" mimetype="text/x-asm6502">
- <highlighting>
- <list name = "opcodes6502">
-
-
- </list>
-
-
-
-
-
- <contexts>
- <context name = "Base" attribute = "Normal Text" lineEndContext = "#stay">
-
-
- <RegExpr String= "#define.*$" attribute = "Preprocessor" context="#stay"/>
- <RegExpr String= "#include .*$" attribute = "Preprocessor" context="#stay"/>
- <RegExpr String= ";.*$" attribute = "Comment" context="#stay"/>
- <RegExpr String= "\.byte" attribute = "Data Type" context="#stay"/>
- <RegExpr String= "\.byt" attribute = "Data Type" context="#stay"/>
- <RegExpr String= "\.word" attribute = "Data Type" context="#stay"/>
- <RegExpr String= "\.asc" attribute = "Data Type" context="#stay"/>
- <RegExpr String= "\.dsb" attribute = "Data Type" context="#stay"/>
- <RegExpr String= "\.fopt" attribute = "Data Type" context="#stay"/>
- <RegExpr String= "\.text" attribute = "Data Type" context="#stay"/>
- <RegExpr String= "\.data" attribute = "Data Type" context="#stay"/>
- <RegExpr String= "\.bss" attribute = "Data Type" context="#stay"/>
- <RegExpr String= "\.zero" attribute = "Data Type" context="#stay"/>
- <RegExpr String= "\.align" attribute = "Data Type" context="#stay"/>
- <RegExpr String= "\$[A-Za-z0-9]*" attribute = "Hex" context="#stay"/>
- <RegExpr String= ",x$" attribute = "Keyword" context="#stay" insensitive="TRUE"/>
- <RegExpr String= ",y$" attribute = "Keyword" context="#stay" insensitive="TRUE"/>
- <RegExpr String= "#" attribute = "Keyword" context="#stay" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="TAX" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="ADC" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="AND" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="ASL" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="BCC" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="BCS" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="BEQ" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="BIT" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="BMI" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="BNE" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="BPL" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="BRK" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="BVC" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="BVS" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="CLC" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="CLD" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="CLI" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="CLV" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="CMP" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="CPX" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="CPY" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="DEC" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="DEX" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="DEY" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="EOR" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="INC" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="INX" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="INY" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="JMP" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="JSR" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="LDA" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="LDX" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="LDY" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="LSR" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="NOP" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="ORA" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="PHA" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="PHP" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="PLA" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="PLP" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="ROL" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="ROR" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="RTI" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="RTS" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="SBC" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="SEC" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="SED" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="SEI" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="STA" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="STX" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="STY" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="TAY" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="TSX" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="TXA" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="TXS" insensitive="TRUE"/>
- <StringDetect attribute="Keyword" context="#stay" String="TYA" insensitive="TRUE"/>
-
- <keyword String = "opcodes6502" attribute = "Keyword" context = "#stay" />
- <RegExpr String= "\*=" attribute = "Decimal" context="#stay"/>
- <RangeDetect char = "&quot;" char1 = "&quot;" attribute = "String" context = "#stay"/>
- <AnyChar String = "-+&lt;&gt;=;" attribute = "Operator" context = "#stay"/>
- <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*" beginRegion="Comment"/>
-
-
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar 2">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- </context>
- </contexts>
-
- <itemDatas>
- <itemData name = "Normal Text" defStyleNum = "dsNormal"/>
- <itemData name = "Keyword" defStyleNum = "dsKeyword"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name = "String" defStyleNum = "dsString"/>
- <itemData name = "Comment" defStyleNum = "dsComment"/>
- <itemData name = "Substitution" defStyleNum = "dsOthers"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- <itemData name = "Parameter" defStyleNum = "dsOthers"/>
- <itemData name = "Operator" defStyleNum = "dsOthers"/>
- <itemData name = "Command" defStyleNum = "dsNormal"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start=";"/>
- <comment name="multiLine" start="/*" end="*/"/>
- </comments>
- <keywords casesensitive="1"/>
- </general>
-</language>
-
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="AWK" version="0.1" kateversion="2.1" section="Scripts" extensions="*.awk" mimetype="text/x-awk">
- <highlighting>
- <list name="keywords">
- <item>BEGIN</item>
- <item>END</item>
- <item>if</item>
- <item>else</item>
- <item>while</item>
- <item>do</item>
- <item>for</item>
- <item>in</item>
- <item>continue</item>
- <item>break</item>
- <item>print</item>
- <item>printf</item>
- <item>getline</item>
- <item>function</item>
- <item>return</item>
- <item>next</item>
- <item>exit</item>
- </list>
- <list name="builtins">
- <item>ARGC</item>
- <item>ARGV</item>
- <item>CONVFMT</item>
- <item>ENVIRON</item>
- <item>FILENAME</item>
- <item>FNR</item>
- <item>FS</item>
- <item>NF</item>
- <item>NR</item>
- <item>OFMT</item>
- <item>OFS</item>
- <item>ORS</item>
- <item>RS</item>
- <item>RSTART</item>
- <item>RLENGTH</item>
- <item>SUBSEP</item>
- </list>
- <list name="functions">
- <item>gsub</item>
- <item>index</item>
- <item>length</item>
- <item>match</item>
- <item>split</item>
- <item>sprintf</item>
- <item>sub</item>
- <item>substr</item>
- <item>tolower</item>
- <item>toupper</item>
- <item>atan2</item>
- <item>cos</item>
- <item>exp</item>
- <item>int</item>
- <item>log</item>
- <item>rand</item>
- <item>sin</item>
- <item>sqrt</item>
- <item>srand</item>
- <item>close</item>
- <item>fflush</item>
- <item>system</item>
- </list>
- <contexts>
- <context name="Base" attribute="Normal" lineEndContext="#stay">
- <keyword String="keywords" attribute="Keyword" context="#stay"/>
- <keyword String="builtins" attribute="Builtin" context="#stay"/>
- <keyword String="functions" attribute="Function" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- <Float attribute="Float" context="#stay"/>
- <RegExpr String="\$[A-Za-z0-9_]+" attribute="Field" context="#stay"/>
- <DetectChar char="&quot;" attribute="String" context="String"/>
- <DetectChar char="/" attribute="Pattern" context="Pattern"/>
- <RegExpr String="#.*$" attribute="Comment" context="#stay"/>
- </context>
- <context name="String" attribute="String" lineEndContext="#stay">
- <DetectChar char="&quot;" attribute="String" context="#pop"/>
- <HlCStringChar attribute="String" context="#stay"/>
- </context>
- <context name="Pattern" attribute="Pattern" lineEndContext="#stay">
- <DetectChar char="/" attribute="Pattern" context="#pop"/>
- <RegExpr String="\\." attribute="Pattern" context="#stay"/>
- </context>
- <context name="Field" attribute="Field" lineEndContext="#stay">
- <RegExpr String="\$[A-Za-z0-9_]+" attribute="Field" context="#pop"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Builtin" defStyleNum="dsDataType"/>
- <itemData name="Function" defStyleNum="dsKeyword"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Pattern" defStyleNum="dsString"/>
- <itemData name="Field" defStyleNum="dsOthers"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="#"/>
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Bash" version="1.08" kateversion="2.2" section="Scripts" extensions="*.sh" mimetype="application/x-shellscript">
- <highlighting>
- <list name = "keywords">
- <item> break </item>
- <item> case </item>
- <item> else </item>
- <item> esac </item>
- <item> exit </item>
- <item> export </item>
- <item> for </item>
- <item> function </item>
- <item> in </item>
- <item> return </item>
- <item> select </item>
- <item> then </item>
- <item> until </item>
- <item> while </item>
- <item> . </item>
- <item> done </item>
- <item> do </item>
- <item> elif </item>
- <item> fi </item>
- <item> if </item>
-
- </list>
- <list name = "commands">
- <item> cp </item>
- <item> date </item>
- <item> echo </item>
- <item> eval </item>
- <item> dcop </item>
- <item> dcopstart </item>
- <item> dcopfind </item>
- </list>
- <contexts>
- <context name = "Base" attribute = "Normal Text" lineEndContext = "#stay">
- <RegExpr attribute="Keyword" context="#stay" String="\bdone\b" insensitive="TRUE" endRegion="dodone1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\bdo\b" insensitive="TRUE" beginRegion="dodone1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\belif\b" insensitive="TRUE" beginRegion="iffi1" endRegion="iffi1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\bif\b" insensitive="TRUE" beginRegion="iffi1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\bfi\b" insensitive="TRUE" endRegion="iffi1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\bcase\b" insensitive="TRUE" beginRegion="case1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\besac\b" insensitive="TRUE" endRegion="case1"/>
- <RegExpr attribute="Keyword" context="#stay" String="^[^()]+\)" insensitive="TRUE" beginRegion="subcase1"/>
- <StringDetect attribute="Keyword" context="#stay" String=";;" insensitive="TRUE" endRegion="subcase1"/>
- <DetectChar attribute="Keyword" context="#stay" char="{" beginRegion="func1"/>
- <DetectChar attribute="Keyword" context="#stay" char="}" endRegion="func1"/>
-
- <keyword String = "keywords" attribute = "Keyword" context = "#stay"/>
- <keyword String = "commands" attribute = "Command" context = "#stay"/>
- <Int attribute = "Decimal" context = "#stay"/>
- <RegExpr String = "\$[A-Za-z0-9_?{}!]+" attribute = "Parameter" context = "#stay"/>
- <RangeDetect char = "&quot;" char1 = "&quot;" attribute = "String" context = "#stay"/>
- <AnyChar String = "|&lt;&gt;=;" attribute = "Operator" context = "#stay"/>
- <DetectChar char="'" attribute = "String" context = "Single Quote"/>
- <DetectChar char="`" attribute = "Substitution" context = "Substitution"/>
- <Detect2Chars attribute = "Normal Text" context = "#stay" char = "\" char1 = "#"/>
- <RegExpr String= "#.*$" attribute = "Comment" context="#stay"/>
-
- </context>
- <context name = "String" attribute = "String" lineEndContext="#stay">
- <StringDetect String = "\\" attribute = "String" context = "#stay"/>
- <StringDetect String = "\&quot;" attribute = "String" context = "#stay"/>
- <DetectChar char = "&quot;" attribute = "String" context = "#pop"/>
- </context>
- <context name = "Single Quote" attribute = "String" lineEndContext="#stay">
- <StringDetect String = "\\" attribute = "String" context = "#stay"/>
- <StringDetect String = "\'" attribute = "String" context = "#stay"/>
- <DetectChar char = "'" attribute = "String" context = "#pop"/>
- </context>
- <context name = "Substitution" attribute = "Substitution" lineEndContext="#stay">
- <StringDetect String = "\\" attribute = "String" context = "#stay"/>
- <StringDetect String = "\`" attribute = "String" context = "#stay"/>
- <DetectChar char = "`" attribute = "Substitution" context = "#pop"/>
- </context>
- <context name = "Parameter" attribute = "Parameter" lineEndContext="#stay">
- <RegExpr String = "\$[A-Za-z0-9_?]+" attribute = "Parameter" context="#pop"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name = "Normal Text" defStyleNum = "dsNormal"/>
- <itemData name = "Keyword" defStyleNum = "dsKeyword"/>
- <itemData name = "Decimal" defStyleNum = "dsDecVal"/>
- <itemData name = "Float" defStyleNum = "dsFloat"/>
- <itemData name = "Char" defStyleNum = "dsChar"/>
- <itemData name = "String" defStyleNum = "dsString"/>
- <itemData name = "Comment" defStyleNum = "dsComment"/>
- <itemData name = "Substitution" defStyleNum = "dsOthers"/>
- <itemData name = "Parameter" defStyleNum = "dsOthers"/>
- <itemData name = "Operator" defStyleNum = "dsOthers"/>
- <itemData name = "Command" defStyleNum = "dsNormal"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="#"/>
- </comments>
- <keywords casesensitive="1"/>
- </general>
-</language>
-
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language>
-<language name="BibTeX" version="0.1" extensions="*.bib" section="Markup" mimetype="text/x-bib" casesensitive="1">
- <highlighting>
- <contexts>
- <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
- <DetectChar char="@" attribute="Bib Item" context="Bib Item" />
- <DetectChar char="%" attribute="Comment" context="Comment"/>
- </context>
-
- <context name="Bib Item" attribute="Bib Item" lineEndContext="#stay">
- <DetectChar char="{" attribute="Normal Text" context="Ref Key" />
- <DetectChar char="%" attribute="Comment" context="Comment"/>
- </context>
-
- <context name="Ref Key" attribute="Ref Key" lineEndContext="#stay">
- <DetectChar char="," attribute="Normal Text" context="Keyword" />
- <DetectChar char="%" attribute="Comment" context="Comment"/>
- </context>
-
- <context name="Keyword" attribute="Keyword" lineEndContext="#stay">
- <RegExpr String="\\." attribute="Keyword" context="#stay"/>
- <DetectChar char="@" attribute="Bib Item" context="Bib Item"/>
- <DetectChar char="=" attribute="Normal Text" context="#stay"/>
- <DetectChar char="," attribute="Normal Text" context="#stay"/>
- <DetectChar char='"' attribute="Value" context="Value"/>
- <DetectChar char="%" attribute="Comment" context="Comment"/>
- </context>
-
- <context name="Value" attribute="Value" lineEndContext="#stay">
- <Detect2Chars char="\" char1='"' attribute="Value" context="#stay"/>
- <DetectChar char='"' attribute="Value" context="Keyword"/>
- </context>
-
- <context name="Comment" attribute="5" lineEndContext="#pop">
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Bib Item" defStyleNum="dsNormal" color="#0000ff" selColor="#ffff00" bold="1" italic="0"/>
- <itemData name="Keyword" defStyleNum="dsNormal" color="#000000" selColor="#dddddd" bold="0" italic="0"/>
- <itemData name="Value" defStyleNum="dsNormal" color="#aa5500" selColor="#22aaff" bold="0" italic="0"/>
- <itemData name="Ref Key" defStyleNum="dsNormal" color="#007700" selColor="#00aa00" bold="1" italic="0"/>
- <itemData name="Comment" defStyleNum="dsNormal" color="#aaaaaa" selColor="#222222" bold="0" italic="0"/>
- </itemDatas>
- </highlighting><general>
- <comments>
- <comment name="singleLine" start="%" />
- </comments>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="C" version="1.09" kateversion="2.1" section="Sources" extensions="*.c;*.C;*.h" mimetype="text/x-csrc;text/x-c++src;text/x-chdr" priority="5">
- <highlighting>
- <list name="keywords">
- <item> break </item>
- <item> case </item>
- <item> continue </item>
- <item> default </item>
- <item> do </item>
- <item> else </item>
- <item> enum </item>
- <item> extern </item>
- <item> for </item>
- <item> goto </item>
- <item> if </item>
- <item> inline </item>
- <item> return </item>
- <item> sizeof </item>
- <item> struct </item>
- <item> switch </item>
- <item> typedef </item>
- <item> union </item>
- <item> while </item>
- </list>
- <list name="types">
- <item> auto </item>
- <item> char </item>
- <item> const </item>
- <item> double </item>
- <item> float </item>
- <item> int </item>
- <item> long </item>
- <item> register </item>
- <item> restrict </item>
- <item> short </item>
- <item> signed </item>
- <item> static </item>
- <item> unsigned </item>
- <item> void </item>
- <item> volatile </item>
- <item> _Imaginary </item>
- <item> _Complex </item>
- <item> _Bool </item>
- </list>
- <list name="attention">
- <item> FIXME </item>
- <item> TODO </item>
- <item> ### </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <DetectChar attribute="Symbol" context="#stay" char="{" beginRegion="Brace1" />
- <DetectChar attribute="Symbol" context="#stay" char="}" endRegion="Brace1" />
- <Float attribute="Float" context="#stay">
- <AnyChar String="fF" attribute="Float" context="#stay"/>
- </Float>
- <HlCOct attribute="Octal" context="#stay"/>
- <HlCHex attribute="Hex" context="#stay"/>
- <Int attribute="Decimal" context="#stay" >
- <StringDetect attribute="Decimal" context="#stay" String="ULL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LUL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LLU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="UL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="U" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="L" insensitive="TRUE"/>
- </Int>
- <HlCChar attribute="Char" context="#stay"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*" beginRegion="Comment"/>
- <StringDetect attribute="Preprocessor" context="Outscoped" String="#if 0" insensitive="FALSE"/>
- <DetectChar attribute="Preprocessor" context="Preprocessor" char="#"/>
- <RegExpr attribute="Function" context="#stay" String="\b[_\w][_\w\d]*(?=[\s]*[(])" />
- <RegExpr attribute="Symbol" context="Member" String="[.]{1,1}" />
- <AnyChar attribute="Symbol" context="#stay" String=":!%&amp;()+,-/.*&lt;=&gt;?[]|~^&#59;"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Member">
- <RegExpr attribute="Function" context="#pop" String="\b[_\w][_\w\d]*(?=[\s]*)" />
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Commentar 1">
- <keyword attribute="Decimal" context="#stay" String="attention" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar 2">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- <keyword attribute="Decimal" context="#stay" String="attention" />
- </context>
- <context attribute="Preprocessor" lineEndContext="#pop" name="Preprocessor">
- <LineContinue attribute="Preprocessor" context="#stay"/>
- <RegExpr attribute="Preprocessor" context="Define" String="define.*((?=\\))"/>
- <RegExpr attribute="Preprocessor" context="#stay" String="define.*"/>
- <RangeDetect attribute="Prep. Lib" context="#stay" char="&quot;" char1="&quot;"/>
- <RangeDetect attribute="Prep. Lib" context="#stay" char="&lt;" char1="&gt;"/>
- <Detect2Chars attribute="Comment" context="Commentar/Preprocessor" char="/" char1="*" beginRegion="Comment2"/>
- </context>
- <context attribute="Preprocessor" lineEndContext="#pop" name="Define">
- <LineContinue attribute="Preprocessor" context="#stay"/>
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar/Preprocessor">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment2" />
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Some Context"/>
- <context attribute="Normal Text" lineEndContext="#pop" name="Some Context2"/>
- <context attribute="Comment" lineEndContext="#stay" name="Outscoped" >
- <keyword attribute="Decimal" context="#stay" String="attention" />
- <RegExpr attribute="Comment" context="Outscoped intern" String="^#if" />
- <RegExpr attribute="Preprocessor" context="#pop" String="#endif" />
- <RegExpr attribute="Preprocessor" context="#pop" String="#else" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Outscoped intern">
- <RegExpr attribute="Comment" context="Outscoped intern" String="#if" />
- <RegExpr attribute="Comment" context="#pop" String="#endif" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Function" defStyleNum="dsKeyword" color="#000080" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- <itemData name="Prep. Lib" defStyleNum="dsOthers"/> <!--,Qt::darkYellow,Qt::yellow,false,false)); -->
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="ChangeLog" version="1.01" kateversion="2.1" section="Other" extensions="ChangeLog" mimetype="">
- <highlighting>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <RegExpr attribute="Keyword" context="#stay" String="^\d\d\d\d\s*-\s*\d\d\s*-\s*\d\d.*$"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Identifier" defStyleNum="dsOthers"/>
- <itemData name="Types" defStyleNum="dsDataType"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Cisco" version="1.09" kateversion="2.2" section="Scripts"
- extensions="*.cis" mimetype="text/cisco"
- author="Raphaël GRAPINET" license="LGPL">
- <highlighting>
- <list name = "commands">
- <item> aaa </item>
- <item> access-list </item>
- <item> address </item>
- <item> alias </item>
- <item> arp </item>
- <item> async-bootp </item>
- <item> banner </item>
- <item> boot </item>
- <item> bridge </item>
- <item> buffers </item>
- <item> busy-message </item>
- <item> call-history-mib </item>
- <item> cdp </item>
- <item> chat-script </item>
- <item> class-map </item>
- <item> clock </item>
- <item> cns </item>
- <item> config-register </item>
- <item> controller </item>
- <item> crypto </item>
- <item> default </item>
- <item> default-value </item>
- <item> dialer </item>
- <item> dialer-list </item>
- <item> dnsix-dmdp </item>
- <item> dnsix-nat </item>
- <item> downward-compatible-config </item>
- <item> enable </item>
- <item> end </item>
- <item> exception </item>
- <item> exit </item>
- <item> file </item>
- <item> frame-relay </item>
- <item> help </item>
- <item> hostname </item>
- <item> interface </item>
- <item> ip </item>
- <item> isdn </item>
- <item> isdn-mib </item>
- <item> kerberos </item>
- <item> key </item>
- <item> line </item>
- <item> logging </item>
- <item> login-string </item>
- <item> map-class </item>
- <item> map-list </item>
- <item> memory-size </item>
- <item> menu </item>
- <item> modemcap </item>
- <item> multilink </item>
- <item> netbios </item>
- <item> no </item>
- <item> ntp </item>
- <item> partition </item>
- <item> policy-map </item>
- <item> priority-list </item>
- <item> privilege </item>
- <item> process-max-time </item>
- <item> prompt </item>
- <item> queue-list </item>
- <item> resume-string </item>
- <item> rlogin </item>
- <item> rmon </item>
- <item> route-map </item>
- <item> router </item>
- <item> rtr </item>
- <item> scheduler </item>
- <item> service </item>
- <item> snmp-server </item>
- <item> sntp </item>
- <item> stackmaker </item>
- <item> state-machine </item>
- <item> subscriber-policy </item>
- <item> tacacs-server </item>
- <item> template </item>
- <item> terminal-queue </item>
- <item> tftp-server </item>
- <item> time-range </item>
- <item> username </item>
- <item> virtual-profile </item>
- <item> virtual-template </item>
- <item> vpdn </item>
- <item> vpdn-group </item>
- <item> x25 </item>
- <item> x29 </item>
- </list>
- <list name = "parameters">
- <item> accounting </item>
- <item> accounting-list </item>
- <item> accounting-threshold </item>
- <item> accounting-transits </item>
- <item> address-pool </item>
- <item> as-path </item>
- <item> audit </item>
- <item> auth-proxy </item>
- <item> authentication </item>
- <item> authorization </item>
- <item> bgp-community </item>
- <item> bootp </item>
- <item> cef </item>
- <item> classless </item>
- <item> community-list </item>
- <item> default-gateway </item>
- <item> default-network </item>
- <item> dhcp </item>
- <item> dhcp-server </item>
- <item> domain-list </item>
- <item> domain-lookup </item>
- <item> domain-name </item>
- <item> dvmrp </item>
- <item> exec-callback </item>
- <item> extcommunity-list </item>
- <item> finger </item>
- <item> flow-aggregation </item>
- <item> flow-cache </item>
- <item> flow-export </item>
- <item> forward-protocol </item>
- <item> ftp </item>
- <item> gratuitous-arps </item>
- <item> host </item>
- <item> host-routing </item>
- <item> hp-host </item>
- <item> http </item>
- <item> icmp </item>
- <item> inspect </item>
- <item> local </item>
- <item> mrm </item>
- <item> mroute </item>
- <item> msdp </item>
- <item> multicast </item>
- <item> multicast-routing </item>
- <item> name-server </item>
- <item> nat </item>
- <item> new-model </item>
- <item> ospf </item>
- <item> password </item>
- <item> password-encryption </item>
- <item> pgm </item>
- <item> pim </item>
- <item> port-map </item>
- <item> prefix-list </item>
- <item> radius </item>
- <item> rcmd </item>
- <item> reflexive-list </item>
- <item> route </item>
- <item> routing </item>
- <item> rsvp </item>
- <item> rtcp </item>
- <item> sap </item>
- <item> sdr </item>
- <item> security </item>
- <item> source-route </item>
- <item> subnet-zero </item>
- <item> tacacs </item>
- <item> tcp </item>
- <item> tcp-small-servers </item>
- <item> telnet </item>
- <item> tftp </item>
- <item> timestamps </item>
- <item> udp-small-servers </item>
- <item> vrf </item>
- <item> wccp </item>
- </list>
- <list name = "options">
- <item> accounting </item>
- <item> accounting-list </item>
- <item> accounting-threshold </item>
- <item> accounting-transits </item>
- <item> address-pool </item>
- <item> as-path </item>
- <item> audit </item>
- <item> auth-proxy </item>
- <item> authentication </item>
- <item> authorization </item>
- <item> bgp-community </item>
- <item> bootp </item>
- <item> cef </item>
- <item> classless </item>
- <item> community-list </item>
- <item> default-gateway </item>
- <item> default-network </item>
- <item> dhcp </item>
- <item> dhcp-server </item>
- <item> domain-list </item>
- <item> domain-lookup </item>
- <item> domain-name </item>
- <item> dvmrp </item>
- <item> exec-callback </item>
- <item> extcommunity-list </item>
- <item> finger </item>
- <item> flow-aggregation </item>
- <item> flow-cache </item>
- <item> flow-export </item>
- <item> forward-protocol </item>
- <item> ftp </item>
- <item> gratuitous-arps </item>
- <item> host </item>
- <item> host-routing </item>
- <item> hp-host </item>
- <item> http </item>
- <item> icmp </item>
- <item> inspect </item>
- <item> local </item>
- <item> mrm </item>
- <item> mroute </item>
- <item> msdp </item>
- <item> multicast </item>
- <item> multicast-routing </item>
- <item> name-server </item>
- <item> nat </item>
- <item> new-model </item>
- <item> ospf </item>
- <item> password </item>
- <item> password-encryption </item>
- <item> pgm </item>
- <item> pim </item>
- <item> port-map </item>
- <item> prefix-list </item>
- <item> radius </item>
- <item> rcmd </item>
- <item> reflexive-list </item>
- <item> route </item>
- <item> routing </item>
- <item> rsvp </item>
- <item> rtcp </item>
- <item> sap </item>
- <item> sdr </item>
- <item> security </item>
- <item> source-route </item>
- <item> subnet-zero </item>
- <item> tacacs </item>
- <item> tcp </item>
- <item> tcp-small-servers </item>
- <item> telnet </item>
- <item> tftp </item>
- <item> timestamps </item>
- <item> udp-small-servers </item>
- <item> vrf </item>
- <item> wccp </item>
- </list>
- <contexts>
- <context name = "Base" attribute = "Normal Text" lineEndContext = "#stay">
- <RegExpr attribute="Keyword" context="#stay" String="\bdone\b" insensitive="TRUE" endRegion="dodone1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\bdo\b" insensitive="TRUE" beginRegion="dodone1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\belif\b" insensitive="TRUE" beginRegion="iffi1" endRegion="iffi1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\bif\b" insensitive="TRUE" beginRegion="iffi1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\bfi\b" insensitive="TRUE" endRegion="iffi1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\bcase\b" insensitive="TRUE" beginRegion="case1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\besac\b" insensitive="TRUE" endRegion="case1"/>
- <RegExpr attribute="Keyword" context="#stay" String="^[^()]+\)" insensitive="TRUE" beginRegion="subcase1"/>
- <StringDetect attribute="Keyword" context="#stay" String=";;" insensitive="TRUE" endRegion="subcase1"/>
- <DetectChar attribute="Keyword" context="#stay" char="{" beginRegion="func1"/>
- <DetectChar attribute="Keyword" context="#stay" char="}" endRegion="func1"/>
-
- <keyword String = "commands" attribute = "Command" context = "#stay"/>
- <keyword String = "parameters" attribute = "Parameter" context = "#stay"/>
- <keyword String = "options" attribute = "Keyword" context = "#stay"/>
- <Int attribute = "Decimal" context = "#stay"/>
- <RegExpr String = "\$[A-Za-z0-9_?{}!]+" attribute = "Parameter" context = "#stay"/>
- <RangeDetect char = "&quot;" char1 = "&quot;" attribute = "String" context = "#stay"/>
- <AnyChar String = "|&lt;&gt;=;" attribute = "Operator" context = "#stay"/>
- <DetectChar char="'" attribute = "String" context = "Single Quote"/>
- <DetectChar char="`" attribute = "Substitution" context = "Substitution"/>
- <Detect2Chars attribute = "Normal Text" context = "#stay" char = "\" char1 = "#"/>
- <RegExpr String= "#.*$" attribute = "Comment" context="#stay"/>
-
- </context>
- <context name = "String" attribute = "String" lineEndContext="#stay">
- <StringDetect String = "\\" attribute = "String" context = "#stay"/>
- <StringDetect String = "\&quot;" attribute = "String" context = "#stay"/>
- <DetectChar char = "&quot;" attribute = "String" context = "#pop"/>
- </context>
- <context name = "Single Quote" attribute = "String" lineEndContext="#stay">
- <StringDetect String = "\\" attribute = "String" context = "#stay"/>
- <StringDetect String = "\'" attribute = "String" context = "#stay"/>
- <DetectChar char = "'" attribute = "String" context = "#pop"/>
- </context>
- <context name = "Substitution" attribute = "Substitution" lineEndContext="#stay">
- <StringDetect String = "\\" attribute = "String" context = "#stay"/>
- <StringDetect String = "\`" attribute = "String" context = "#stay"/>
- <DetectChar char = "`" attribute = "Substitution" context = "#pop"/>
- </context>
- <context name = "Parameter" attribute = "Parameter" lineEndContext="#stay">
- <RegExpr String = "\$[A-Za-z0-9_?]+" attribute = "Parameter" context="#pop"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name = "Normal Text" defStyleNum = "dsNormal"/>
- <itemData name = "Keyword" defStyleNum = "dsKeyword"/>
- <itemData name = "Decimal" defStyleNum = "dsDecVal"/>
- <itemData name = "Float" defStyleNum = "dsFloat"/>
- <itemData name = "Char" defStyleNum = "dsChar"/>
- <itemData name = "String" defStyleNum = "dsString"/>
- <itemData name = "Comment" defStyleNum = "dsComment"/>
- <itemData name = "Substitution" defStyleNum = "dsOthers"/>
- <itemData name = "Parameter" defStyleNum = "dsOthers"/>
- <itemData name = "Operator" defStyleNum = "dsOthers"/>
- <itemData name = "Command" defStyleNum = "dsNormal"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="!"/>
- </comments>
- <keywords casesensitive="0"/>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="ColdFusion" version="1.03" kateversion="2.1" section="Markup" extensions="*.cfm;*.cfc;*.cfml;*.dbm" mimetype="text/x-coldfusion">
-
- <highlighting>
-
- <list name="Script Keywords">
-
- <item> if </item>
- <item> else </item>
- <item> for </item>
- <item> in </item>
- <item> while </item>
- <item> do </item>
- <item> continue </item>
- <item> break </item>
- <item> with </item>
- <item> try </item>
- <item> catch </item>
- <item> switch </item>
- <item> case </item>
- <item> new </item>
- <item> var </item>
- <item> function </item>
- <item> return </item>
- <item> this </item>
- <item> delete </item>
- <item> true </item>
- <item> false </item>
- <item> void </item>
- <item> throw </item>
- <item> typeof </item>
- <item> const </item>
- <item> default </item>
-
- </list>
-
- <list name="Script Objects">
-
- <item> Anchor </item>
- <item> Applet </item>
- <item> Area </item>
- <item> Array </item>
- <item> Boolean </item>
- <item> Button </item>
- <item> Checkbox </item>
- <item> Date </item>
- <item> Document </item>
- <item> Event </item>
- <item> FileUpload </item>
- <item> Form </item>
- <item> Frame </item>
- <item> Function </item>
- <item> Hidden </item>
- <item> History </item>
- <item> Image </item>
- <item> Layer </item>
- <item> Linke </item>
- <item> Location </item>
- <item> Math </item>
- <item> Navigator </item>
- <item> Number </item>
- <item> Object </item>
- <item> Option </item>
- <item> Password </item>
- <item> Radio </item>
- <item> RegExp </item>
- <item> Reset </item>
- <item> Screen </item>
- <item> Select </item>
- <item> String </item>
- <item> Submit </item>
- <item> Text </item>
- <item> Textarea </item>
- <item> Window </item>
-
- </list>
-
- <list name="Script Methods">
-
- <item> abs </item>
- <item> acos </item>
- <item> alert </item>
- <item> anchor </item>
- <item> apply </item>
- <item> asin </item>
- <item> atan </item>
- <item> atan2 </item>
- <item> back </item>
- <item> blur </item>
- <item> call </item>
- <item> captureEvents </item>
- <item> ceil </item>
- <item> charAt </item>
- <item> charCodeAt </item>
- <item> clearInterval </item>
- <item> clearTimeout </item>
- <item> click </item>
- <item> close </item>
- <item> compile </item>
- <item> concat </item>
- <item> confirm </item>
- <item> cos </item>
- <item> disableExternalCapture </item>
- <item> enableExternalCapture </item>
- <item> eval </item>
- <item> exec </item>
- <item> exp </item>
- <item> find </item>
- <item> floor </item>
- <item> focus </item>
- <item> forward </item>
- <item> fromCharCode </item>
- <item> getDate </item>
- <item> getDay </item>
- <item> getFullYear </item>
- <item> getHours </item>
- <item> getMilliseconds </item>
- <item> getMinutes </item>
- <item> getMonth </item>
- <item> getSeconds </item>
- <item> getSelection </item>
- <item> getTime </item>
- <item> getTimezoneOffset </item>
- <item> getUTCDate </item>
- <item> getUTCDay </item>
- <item> getUTCFullYear </item>
- <item> getUTCHours </item>
- <item> getUTCMilliseconds </item>
- <item> getUTCMinutes </item>
- <item> getUTCMonth </item>
- <item> getUTCSeconds </item>
- <item> go </item>
- <item> handleEvent </item>
- <item> home </item>
- <item> indexOf </item>
- <item> javaEnabled </item>
- <item> join </item>
- <item> lastIndexOf </item>
- <item> link </item>
- <item> load </item>
- <item> log </item>
- <item> match </item>
- <item> max </item>
- <item> min </item>
- <item> moveAbove </item>
- <item> moveBelow </item>
- <item> moveBy </item>
- <item> moveTo </item>
- <item> moveToAbsolute </item>
- <item> open </item>
- <item> parse </item>
- <item> plugins.refresh </item>
- <item> pop </item>
- <item> pow </item>
- <item> preference </item>
- <item> print </item>
- <item> prompt </item>
- <item> push </item>
- <item> random </item>
- <item> releaseEvents </item>
- <item> reload </item>
- <item> replace </item>
- <item> reset </item>
- <item> resizeBy </item>
- <item> resizeTo </item>
- <item> reverse </item>
- <item> round </item>
- <item> routeEvent </item>
- <item> scrollBy </item>
- <item> scrollTo </item>
- <item> search </item>
- <item> select </item>
- <item> setDate </item>
- <item> setFullYear </item>
- <item> setHours </item>
- <item> setInterval </item>
- <item> setMilliseconds </item>
- <item> setMinutes </item>
- <item> setMonth </item>
- <item> setSeconds </item>
- <item> setTime </item>
- <item> setTimeout </item>
- <item> setUTCDate </item>
- <item> setUTCFullYear </item>
- <item> setUTCHours </item>
- <item> setUTCMilliseconds </item>
- <item> setUTCMinutes </item>
- <item> setUTCMonth </item>
- <item> setUTCSeconds </item>
- <item> shift </item>
- <item> sin </item>
- <item> slice </item>
- <item> sort </item>
- <item> splice </item>
- <item> split </item>
- <item> sqrt </item>
- <item> stop </item>
- <item> String formatting </item>
- <item> submit </item>
- <item> substr </item>
- <item> substring </item>
- <item> taintEnabled </item>
- <item> tan </item>
- <item> test </item>
- <item> toLocaleString </item>
- <item> toLowerCase </item>
- <item> toSource </item>
- <item> toString </item>
- <item> toUpperCase </item>
- <item> toUTCString </item>
- <item> unshift </item>
- <item> unwatch </item>
- <item> UTC </item>
- <item> valueOf </item>
- <item> watch </item>
- <item> write </item>
- <item> writeln </item>
-
- </list>
-
- <list name="CFSCRIPT Keywords">
-
- <item> break </item>
- <item> case </item>
- <item> catch </item>
- <item> continue </item>
- <item> default </item>
- <item> do </item>
- <item> else </item>
- <item> for </item>
- <item> function </item>
- <item> if </item>
- <item> in </item>
- <item> return </item>
- <item> switch </item>
- <item> try </item>
- <item> var </item>
- <item> while </item>
-
- </list>
-
- <list name="CFSCRIPT Functions">
-
- <item> Abs </item>
- <item> ACos </item>
- <item> ArrayAppend </item>
- <item> ArrayAvg </item>
- <item> ArrayClear </item>
- <item> ArrayDeleteAt </item>
- <item> ArrayInsertAt </item>
- <item> ArrayIsEmpty </item>
- <item> ArrayLen </item>
- <item> ArrayMax </item>
- <item> ArrayMin </item>
- <item> ArrayNew </item>
- <item> ArrayPrepend </item>
- <item> ArrayResize </item>
- <item> ArraySet </item>
- <item> ArraySort </item>
- <item> ArraySum </item>
- <item> ArraySwap </item>
- <item> ArrayToList </item>
- <item> Asc </item>
- <item> ASin </item>
- <item> Atn </item>
- <item> BitAnd </item>
- <item> BitMaskClear </item>
- <item> BitMaskRead </item>
- <item> BitMaskSet </item>
- <item> BitNot </item>
- <item> BitOr </item>
- <item> BitSHLN </item>
- <item> BitSHRN </item>
- <item> BitXor </item>
- <item> Ceiling </item>
- <item> Chr </item>
- <item> CJustify </item>
- <item> Compare </item>
- <item> CompareNoCase </item>
- <item> Cos </item>
- <item> CreateDate </item>
- <item> CreateDateTime </item>
- <item> CreateObject </item>
- <item> CreateODBCDate </item>
- <item> CreateODBCDateTime </item>
- <item> CreateODBCTime </item>
- <item> CreateTime </item>
- <item> CreateTimeSpan </item>
- <item> CreateUUID </item>
- <item> DateAdd </item>
- <item> DateCompare </item>
- <item> DateConvert </item>
- <item> DateDiff </item>
- <item> DateFormat </item>
- <item> DatePart </item>
- <item> Day </item>
- <item> DayOfWeek </item>
- <item> DayOfWeekAsString </item>
- <item> DayOfYear </item>
- <item> DaysInMonth </item>
- <item> DaysInYear </item>
- <item> DE </item>
- <item> DecimalFormat </item>
- <item> DecrementValue </item>
- <item> Decrypt </item>
- <item> DeleteClientVariable </item>
- <item> DirectoryExists </item>
- <item> DollarFormat </item>
- <item> Duplicate </item>
- <item> Encrypt </item>
- <item> Evaluate </item>
- <item> Exp </item>
- <item> ExpandPath </item>
- <item> FileExists </item>
- <item> Find </item>
- <item> FindNoCase </item>
- <item> FindOneOf </item>
- <item> FirstDayOfMonth </item>
- <item> Fix </item>
- <item> FormatBaseN </item>
- <item> GetAuthUser </item>
- <item> GetBaseTagData </item>
- <item> GetBaseTagList </item>
- <item> GetBaseTemplatePath </item>
- <item> GetClientVariablesList </item>
- <item> GetCurrentTemplatePath </item>
- <item> GetDirectoryFromPath </item>
- <item> GetException </item>
- <item> GetFileFromPath </item>
- <item> GetFunctionList </item>
- <item> GetHttpRequestData </item>
- <item> GetHttpTimeString </item>
- <item> GetK2ServerDocCount </item>
- <item> GetK2ServerDocCountLimit </item>
- <item> GetLocale </item>
- <item> GetMetaData </item>
- <item> GetMetricData </item>
- <item> GetPageContext </item>
- <item> GetProfileSections </item>
- <item> GetProfileString </item>
- <item> GetServiceSettings </item>
- <item> GetTempDirectory </item>
- <item> GetTempFile </item>
- <item> GetTemplatePath </item>
- <item> GetTickCount </item>
- <item> GetTimeZoneInfo </item>
- <item> GetToken </item>
- <item> Hash </item>
- <item> Hour </item>
- <item> HTMLCodeFormat </item>
- <item> HTMLEditFormat </item>
- <item> IIf </item>
- <item> IncrementValue </item>
- <item> InputBaseN </item>
- <item> Insert </item>
- <item> Int </item>
- <item> IsArray </item>
- <item> IsBinary </item>
- <item> IsBoolean </item>
- <item> IsCustomFunction </item>
- <item> IsDate </item>
- <item> IsDebugMode </item>
- <item> IsDefined </item>
- <item> IsK2ServerABroker </item>
- <item> IsK2ServerDocCountExceeded </item>
- <item> IsK2ServerOnline </item>
- <item> IsLeapYear </item>
- <item> IsNumeric </item>
- <item> IsNumericDate </item>
- <item> IsObject </item>
- <item> IsQuery </item>
- <item> IsSimpleValue </item>
- <item> IsStruct </item>
- <item> IsUserInRole </item>
- <item> IsWDDX </item>
- <item> IsXmlDoc </item>
- <item> IsXmlElement </item>
- <item> IsXmlRoot </item>
- <item> JavaCast </item>
- <item> JSStringFormat </item>
- <item> LCase </item>
- <item> Left </item>
- <item> Len </item>
- <item> ListAppend </item>
- <item> ListChangeDelims </item>
- <item> ListContains </item>
- <item> ListContainsNoCase </item>
- <item> ListDeleteAt </item>
- <item> ListFind </item>
- <item> ListFindNoCase </item>
- <item> ListFirst </item>
- <item> ListGetAt </item>
- <item> ListInsertAt </item>
- <item> ListLast </item>
- <item> ListLen </item>
- <item> ListPrepend </item>
- <item> ListQualify </item>
- <item> ListRest </item>
- <item> ListSetAt </item>
- <item> ListSort </item>
- <item> ListToArray </item>
- <item> ListValueCount </item>
- <item> ListValueCountNoCase </item>
- <item> LJustify </item>
- <item> Log </item>
- <item> Log10 </item>
- <item> LSCurrencyFormat </item>
- <item> LSDateFormat </item>
- <item> LSEuroCurrencyFormat </item>
- <item> LSIsCurrency </item>
- <item> LSIsDate </item>
- <item> LSIsNumeric </item>
- <item> LSNumberFormat </item>
- <item> LSParseCurrency </item>
- <item> LSParseDateTime </item>
- <item> LSParseEuroCurrency </item>
- <item> LSParseNumber </item>
- <item> LSTimeFormat </item>
- <item> LTrim </item>
- <item> Max </item>
- <item> Mid </item>
- <item> Min </item>
- <item> Minute </item>
- <item> Month </item>
- <item> MonthAsString </item>
- <item> Now </item>
- <item> NumberFormat </item>
- <item> ParagraphFormat </item>
- <item> ParameterExists </item>
- <item> ParseDateTime </item>
- <item> Pi </item>
- <item> PreserveSingleQuotes </item>
- <item> Quarter </item>
- <item> QueryAddColumn </item>
- <item> QueryAddRow </item>
- <item> QueryNew </item>
- <item> QuerySetCell </item>
- <item> QuotedValueList </item>
- <item> Rand </item>
- <item> Randomize </item>
- <item> RandRange </item>
- <item> REFind </item>
- <item> REFindNoCase </item>
- <item> RemoveChars </item>
- <item> RepeatString </item>
- <item> Replace </item>
- <item> ReplaceList </item>
- <item> ReplaceNoCase </item>
- <item> REReplace </item>
- <item> REReplaceNoCase </item>
- <item> Reverse </item>
- <item> Right </item>
- <item> RJustify </item>
- <item> Round </item>
- <item> RTrim </item>
- <item> Second </item>
- <item> SetEncoding </item>
- <item> SetLocale </item>
- <item> SetProfileString </item>
- <item> SetVariable </item>
- <item> Sgn </item>
- <item> Sin </item>
- <item> SpanExcluding </item>
- <item> SpanIncluding </item>
- <item> Sqr </item>
- <item> StripCR </item>
- <item> StructAppend </item>
- <item> StructClear </item>
- <item> StructCopy </item>
- <item> StructCount </item>
- <item> StructDelete </item>
- <item> StructFind </item>
- <item> StructFindKey </item>
- <item> StructFindValue </item>
- <item> StructGet </item>
- <item> StructInsert </item>
- <item> StructIsEmpty </item>
- <item> StructKeyArray </item>
- <item> StructKeyExists </item>
- <item> StructKeyList </item>
- <item> StructNew </item>
- <item> StructSort </item>
- <item> StructUpdate </item>
- <item> Tan </item>
- <item> TimeFormat </item>
- <item> ToBase64 </item>
- <item> ToBinary </item>
- <item> ToString </item>
- <item> Trim </item>
- <item> UCase </item>
- <item> URLDecode </item>
- <item> URLEncodedFormat </item>
- <item> URLSessionFormat </item>
- <item> Val </item>
- <item> ValueList </item>
- <item> Week </item>
- <item> WriteOutput </item>
- <item> XmlChildPos </item>
- <item> XmlElemNew </item>
- <item> XmlFormat </item>
- <item> XmlNew </item>
- <item> XmlParse </item>
- <item> XmlSearch </item>
- <item> XmlTransform </item>
- <item> Year </item>
- <item> YesNoFormat </item>
-
- </list>
-
- <contexts>
-
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal Text">
- <StringDetect attribute="CF Comment" context="ctxCF Comment" String="&lt;!---" />
- <StringDetect attribute="HTML Comment" context="ctxHTML Comment" String="&lt;!--" />
- <RegExpr attribute="Script Tags" context="ctxCFSCRIPT Tag" String="&lt;[cC][fF][sS][cC][rR][iI][pP][tT]" />
- <RegExpr attribute="Script Tags" context="ctxSCRIPT Tag" String="&lt;[sS][cC][rR][iI][pP][tT]" />
- <RegExpr attribute="Style Tags" context="ctxSTYLE Tag" String="&lt;[sS][tT][yY][lL][eE]" />
- <DetectChar attribute="HTML Entities" context="ctxHTML Entities" char="&amp;" />
- <RegExpr attribute="Custom Tags" context="ctxCustom Tag" String="&lt;\/?[cC][fF]_" />
- <RegExpr attribute="CFX Tags" context="ctxCFX Tag" String="&lt;\/?[cC][fF][xX]_" />
- <RegExpr attribute="CF Tags" context="ctxCF Tag" String="&lt;\/?[cC][fF]" />
- <RegExpr attribute="Table Tags" context="ctxTable Tag" String="&lt;\/?([tT][aAhHbBfFrRdD])|([cC][aA][pP][tT])" />
- <RegExpr attribute="Anchor Tags" context="ctxAnchor Tag" String="&lt;\/?[aA] " />
- <RegExpr attribute="Image Tags" context="ctxImage Tag" String="&lt;\/?[iI][mM][gG] " />
- <RegExpr attribute="Tags" context="ctxTag" String="&lt;!?\/?[a-zA-Z0-9_]+" />
- </context>
-
-
-
- <context name="ctxCFSCRIPT Tag" attribute="Script Tags" lineEndContext="#stay">
- <DetectChar attribute="Script Tags" context="ctxCFSCRIPT Block" char="&gt;" />
- <DetectChar attribute="Normal Text" context="#stay" char="=" />
- <RegExpr attribute="Attribute Values" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Attribute Values" context="#stay" String="'[^']*'" />
- </context>
-
- <context name="ctxSCRIPT Tag" attribute="Script Tags" lineEndContext="#stay">
- <DetectChar attribute="Script Tags" context="ctxSCRIPT Block" char="&gt;" />
- <DetectChar attribute="Normal Text" context="#stay" char="=" />
- <RegExpr attribute="Attribute Values" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Attribute Values" context="#stay" String="'[^']*'" />
- </context>
-
- <context name="ctxSTYLE Tag" attribute="Style Tags" lineEndContext="#stay">
- <DetectChar attribute="Style Tags" context="ctxSTYLE Block" char="&gt;" />
- <DetectChar attribute="Normal Text" context="#stay" char="=" />
- <RegExpr attribute="Attribute Values" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Attribute Values" context="#stay" String="'[^']*'" />
- </context>
-
-
-
- <context name="ctxTag" attribute="Tags" lineEndContext="#stay">
- <DetectChar attribute="Tags" context="#pop" char="&gt;" />
- <DetectChar attribute="Normal Text" context="#stay" char="=" />
- <RegExpr attribute="Attribute Values" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Attribute Values" context="#stay" String="'[^']*'" />
- </context>
-
- <context name="ctxTable Tag" attribute="Table Tags" lineEndContext="#stay">
- <DetectChar attribute="Table Tags" context="#pop" char="&gt;" />
- <DetectChar attribute="Normal Text" context="#stay" char="=" />
- <RegExpr attribute="Attribute Values" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Attribute Values" context="#stay" String="'[^']*'" />
- </context>
-
- <context name="ctxAnchor Tag" attribute="Anchor Tags" lineEndContext="#stay">
- <DetectChar attribute="Anchor Tags" context="#pop" char="&gt;" />
- <DetectChar attribute="Normal Text" context="#stay" char="=" />
- <RegExpr attribute="Attribute Values" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Attribute Values" context="#stay" String="'[^']*'" />
- </context>
-
- <context name="ctxImage Tag" attribute="Image Tags" lineEndContext="#stay">
- <DetectChar attribute="Image Tags" context="#pop" char="&gt;" />
- <DetectChar attribute="Normal Text" context="#stay" char="=" />
- <RegExpr attribute="Attribute Values" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Attribute Values" context="#stay" String="'[^']*'" />
- </context>
-
- <context name="ctxCF Tag" attribute="CF Tags" lineEndContext="#stay">
- <DetectChar attribute="CF Tags" context="#pop" char="&gt;" />
- <DetectChar attribute="Normal Text" context="#stay" char="=" />
- <RegExpr attribute="Attribute Values" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Attribute Values" context="#stay" String="'[^']*'" />
- </context>
-
- <context name="ctxCustom Tag" attribute="Custom Tags" lineEndContext="#stay">
- <DetectChar attribute="Custom Tags" context="#pop" char="&gt;" />
- <DetectChar attribute="Normal Text" context="#stay" char="=" />
- <RegExpr attribute="Attribute Values" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Attribute Values" context="#stay" String="'[^']*'" />
- </context>
-
- <context name="ctxCFX Tag" attribute="CFX Tags" lineEndContext="#stay">
- <DetectChar attribute="CFX Tags" context="#pop" char="&gt;" />
- <DetectChar attribute="Normal Text" context="#stay" char="=" />
- <RegExpr attribute="Attribute Values" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Attribute Values" context="#stay" String="'[^']*'" />
- </context>
-
-
-
- <context name="ctxHTML Comment" attribute="HTML Comment" lineEndContext="#stay">
- <StringDetect attribute="CF Comment" context="ctxCF Comment" String="&lt;!---" />
- <StringDetect attribute="HTML Comment" context="#pop" String="--&gt;" />
- </context>
-
- <context name="ctxCF Comment" attribute="CF Comment" lineEndContext="#stay">
- <StringDetect attribute="CF Comment" context="#pop" String="---&gt;" />
- </context>
-
- <context name="ctxC Style Comment" attribute="Script Comment" lineEndContext="#stay">
- <Detect2Chars attribute="Script Comment" context="#pop" char="*" char1="/" />
- </context>
-
- <context name="ctxOne Line Comment" attribute="Script Comment" lineEndContext="#pop" />
-
- <context name="ctxHTML Entities" attribute="HTML Entities" lineEndContext="#pop">
- <DetectChar attribute="HTML Entities" context="#pop" char=";" />
- </context>
-
-
-
- <context name="ctxCFSCRIPT Block" attribute="Normal Text" lineEndContext="#stay">
- <Detect2Chars attribute="Script Comment" context="ctxC Style Comment" char="/" char1="*" />
- <Detect2Chars attribute="Script Comment" context="ctxOne Line Comment" char="/" char1="/" />
- <RegExpr attribute="Script Strings" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Script Strings" context="#stay" String="'[^']*'" />
- <Int attribute="Script Numbers" context="#stay" />
- <Float attribute="Script Numbers" context="#stay" />
- <AnyChar attribute="Script Operators" context="#stay" String="[()[\]=+-*/]+" />
- <AnyChar attribute="Brackets" context="#stay" String="{}" />
-
- <keyword attribute="Script Keywords" context="#stay" String="CFSCRIPT Keywords" />
- <keyword attribute="Script Functions" context="#stay" String="CFSCRIPT Functions" />
- <RegExpr attribute="Script Tags" context="#pop#pop" String="&lt;/[cC][fF][sS][cC][rR][iI][pP][tT]&gt;" />
- </context>
-
-
-
- <context name="ctxSCRIPT Block" attribute="Normal Text" lineEndContext="#stay">
- <Detect2Chars attribute="Script Comment" context="ctxC Style Comment" char="/" char1="*" />
- <Detect2Chars attribute="Script Comment" context="ctxOne Line Comment" char="/" char1="/" />
- <RegExpr attribute="Script Strings" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Script Strings" context="#stay" String="'[^']*'" />
- <Int attribute="Script Numbers" context="#stay" />
- <Float attribute="Script Numbers" context="#stay" />
- <AnyChar attribute="Script Operators" context="#stay" String="[()[\]=+-*/]+" />
- <AnyChar attribute="Brackets" context="#stay" String="{}" />
-
- <keyword attribute="Script Keywords" context="#stay" String="Script Keywords" />
- <keyword attribute="Script Objects" context="#stay" String="Script Objects" />
- <keyword attribute="Script Functions" context="#stay" String="Script Methods" />
- <RegExpr attribute="Script Tags" context="#pop#pop" String="&lt;/[sS][cC][rR][iI][pP][tT]&gt;" />
- </context>
-
-
-
- <context name="ctxSTYLE Block" attribute="Style Selectors" lineEndContext="#stay">
- <Detect2Chars attribute="Script Comment" context="ctxC Style Comment" char="/" char1="*" />
- <DetectChar attribute="Brackets" context="ctxStyle Properties" char="{" />
- <RegExpr attribute="Style Tags" context="#pop#pop" String="&lt;/[sS][tT][yY][lL][eE]&gt;" />
- </context>
-
- <context name="ctxStyle Properties" attribute="Style Properties" lineEndContext="#stay">
- <DetectChar attribute="Brackets" context="#pop" char="}" />
- <Detect2Chars attribute="Script Comment" context="ctxC Style Comment" char="/" char1="*" />
- <DetectChar attribute="Normal Text" context="ctxStyle Values" char=":" />
- </context>
-
- <context name="ctxStyle Values" attribute="Style Values" lineEndContext="#pop">
- <DetectChar attribute="Normal Text" context="#pop" char=";" />
- <DetectChar attribute="Normal Text" context="#stay" char="," />
- <Int attribute="Numbers" context="#stay" />
- <Float attribute="Numbers" context="#stay" />
- <RegExpr attribute="Numbers" context="#stay" String="#([0-9a-fA-F]{3})|([0-9a-fA-F]{6})" />
- <RegExpr attribute="Attribute Values" context="#stay" String="&quot;[^&quot;]*&quot;" />
- <RegExpr attribute="Attribute Values" context="#stay" String="'[^']*'" />
- </context>
-
- </contexts>
-
- <itemDatas>
-
- <itemData name="Normal Text" defStyleNum="dsNormal" color="#000000" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Tags" defStyleNum="dsNormal" color="#000080" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Table Tags" defStyleNum="dsNormal" color="#008080" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Script Tags" defStyleNum="dsNormal" color="#800000" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Image Tags" defStyleNum="dsNormal" color="#800080" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Style Tags" defStyleNum="dsNormal" color="#800080" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Anchor Tags" defStyleNum="dsNormal" color="#008000" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Attribute Values" defStyleNum="dsNormal" color="#0000ff" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="HTML Comment" defStyleNum="dsComment" color="#008000" selColor="#999999" bold="0" italic="0" />
- <itemData name="CF Comment" defStyleNum="dsComment" color="#ff9900" selColor="#999999" bold="0" italic="0" />
- <itemData name="Script Comment" defStyleNum="dsComment" color="#ff9900" selColor="#999999" bold="0" italic="0" />
- <itemData name="CF Tags" defStyleNum="dsNormal" color="#800000" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Custom Tags" defStyleNum="dsNormal" color="#cc6666" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="CFX Tags" defStyleNum="dsNormal" color="#008000" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Numbers" defStyleNum="dsNormal" color="#0000ff" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="HTML Entities" defStyleNum="dsNormal" color="#000000" selColor="#ffffff" bold="1" italic="0" />
- <itemData name="Style Selectors" defStyleNum="dsNormal" color="#ff00ff" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Style Properties" defStyleNum="dsNormal" color="#000080" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Style Values" defStyleNum="dsNormal" color="#ff0000" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Brackets" defStyleNum="dsNormal" color="#000080" selColor="#ffffff" bold="1" italic="0" />
- <itemData name="Script Numbers" defStyleNum="dsNormal" color="#ff00ff" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Script Strings" defStyleNum="dsNormal" color="#008080" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Script Operators" defStyleNum="dsNormal" color="#0000ff" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Script Keywords" defStyleNum="dsNormal" color="#0000cc" selColor="#ffffff" bold="1" italic="0" />
- <itemData name="Script Functions" defStyleNum="dsNormal" color="#000080" selColor="#ffffff" bold="1" italic="0" />
- <itemData name="Script Objects" defStyleNum="dsNormal" color="#0000cc" selColor="#ffffff" bold="1" italic="0" />
-
- </itemDatas>
-
- </highlighting>
-
- <general>
-
- <comments>
-
- <comment name="multiLine" start="&lt;!--" end="--&gt;" />
- <comment name="multiLine" start="/*" end="*/" />
- <comment name="singleLine" start="//" />
-
- </comments>
-
- <keywords casesensitive="0" weakDeliminator="-" />
-
- </general>
-
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!-- Author: Werner Braun <wb@o3-software.de> -->
-<!-- 29.05.2003 wb mailed to the kate-team (cullmann) -->
-<!-- 23.05.2003 wb added *.bro File-Type for GPCP Browser output-->
-<!-- 09.05.2003 wb nested comments allowed (maximum two level nesting) -->
-<!-- 07.04.2003 wb IN Problem solved -->
-<!-- 06.05.2003 wb NEW without ( -->
-<!-- 22.04.2003 wb Minor bugfixes -->
-<!-- 19.04.2003 wb Some more Enhancements -->
-<!-- 18.04.2003 wb Enhancenment for Maior / Minor Comments and Full / ReadOnly Exports, Folds for Procedures, Records, Comments -->
-<!-- 17.04.2003 wb Enhancements for Relation and Operators -->
-<language name="Component-Pascal" version="1.05" kateversion="2.1" section="Sources"
- extensions="*.cp;*.bro" mimetype="text/x-component-pascal"
- author="Werner Braun (wb@o3-software.de)" license="">
- <highlighting>
- <list name="keywords">
- <item> BEGIN </item>
- <item> BY </item>
- <item> CASE </item>
- <item> CLOSE </item>
- <item> CONST </item>
- <item> DO </item>
- <item> ELSE </item>
- <item> ELSIF </item>
- <item> END </item>
- <item> FOR </item>
- <item> IF </item>
- <item> IMPORT </item>
- <item> LOOP </item>
- <item> MODULE </item>
- <item> NEW </item>
- <item> OF </item>
- <item> OUT </item>
- <item> PROCEDURE </item>
- <item> REPEAT </item>
- <item> THEN </item>
- <item> TO </item>
- <item> TYPE </item>
- <item> UNTIL </item>
- <item> VAR </item>
- <item> WHILE </item>
- <item> WITH </item>
- </list>
- <list name="exits">
- <item> ASSERT </item>
- <item> EXIT </item>
- <item> HALT </item>
- <item> RETURN </item>
- </list>
- <list name="types">
- <item> ANYPTR </item>
- <item> ANYREC </item>
- <item> ARRAY </item>
- <item> BOOLEAN </item>
- <item> SHORTCHAR </item>
- <item> CHAR </item>
- <item> BYTE </item>
- <item> SHORTINT </item>
- <item> INTEGER </item>
- <item> LONGINT </item>
- <item> POINTER </item>
- <item> RECORD </item>
- <item> SHORTREAL </item>
- <item> REAL </item>
- <item> SET </item>
- </list>
- <list name="attributes">
- <item> ABSTRACT </item>
- <item> EMPTY </item>
- <item> EXTENSIBLE </item>
- <item> LIMITED </item>
- </list>
- <list name="builtins">
- <item> ABS </item>
- <item> ASH </item>
- <item> BITS </item>
- <item> CAP </item>
- <item> CHR </item>
- <item> DEC </item>
- <item> ENTIER </item>
- <item> EXCL </item>
- <item> INC </item>
- <item> INCL </item>
- <item> LEN </item>
- <item> LONG </item>
- <item> MAX </item>
- <item> MIN </item>
- <item> ODD </item>
- <item> ORD </item>
- <item> SHORT </item>
- <item> SIZE </item>
- </list>
- <list name="specials">
- <item> FALSE </item>
- <item> INF </item>
- <item> NIL </item>
- <item> TRUE </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <StringDetect attribute="CommentMaior" context="Comment1" String="(**" beginRegion="Comment"/>
- <Detect2Chars attribute="CommentMinor" context="Comment2" char="(" char1="*" beginRegion="Comment"/>
- <DetectChar attribute="String" context="String1" char="&quot;" />
- <DetectChar attribute="String" context="String2" char="'" />
- <RegExpr attribute="Keyword" context="#stay" String="PROCEDURE\s" beginRegion="Proc"/>
- <RegExpr attribute="Normal Text" context="#stay" String="ABSTRACT;|EMPTY;|END\s*[A-Za-z][A-Za-z0-9_]*\;" endRegion="Proc"/>
- <RegExpr attribute="Type" context="#stay" String="RECORD" beginRegion="Rec"/>
- <RegExpr attribute="Keyword" context="#stay" String="END" endRegion="Rec"/>
- <StringDetect attribute="MemAlloc" context="#stay" String="NEW"/>
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Exit" context="#stay" String="exits"/>
- <keyword attribute="Type" context="#stay" String="types"/>
- <keyword attribute="Attribute" context="#stay" String="attributes"/>
- <keyword attribute="Builtin" context="#stay" String="builtins"/>
- <keyword attribute="SpecialValues" context="#stay" String="specials"/>
- <RegExpr attribute="Integer" context="#stay" String="\s[\+|\-]{0,1}[0-9]([0-9]*|[0-9A-F]*(H|L))"/>
- <Float attribute="Float" context="#stay"/>
- <RegExpr attribute="Char" context="#stay" String="\s[0-9][0-9A-F]*X"/>
- <RegExpr attribute="ExportFull" context="#stay" String="[A-Za-z][A-Za-z0-9_]*\*"/>
- <RegExpr attribute="ExportReadOnly" context="#stay" String="[A-Za-z][A-Za-z0-9_]*\-"/>
- <RegExpr attribute="Relation" context="#stay" String="\s(=|#|&lt;|&lt;=|&gt;|&gt;=|IN\s|IS)"/>
- <RegExpr attribute="Operator" context="#stay" String="\s(\+|\-|OR|\*|/|DIV|MOD|\&amp;)"/>
- </context>
- <context attribute="CommentMaior" lineEndContext="#stay" name="Comment1">
- <Detect2Chars attribute="CommentMaior" context="#pop" char="*" char1=")" endRegion="Comment"/>
- <Detect2Chars attribute="CommentMinor" context="CommentN" char="(" char1="*"/>
- </context>
- <context attribute="CommentMinor" lineEndContext="#stay" name="Comment2">
- <Detect2Chars attribute="CommentMinor" context="#pop" char="*" char1=")" endRegion="Comment"/>
- <Detect2Chars attribute="CommentMinor" context="CommentN" char="(" char1="*"/>
- </context>
- <context attribute="CommentMinor" lineEndContext="#stay" name="CommentN">
- <Detect2Chars attribute="CommentMinor" context="#pop" char="*" char1=")"/>
- <Detect2Chars attribute="CommentMinor" context="CommentN2" char="(" char1="*"/>
- </context>
- <context attribute="CommentMinor" lineEndContext="#stay" name="CommentN2">
- <Detect2Chars attribute="CommentMinor" context="#pop" char="*" char1=")"/>
- </context>
- <context attribute="String" lineEndContext="#stay" name="String1">
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="String" lineEndContext="#stay" name="String2">
- <DetectChar attribute="String" context="#pop" char="'"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="CommentMaior" defStyleNum="dsComment" />
- <itemData name="CommentMinor" defStyleNum="dsComment" />
- <itemData name="String" defStyleNum="dsString" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="MemAlloc" defStyleNum="dsKeyword" />
- <itemData name="Exit" defStyleNum="dsKeyword"/>
- <itemData name="Type" defStyleNum="dsDataType"/>
- <itemData name="Attribute" defStyleNum="dsOthers"/>
- <itemData name="Builtin" defStyleNum="dsNormal"/>
- <itemData name="Integer" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat" />
- <itemData name="Char" defStyleNum="dsChar" />
- <itemData name="SpecialValues" defStyleNum="dsDecVal"/>
- <itemData name="ExportFull" defStyleNum="dsOthers"/>
- <itemData name="ExportReadOnly" defStyleNum="dsOthers"/>
- <itemData name="Relation" defStyleNum="dsNormal"/>
- <itemData name="Operator" defStyleNum="dsNormal"/>
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="1" />
- <comments>
- <comment name="multiLine" start="(*" end="*)" />
- </comments>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="C++" version="1.15" kateversion="2.1" section="Sources" extensions="*.cxx;*.cpp;*.cc;*.C;*.h;*.hxx;*.hpp;*.hcc;*.moc" mimetype="text/x-c++src;text/x-c++hdr;text/x-chdr" priority="9">
- <highlighting>
- <list name="keywords">
- <item> asm </item>
- <item> break </item>
- <item> case </item>
- <item> catch </item>
- <item> class </item>
- <item> const_cast </item>
- <item> continue </item>
- <item> default </item>
- <item> delete </item>
- <item> do </item>
- <item> dynamic_cast</item>
- <item> else </item>
- <item> enum </item>
- <item> explicit </item>
- <item> export </item>
- <item> extern </item>
- <item> false </item>
- <item> friend </item>
- <item> for </item>
- <item> goto </item>
- <item> if </item>
- <item> inline </item>
- <item> namespace </item>
- <item> new </item>
- <item> operator </item>
- <item> private </item>
- <item> protected </item>
- <item> public </item>
- <item> reinterpret_cast </item>
- <item> return </item>
- <item> sizeof </item>
- <item> static_cast </item>
- <item> struct </item>
- <item> switch </item>
- <item> template </item>
- <item> this </item>
- <item> throw </item>
- <item> true </item>
- <item> try </item>
- <item> typedef </item>
- <item> typeid </item>
- <item> type_info </item>
- <item> typename </item>
- <item> union </item>
- <item> using </item>
- <item> virtual </item>
- <item> while </item>
-
- <item> and </item>
- <item> and_eq </item>
- <item> bad_cast </item>
- <item> bad_typeid </item>
- <item> bitand </item>
- <item> bitor </item>
- <item> compl </item>
- <item> not </item>
- <item> not_eq </item>
- <item> or </item>
- <item> or_eq </item>
- <item> xor </item>
- <item> xor_eq </item>
- <item> except </item>
- <item> finally </item>
- <item> xalloc </item>
- </list>
- <list name="extensions">
- <item> K_DCOP </item>
- <item> SLOT </item>
- <item> SIGNAL </item>
- <item> Q_CLASSINFO </item>
- <item> Q_ENUMS </item>
- <item> Q_EXPORT </item>
- <item> Q_OBJECT </item>
- <item> Q_OVERRIDE </item>
- <item> Q_PROPERTY </item>
- <item> Q_SETS </item>
- <item> TRUE </item>
- <item> FALSE </item>
- <item> connect </item>
- <item> disconnect </item>
- <item> emit </item>
- <item> signals </item>
- <item> slots </item>
- </list>
- <list name="types">
- <item> auto </item>
- <item> bool </item>
- <item> char </item>
- <item> const </item>
- <item> double </item>
- <item> float </item>
- <item> int </item>
- <item> long </item>
- <item> mutable </item>
- <item> register </item>
- <item> short </item>
- <item> signed </item>
- <item> static </item>
- <item> unsigned </item>
- <item> void </item>
- <item> volatile </item>
- <item> uchar </item>
- <item> uint </item>
- <item> int8_t </item>
- <item> int16_t </item>
- <item> int32_t </item>
- <item> int64_t </item>
- <item> uint8_t </item>
- <item> uint16_t </item>
- <item> uint32_t </item>
- <item> uint64_t </item>
- <item> wchar_t </item>
- </list>
- <list name="attention">
- <item> FIXME </item>
- <item> TODO </item>
- <item> ### </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <RegExpr attribute="Decimal" context="#stay" String="//\s*BEGIN.*$" beginRegion="Region1"/>
- <RegExpr attribute="Decimal" context="#stay" String="//\s*END.*$" endRegion="Region1"/>
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Extensions" context="#stay" String="extensions" />
- <keyword attribute="Data Type" context="#stay" String="types" />
- <Float attribute="Float" context="#stay">
- <AnyChar String="fF" attribute="Float" context="#stay"/>
- </Float>
- <HlCOct attribute="Octal" context="#stay"/>
- <HlCHex attribute="Hex" context="#stay"/>
- <Int attribute="Decimal" context="#stay">
- <StringDetect attribute="Decimal" context="#stay" String="ULL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LUL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LLU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="UL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="U" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="L" insensitive="TRUE"/>
- </Int>
- <HlCChar attribute="Char" context="#stay"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*" beginRegion="Comment"/>
- <DetectChar attribute="Symbol" context="#stay" char="{" beginRegion="Brace1" />
- <DetectChar attribute="Symbol" context="#stay" char="}" endRegion="Brace1" />
- <StringDetect attribute="Preprocessor" context="Outscoped" String="#if 0"/>
- <DetectChar attribute="Preprocessor" context="Preprocessor" char="#"/>
- <RegExpr attribute="Function" context="#stay" String="\b[_\w][_\d\w]*(?=[\s]*[(])" />
- <RegExpr attribute="Symbol" context="Member" String="([.]{1,1}|[:]{2,2})" />
- <AnyChar attribute="Symbol" context="#stay" String=":!%&amp;()+,-/.*&lt;=&gt;?[]{|}~^&#59;"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Member">
- <RegExpr attribute="Function" context="#pop" String="\b[_\w][_\w\d]*(?=[\s]*)" />
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Commentar 1">
- <keyword attribute="Decimal" context="#stay" String="attention" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar 2">
- <keyword attribute="Decimal" context="#stay" String="attention" />
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- </context>
- <context attribute="Preprocessor" lineEndContext="#pop" name="Preprocessor">
- <LineContinue attribute="Preprocessor" context="#stay"/>
- <RegExpr attribute="Preprocessor" context="Define" String="define.*((?=\\))"/>
- <RegExpr attribute="Preprocessor" context="#stay" String="define.*"/>
- <RangeDetect attribute="Prep. Lib" context="#stay" char="&quot;" char1="&quot;"/>
- <RangeDetect attribute="Prep. Lib" context="#stay" char="&lt;" char1="&gt;"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar/Preprocessor" char="/" char1="*"/>
- </context>
- <context attribute="Preprocessor" lineEndContext="#pop" name="Define">
- <LineContinue attribute="Preprocessor" context="#stay"/>
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar/Preprocessor">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" />
- </context>
- <context attribute="Normal Text" lineEndContext="String" name="Some Context"/>
- <context attribute="Normal Text" lineEndContext="Preprocessor" name="Some Context2"/>
- <context attribute="Comment" lineEndContext="#stay" name="Outscoped" >
- <keyword attribute="Decimal" context="#stay" String="attention" />
- <RegExpr attribute="Comment" context="Outscoped intern" String="^#if" />
- <RegExpr attribute="Preprocessor" context="#pop" String="#endif" />
- <RegExpr attribute="Preprocessor" context="#pop" String="#else" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Outscoped intern">
- <RegExpr attribute="Comment" context="Outscoped intern" String="#if" />
- <RegExpr attribute="Comment" context="#pop" String="#endif" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Extensions" defStyleNum="dsKeyword" color="#0095ff" selColor="#ffffff" bold="1" italic="0"/>
- <itemData name="Function" defStyleNum="dsKeyword" color="#000080" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- <itemData name="Prep. Lib" defStyleNum="dsOthers"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="C#" version="1.08" kateversion="2.1" section="Sources" extensions="*.cs" mimetype="text/x-csharp-src;text/x-csharp-hde">
- <highlighting>
- <list name="keywords">
- <item> abstract</item>
- <item> as</item>
- <item> base</item>
- <item> break</item>
- <item> case</item>
- <item> catch</item>
- <item> class</item>
- <item> checked</item>
- <item> continue</item>
- <item> default</item>
- <item> delegate</item>
- <item> do</item>
- <item> else</item>
- <item> enum</item>
- <item> event</item>
- <item> explicit</item>
- <item> extern</item>
- <item> false</item>
- <item> for</item>
- <item> foreach</item>
- <item> finally</item>
- <item> fixed</item>
- <item> goto</item>
- <item> if</item>
- <item> implicit</item>
- <item> in</item>
- <item> interface</item>
- <item> internal</item>
- <item> is</item>
- <item> lock</item>
- <item> namespace</item>
- <item> new</item>
- <item> null</item>
- <item> operator</item>
- <item> out</item>
- <item> override</item>
- <item> params</item>
- <item> private</item>
- <item> protected</item>
- <item> public</item>
- <item> readonly</item>
- <item> ref</item>
- <item> return</item>
- <item> sealed</item>
- <item> sizeof</item>
- <item> stackalloc</item>
- <item> static</item>
- <item> struct</item>
- <item> switch</item>
- <item> this</item>
- <item> throw</item>
- <item> true</item>
- <item> try</item>
- <item> typeof</item>
- <item> unchecked</item>
- <item> unsafe</item>
- <item> using</item>
- <item> virtual</item>
- <item> while</item>
- <item> #if</item>
- <item> #else</item>
- <item> #elif</item>
- <item> #endif</item>
- <item> #define</item>
- <item> #undef</item>
- <item> #warning</item>
- <item> #error</item>
- <item> #line</item>
- </list>
- <list name="types">
- <item> bool</item>
- <item> byte</item>
- <item> char</item>
- <item> const</item>
- <item> decimal</item>
- <item> double</item>
- <item> float</item>
- <item> int</item>
- <item> long</item>
- <item> object</item>
- <item> uint</item>
- <item> ushort</item>
- <item> ulong</item>
- <item> sbyte</item>
- <item> short</item>
- <item> string</item>
- <item> void</item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data Type" context="#stay" String="types" />
- <Float attribute="Float" context="#stay">
- <AnyChar String="fF" attribute="Float" context="#stay"/>
- </Float>
- <HlCOct attribute="Octal" context="#stay"/>
- <HlCHex attribute="Hex" context="#stay"/>
- <Int attribute="Decimal" context="#stay" >
- <StringDetect attribute="Decimal" context="#stay" String="ULL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LUL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LLU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="UL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="U" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="L" insensitive="TRUE"/>
- </Int>
- <HlCChar attribute="Char" context="#stay"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*"/>
- <DetectChar attribute="Symbol" context="#stay" char="{" beginRegion="block1"/>
- <DetectChar attribute="Symbol" context="#stay" char="}" endRegion="block1"/>
- <RegExpr attribute="Decimal" context="#stay" String="#region.*$" beginRegion="Region1"/>
- <RegExpr attribute="Decimal" context="#stay" String="#endregion.*$" endRegion="Region1"/>
- <RegExpr attribute="Function" context="#stay" String="\b[_\w][_\w\d]*(?=[\s]*[(])" />
- <RegExpr attribute="Symbol" context="Member" String="[.]{1,1}" />
- <AnyChar attribute="Symbol" context="#stay" String=":!%&amp;()+,-/.*&lt;=&gt;?[]|~^&#59;"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#pop"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Member">
- <RegExpr attribute="Function" context="#pop" String="\b[_\w][_\w\d]*(?=[\s]*)" />
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Commentar 1"/>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar 2">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Function" defStyleNum="dsKeyword" color="#000080" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="CSS" version="1.02" kateversion="2.1" section="Markup" extensions="*.css" mimetype="text/css">
- <highlighting>
- <list name="keywords">
- <item> azimuth </item>
- <item> background-attachment </item>
- <item> background-color </item>
- <item> background-image </item>
- <item> background-position </item>
- <item> background-repeat </item>
- <item> border-collapse </item>
- <item> border-spacing </item>
- <item> border-top-color </item>
- <item> border-right-color </item>
- <item> border-bottom-color </item>
- <item> border-left-color </item>
- <item> border-top-style </item>
- <item> border-right-style </item>
- <item> border-bottom-style </item>
- <item> border-left-style </item>
- <item> border-top-width </item>
- <item> border-right-width </item>
- <item> border-bottom-width </item>
- <item> border-left-width </item>
- <item> bottom </item>
- <item> caption-side </item>
- <item> clear </item>
- <item> clip </item>
- <item> color </item>
- <item> content </item>
- <item> counter-increment </item>
- <item> counter-reset </item>
- <item> cue-after </item>
- <item> cue-before </item>
- <item> cursor </item>
- <item> direction </item>
- <item> display </item>
- <item> elevation </item>
- <item> empty-cells </item>
- <item> float </item>
- <item> font-family </item>
- <item> font-size </item>
- <item> font-size-adjust </item>
- <item> font-stretch </item>
- <item> font-style </item>
- <item> font-variant </item>
- <item> font-weight </item>
- <item> height </item>
- <item> left </item>
- <item> letter-spacing </item>
- <item> line-height </item>
- <item> list-style-image </item>
- <item> list-style-position </item>
- <item> list-style-keyword </item>
- <item> list-style-type </item>
- <item> margin-top </item>
- <item> margin-right </item>
- <item> margin-bottom </item>
- <item> margin-left </item>
- <item> marker-offset </item>
- <item> max-height </item>
- <item> max-width </item>
- <item> min-height </item>
- <item> min-width </item>
- <item> orphans </item>
- <item> outline-color </item>
- <item> outline-style </item>
- <item> outline-width </item>
- <item> overflow </item>
- <item> padding-top </item>
- <item> padding-right </item>
- <item> padding-bottom </item>
- <item> padding-left </item>
- <item> page </item>
- <item> page-break-after </item>
- <item> page-break-before </item>
- <item> page-break-inside </item>
- <item> pause-after </item>
- <item> pause-before </item>
- <item> pitch </item>
- <item> pitch-range </item>
- <item> play-during </item>
- <item> position </item>
- <item> quotes </item>
- <item> richness </item>
- <item> right </item>
- <item> size </item>
- <item> speak </item>
- <item> speak-header </item>
- <item> speak-numeral </item>
- <item> speak-punctuation </item>
- <item> speech-rate </item>
- <item> stress </item>
- <item> table-layout </item>
- <item> text-align </item>
- <item> text-decoration </item>
- <item> text-decoration-color </item>
- <item> text-indent </item>
- <item> text-shadow </item>
- <item> text-transform </item>
- <item> top </item>
- <item> unicode-bidi </item>
- <item> vertical-align </item>
- <item> visibility </item>
- <item> voice-family </item>
- <item> volume </item>
- <item> white-space </item>
- <item> widows </item>
- <item> width </item>
- <item> word-spacing </item>
- <item> z-index </item>
- <item> background </item>
- <item> border </item>
- <item> border-color </item>
- <item> border-style </item>
- <item> border-top </item>
- <item> border-right </item>
- <item> border-bottom </item>
- <item> border-left </item>
- <item> border-width </item>
- <item> cue </item>
- <item> font </item>
- <item> list-style </item>
- <item> margin </item>
- <item> outline </item>
- <item> padding </item>
- <item> pause </item>
- <item> konq_bgpos_x </item>
- <item> konq_bgpos_y </item>
- </list>
- <list name="types">
- <item> inherit </item>
- <item> none </item>
- <item> hidden </item>
- <item> dotted </item>
- <item> dashed </item>
- <item> solid </item>
- <item> double </item>
- <item> groove </item>
- <item> ridge </item>
- <item> inset </item>
- <item> outset </item>
- <item> xx-small </item>
- <item> x-small </item>
- <item> small </item>
- <item> medium </item>
- <item> large </item>
- <item> x-large </item>
- <item> xx-large </item>
- <item> smaller </item>
- <item> larger </item>
- <item> italic </item>
- <item> oblique </item>
- <item> small-caps </item>
- <item> normal </item>
- <item> bold </item>
- <item> bolder </item>
- <item> lighter </item>
- <item> light </item>
- <item> 100 </item>
- <item> 200 </item>
- <item> 300 </item>
- <item> 400 </item>
- <item> 500 </item>
- <item> 600 </item>
- <item> 700 </item>
- <item> 800 </item>
- <item> 900 </item>
- <item> transparent </item>
- <item> repeat </item>
- <item> repeat-x </item>
- <item> repeat-y </item>
- <item> no-repeat </item>
- <item> baseline </item>
- <item> sub </item>
- <item> super </item>
- <item> top </item>
- <item> text-top </item>
- <item> middle </item>
- <item> bottom </item>
- <item> text-bottom </item>
- <item> left </item>
- <item> right </item>
- <item> center </item>
- <item> justify </item>
- <item> konq-center </item>
- <item> disc </item>
- <item> circle </item>
- <item> square </item>
- <item> decimal </item>
- <item> decimal-leading-zero </item>
- <item> lower-roman </item>
- <item> upper-roman </item>
- <item> lower-greek </item>
- <item> lower-alpha </item>
- <item> lower-latin </item>
- <item> upper-alpha </item>
- <item> upper-latin </item>
- <item> hebrew </item>
- <item> armenian </item>
- <item> georgian </item>
- <item> cjk-ideographic </item>
- <item> hiragana </item>
- <item> katakana </item>
- <item> hiragana-iroha </item>
- <item> katakana-iroha </item>
- <item> inline </item>
- <item> block </item>
- <item> list-item </item>
- <item> run-in </item>
- <item> compact </item>
- <item> marker </item>
- <item> table </item>
- <item> inline-table </item>
- <item> table-row-group </item>
- <item> table-header-group </item>
- <item> table-footer-group </item>
- <item> table-row </item>
- <item> table-column-group </item>
- <item> table-column </item>
- <item> table-cell </item>
- <item> table-caption </item>
- <item> auto </item>
- <item> crosshair </item>
- <item> default </item>
- <item> pointer </item>
- <item> move </item>
- <item> e-resize </item>
- <item> ne-resize </item>
- <item> nw-resize </item>
- <item> n-resize </item>
- <item> se-resize </item>
- <item> sw-resize </item>
- <item> s-resize </item>
- <item> w-resize </item>
- <item> text </item>
- <item> wait </item>
- <item> help </item>
- <item> above </item>
- <item> absolute </item>
- <item> always </item>
- <item> avoid </item>
- <item> below </item>
- <item> bidi-override </item>
- <item> blink </item>
- <item> both </item>
- <item> capitalize </item>
- <item> caption </item>
- <item> close-quote </item>
- <item> collapse </item>
- <item> condensed </item>
- <item> crop </item>
- <item> cross </item>
- <item> embed </item>
- <item> expanded </item>
- <item> extra-condensed </item>
- <item> extra-expanded </item>
- <item> fixed </item>
- <item> hand </item>
- <item> hide </item>
- <item> higher </item>
- <item> icon </item>
- <item> inside </item>
- <item> invert </item>
- <item> landscape </item>
- <item> level </item>
- <item> line-through </item>
- <item> loud </item>
- <item> lower </item>
- <item> lowercase </item>
- <item> ltr </item>
- <item> menu </item>
- <item> message-box </item>
- <item> mix </item>
- <item> narrower </item>
- <item> no-close-quote </item>
- <item> no-open-quote </item>
- <item> nowrap </item>
- <item> open-quote </item>
- <item> outside </item>
- <item> overline </item>
- <item> portrait </item>
- <item> pre </item>
- <item> relative </item>
- <item> rtl </item>
- <item> scroll </item>
- <item> semi-condensed </item>
- <item> semi-expanded </item>
- <item> separate </item>
- <item> show </item>
- <item> small-caption </item>
- <item> static </item>
- <item> static-position </item>
- <item> status-bar </item>
- <item> thick </item>
- <item> thin </item>
- <item> ultra-condensed </item>
- <item> ultra-expanded </item>
- <item> underline </item>
- <item> uppercase </item>
- <item> visible </item>
- <item> wider </item>
- <item> break </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <RegExpr attribute="Notice" context="#stay" String="/\*BEGIN.*\*/" beginRegion="UserDefined" />
- <RegExpr attribute="Notice" context="#stay" String="/\*END.*\*/" endRegion="UserDefined" />
- <Detect2Chars attribute="Comment" context="Comment" char="/" char1="*" beginRegion="Comment" />
- <DetectChar attribute="Normal Text" context="Rules" char="{" beginRegion="RuleSet" />
- </context>
- <context attribute="Normal Text" lineEndContext="#stay" name="Rules">
- <DetectChar attribute="Normal Text" context="#pop" char="}" endRegion="RuleSet" />
- <Detect2Chars attribute="Comment" context="Comment" char="/" char1="*" beginRegion="Comment" />
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Data Type" context="#stay" String="types" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Comment">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment" />
- <RegExpr attribute="Notice" context= "#stay" String="(FIXME|TODO|NOTE)" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Comment" defStyleNum="dsComment" />
- <itemData name="Notice" defStyleNum="dsString" bold="1"/>
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="1" weakDeliminator="-"/>
- <comments>
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="CUE Sheet" version="0.9" kateversion="2.1" section="Other" extensions="*.cue" mimetype="application/x-cue">
- <highlighting>
- <list name="keywords">
- <item> CATALOG </item>
- <item> CDTEXTFILE </item>
- <item> FILE </item>
- <item> FLAGS </item>
- <item> INDEX </item>
- <item> ISRC </item>
- <item> PERFORMER </item>
- <item> PREGAP </item>
- <item> POSTGAP </item>
- <item> REM </item>
- <item> SONGWRITER </item>
- <item> TITLE </item>
- <item> TRACK </item>
- </list>
- <list name="format">
- <item> AIFF </item>
- <item> WAVE </item>
- <item> MP3 </item>
- <item> BINARY </item>
- <item> MOTOTOLA </item>
- </list>
- <list name="mode">
- <item> AUDIO </item>
- <item> CDG </item>
- <item> CDI </item>
- <item> MODE1 </item>
- <item> MODE2 </item>
- <item> RAW </item>
- </list>
- <list name="flags">
- <item> 4CH </item>
- <item> DCP </item>
- <item> PRE </item>
- <item> SCMS </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Format" context="#stay" String="format" />
- <keyword attribute="Mode" context="#stay" String="mode" />
- <keyword attribute="Flags" context="#stay" String="flags" />
- <Int attribute="Decimal" context="#stay" />
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <DetectChar attribute="Comment" context="Comment" char=";"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Comment" />
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Format" defStyleNum="dsNormal" color="#800000"/>
- <itemData name="Mode" defStyleNum="dsNormal" color="#000080"/>
- <itemData name="Flags" defStyleNum="dsNormal" color="#008000"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start=";" />
- </comments>
- <keywords casesensitive="0" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="D" version="1.1" kateversion="2.1" section="Sources" extensions="*.d;*.D" mimetype="text/x-dsrc">
- <highlighting>
- <list name="keywords">
- <item> abstract </item>
- <item> alias </item>
- <item> align </item>
- <item> asm </item>
- <item> auto </item>
-
- <item> body </item>
- <item> break </item>
-
- <item> case </item>
- <item> cast </item>
- <item> catch </item>
- <item> class </item>
- <item> const </item>
- <item> continue </item>
-
- <item> default </item>
- <item> delegate </item>
- <item> delete </item>
- <item> deprecated </item>
- <item> do </item>
-
- <item> else </item>
- <item> enum </item>
- <item> export </item>
-
- <item> false </item>
- <item> final </item>
- <item> finally </item>
- <item> for </item>
- <item> foreach </item>
- <item> function </item>
-
- <item> goto </item>
-
- <item> if </item>
- <item> in </item>
- <item> inout </item>
- <item> interface </item>
- <item> invariant </item>
-
- <item> new </item>
- <item> null </item>
-
- <item> override </item>
- <item> out </item>
-
- <item> private </item>
- <item> protected </item>
- <item> public </item>
-
- <item> return </item>
-
- <item> static </item>
- <item> struct </item>
- <item> super </item>
- <item> switch </item>
- <item> synchronized </item>
-
- <item> this </item>
- <item> throw </item>
- <item> true </item>
- <item> try </item>
- <item> typedef </item>
-
- <item> union </item>
-
- <item> volatile </item>
-
- <item> while </item>
- <item> with </item>
- </list>
- <list name="modules">
- <item> module </item>
- <item> import </item>
- </list>
- <list name="types">
- <item> void </item>
- <item> bit </item>
- <item> byte </item>
- <item> ubyte </item>
- <item> short </item>
- <item> ushort </item>
- <item> int </item>
- <item> uint </item>
- <item> long </item>
- <item> ulong </item>
- <item> cent </item>
- <item> ucent </item>
- <item> float </item>
- <item> double </item>
- <item> real </item>
- <item> ireal </item>
- <item> ifloat </item>
- <item> idouble </item>
- <item> creal </item>
- <item> cfloat </item>
- <item> cdouble </item>
- <item> char </item>
- <item> wchar </item>
- <item> dchar </item>
- </list>
- <list name="phobos">
- <item> printf </item>
- </list>
- <list name="linkage">
- <item> extern </item>
- </list>
- <list name="ltypes">
- <item> C </item>
- <item> D </item>
- <item> Windows </item>
- <item> Pascal </item>
- </list>
- <list name="debug">
- <item> debug </item>
- </list>
- <list name="assert">
- <item> assert </item>
- </list>
- <list name="version">
- <item> version </item>
- </list>
- <list name="vtypes">
- <item> DigitalMars </item>
- <item> X86 </item>
- <item> Win32 </item>
- <item> linux </item>
- <item> LittleEndian </item>
- <item> BigEndian </item>
- <item> D_InlineAsm </item>
- <item> none </item>
- </list>
- <list name="unittest">
- <item> unittest </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="normal">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Module" context="ModuleName" String="modules"/>
- <keyword attribute="Type" context="#stay" String="types"/>
- <keyword attribute="Phobos Library" context="#stay" String="phobos"/>
- <keyword attribute="Linkage" context="Linkage" String="linkage"/>
- <keyword attribute="Debug" context="#stay" String="debug"/>
- <keyword attribute="Assert" context="#stay" String="assert"/>
- <keyword attribute="Version" context="Version" String="version"/>
- <keyword attribute="Unit Test" context="#stay" String="unittest"/>
-
- <Detect2Chars attribute="Wysiwyg" context="Wysiwyg" char="r" char1="&quot;"/>
- <Detect2Chars attribute="Hex" context="Hex" char="x" char1="&quot;"/>
-
- <RegExpr attribute="Normal Text" context="#pop" String="[_a-z][\w]*" insensitive="TRUE"/>
-
- <RegExpr attribute="Pragmas" context="#pop" String="\#[ ]*line"/>
-
- <RegExpr attribute="Escape String" context="#pop" String="\\[n|t|&quot;]"/>
- <RegExpr attribute="Escape String" context="#pop" String="(\\r\\n)"/>
- <RegExpr attribute="Escape String" context="#pop" String="\\0[0-7]+"/>
- <RegExpr attribute="Escape String" context="#pop" String="\\u[\d]+" insensitive="TRUE"/>
- <RegExpr attribute="Escape String" context="#pop" String="\\x[\da-fA-F]+"/>
-
- <RegExpr attribute="Binary" context="#pop" String="0b[01]+[_01]*[ ]*\.\.[ ]*0b[01]+[_01]*(UL|LU|U|L)?" insensitive="TRUE"/>
- <RegExpr attribute="Octal" context="#pop" String="0[0-7]+[_0-7]*[ ]*\.\.[ ]*0[0-7]+[_0-7]*(UL|LU|U|L)?" insensitive="TRUE"/>
- <RegExpr attribute="Hex" context="#pop" String="0x[\da-f]+[_\da-f]*[ ]*\.\.[ ]*0x[\da-f]+[_\da-f]*(UL|LU|U|L)?" insensitive="TRUE"/>
- <RegExpr attribute="Integer" context="#pop" String="[\d]+[_\d]*(UL|LU|U|L)?[ ]*\.\.[ ]*[\d]+[_\d]*(UL|LU|U|L)?" insensitive="TRUE"/>
-
- <RegExpr attribute="Float" context="#pop" String="[\d]*[_\d]*\.[_\d]*(e-|e|e\+)?[\d]+[_\d]*(F|L|I|FI|LI|)?" insensitive="TRUE"/>
- <RegExpr attribute="Float" context="#pop" String="[\d]*[_\d]*\.?[_\d]*(e-|e|e\+)[\d]+[_\d]*(F|L|I|FI|LI|)?" insensitive="TRUE"/>
- <RegExpr attribute="Float" context="#pop" String="0x[\da-f]+[_\da-f]*\.[_\da-f]*(p-|p|p\+)?[\da-f]+[_\da-f]*(F|L|I|FI|LI)?" insensitive="TRUE"/>
- <RegExpr attribute="Float" context="#pop" String="0x[\da-f]+[_\da-f]*\.?[_\da-f]*(p-|p|p\+)[\da-f]+[_\da-f]*(F|L|I|FI|LI)?" insensitive="TRUE"/>
-
- <RegExpr attribute="Binary" context="#pop" String="0B[01]+[_01]*(UL|LU|U|L)?" insensitive="TRUE"/>
- <RegExpr attribute="Octal" context="#pop" String="0[0-7]+[_0-7]*(UL|LU|U|L)?" insensitive="TRUE"/>
- <RegExpr attribute="Hex" context="#pop" String="0x[\da-f]+[_\da-f]*(UL|LU|U|L)?" insensitive="TRUE"/>
- <RegExpr attribute="Integer" context="#pop" String="[\d]+[_\d]*(UL|LU|U|L)?" insensitive="TRUE"/>
-
- <DetectChar attribute="Char" context="Char" char="'"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <DetectChar attribute="Wysiwyg" context="Wysiwyg" char="`"/>
-
- <Detect2Chars attribute="Comment" context="CommentLine" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="CommentBlockA" char="/" char1="*" beginRegion="CommentA"/>
- <Detect2Chars attribute="Comment" context="CommentBlockB" char="/" char1="+" beginRegion="CommentB"/>
-
- <DetectChar attribute="Normal Text" context="#stay" char="{" beginRegion="BraceA" />
- <DetectChar attribute="Normal Text" context="#stay" char="}" endRegion="BraceA" />
- </context>
-
- <context attribute="Module Name" lineEndContext="#stay" name="ModuleName">
- <DetectChar attribute="Normal Text" context="#stay" char=","/>
- <DetectChar attribute="Normal Text" context="#pop" char=";"/>
- <Detect2Chars attribute="Comment" context="CommentLine" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="CommentBlockA" char="/" char1="*" beginRegion="CommentA"/>
- <Detect2Chars attribute="Comment" context="CommentBlockB" char="/" char1="+" beginRegion="CommentB"/>
- </context>
-
- <context attribute="Linkage" lineEndContext="#pop" name="Linkage">
- <keyword attribute="Type" context="#pop" String="types"/>
- <DetectChar attribute="Normal Text" context="#stay" char="("/>
- <keyword attribute="Linkage Type" context="#stay" String="ltypes"/>
- <DetectChar attribute="Normal Text" context="#pop" char=")"/>
- <DetectChar attribute="Normal Text" context="#pop" char=";"/>
- </context>
- <context attribute="Version" lineEndContext="#pop" name="Version">
- <DetectChar attribute="Normal Text" context="#pop" char="="/>
- <DetectChar attribute="Normal Text" context="#stay" char="("/>
- <keyword attribute="Version Type" context="#stay" String="vtypes"/>
- <RegExpr attribute="Normal Text" context="#pop" String="\w" insensitive="TRUE"/>
- <DetectChar attribute="Normal Text" context="#pop" char=")"/>
- </context>
-
- <context attribute="Wysiwyg" lineEndContext="#stay" name="Wysiwyg">
- <DetectChar attribute="Wysiwyg" context="#pop" char="&quot;"/>
- <DetectChar attribute="Wysiwyg" context="#pop" char="`"/>
- </context>
- <context attribute="Hex" lineEndContext="#stay" name="Hex">
- <DetectChar attribute="Hex" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Char" lineEndContext="#stay" name="Char">
- <Detect2Chars attribute="Char" context="#stay" char="\" char1="'"/>
- <Detect2Chars attribute="Char" context="#stay" char="\" char1="\"/>
- <DetectChar attribute="Char" context="#pop" char="'"/>
- </context>
- <context attribute="String" lineEndContext="#stay" name="String">
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
-
- <context attribute="Comment" lineEndContext="#pop" name="CommentLine">
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="CommentBlockA">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="CommentA"/>
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="CommentBlockB">
- <Detect2Chars attribute="Comment" context="#pop" char="+" char1="/" endRegion="CommentB"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyWord" color="#000000" selColor="#ffffff" bold="1" italic="0"/>
- <itemData name="Module" defStyleNum="dsKeyWord" color="#0000ff" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Module Name" defStyleNum="dsKeyWord" color="#0000ff" selColor="#ffffff" bold="1" italic="1"/>
- <itemData name="Type" defStyleNum="dsDataType"/>
- <itemData name="Phobos Library" defStyleNum="dsKeyWord" color="#000000" selColor="#ffffff" bold="1" italic="1"/>
- <itemData name="Linkage" defStyleNum="dsKeyWord" color="#ff0000" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Linkage Type" defStyleNum="dsDataType" color="#ff0000" selColor="#ffffff" bold="1" italic="1"/>
- <itemData name="Debug" defStyleNum="dsKeyWord" color="#ff00ff" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Assert" defStyleNum="dsKeyWord" color="#0000ff" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Version" defStyleNum="dsKeyWord" color="#ff0000" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Version Type" defStyleNum="dsDataType" color="#ff0000" selColor="#ffffff" bold="1" italic="1"/>
- <itemData name="Unit Test" defStyleNum="dsKeyWord" color="#ff00ff" selColor="#ffffff" bold="1" italic="0"/>
- <itemData name="Pragmas" defStyleNum="dsKeyWord" color="#00aa00" selColor="#ffffff" bold="1" italic="0"/>
-
- <itemData name="Integer" defStyleNum="dsDecVal"/>
- <itemData name="Binary" defStyleNum="dsBaseN" color="#00dddd" selColor="#00ffff" bold="0" italic="0"/>
- <itemData name="Octal" defStyleNum="dsBaseN" color="#00aaaa" selColor="#00ffff" bold="0" italic="0"/>
- <itemData name="Hex" defStyleNum="dsBaseN" color="#006666" selColor="#00ffff" bold="0" italic="0"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
-
- <itemData name="Escape String" defStyleNum="dsString" color="#00aa00" selColor="#ff0000" bold="0" italic="0"/>
- <itemData name="String" defStyleNum="dsString" color="#00aa00" selColor="#ff0000" bold="0" italic="0"/>
- <itemData name="Char" defStyleNum="dsChar" color="#ff00ff" selColor="#ff00ff" bold="0" italic="0"/>
- <itemData name="Wysiwyg" defStyleNum="dsChar" color="#a100a1" selColor="#ff00ff" bold="0" italic="0"/>
-
- <itemData name="Comment" defStyleNum="dsComment"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//"/>
- <comment name="multiLine" start="/+" end="+/"/>
- </comments>
- <keywords casesensitive="TRUE"/>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name=".desktop" version="1.02" kateversion="2.1" section="Other" extensions="*.desktop;*.kdelnk" mimetype="application/x-desktop">
- <highlighting>
- <contexts>
- <context attribute="Key" lineEndContext="#stay" name="Normal">
- <RegExpr String="^\[.*\]$" attribute="Section" context="#stay" beginRegion="Section" endRegion="Section" />
- <RegExpr String="\[.*\]" attribute="Language" context="Value"/>
- <DetectChar char="=" attribute="Normal Text" context="Value"/>
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Value"/>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Section" defStyleNum="dsKeyword"/>
- <itemData name="Key" defStyleNum="dsDataType"/>
- <itemData name="Language" defStyleNum="dsNormal" color="#0000FF" selColor="#ffffff" italic="0" bold="1"/>
- </itemDatas>
- </highlighting>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Diff" version="1.01" kateversion="2.1" section="Other" extensions="*.diff;*patch" mimetype="text/x-diff">
- <highlighting>
-
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <RegExpr attribute="Keyword" context="Keyword" String="^(\+\+\+|\-\-\-|\*\*\*|diff|\d)" />
- <RegExpr attribute="Added line" context="Added" String="^(\+|&gt;|!)" />
- <RegExpr attribute="Removed line" context="Removed" String="^(\-|&lt;)" />
- <RegExpr attribute="Data Type" context="Data" String="^\@\@" />
- </context>
-
- <context attribute="Keyword" lineEndContext="#pop" name="Keyword"/>
- <context attribute="Removed line" lineEndContext="#pop" name="Removed"/>
- <context attribute="Added line" lineEndContext="#pop" name="Added"/>
- <context attribute="Data Type" lineEndContext="#pop" name="Data"/>
-
- </contexts>
-
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Removed line" defStyleNum="dsOthers"/>
- <itemData name="Added line" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="E Language" version="0.1" kateversion="2.1" section="Sources" extensions="*.e" mimetype="text/x-e-src">
- <highlighting>
- <list name="Type">
- <item> FALSE </item>
- <item> MAX_INT </item>
- <item> MIN_INT </item>
- <item> NULL </item>
- <item> TRUE </item>
- <item> UNDEF </item>
- <item> bit </item>
- <item> bits </item>
- <item> body </item>
- <item> bool </item>
- <item> byte </item>
- <item> byte_array </item>
- <item> continue </item>
- <item> copy </item>
- <item> default </item>
- <item> external_pointer </item>
- <item> files </item>
- <item> file </item>
- <item> form </item>
- <item> global </item>
- <item> index </item>
- <item> init </item>
- <item> int </item>
- <item> it </item>
- <item> list </item>
- <item> load </item>
- <item> long </item>
- <item> me </item>
- <item> method </item>
- <item> module </item>
- <item> ntv </item>
- <item> of </item>
- <item> pat </item>
- <item> print </item>
- <item> result </item>
- <item> source_ref </item>
- <item> string </item>
- <item> symtab </item>
- <item> sys </item>
- <item> test </item>
- <item> uint </item>
- <item> untyped </item>
- <item> vec </item>
- </list>
- <list name="Function">
- <item> run </item>
- <item> init </item>
- <item> pre_generate </item>
- <item> dut_error </item>
- <item> pack </item>
- <item> unpack </item>
- <item> post_generate </item>
- <item> pre_generate </item>
- <item> set_config </item>
- <item> hex </item>
- <item> stop_run </item>
- <item> append </item>
- <item> size </item>
- <item> delete </item>
- <item> is_empty </item>
- <item> deep_compare </item>
- <item> deep_compare_physical </item>
- <item> clear </item>
- <item> pop0 </item>
- <item> setup </item>
- <item> crc_32 </item>
- </list>
- <list name="Statement">
- <item> chars </item>
- <item> define </item>
- <item> extend </item>
- <item> event </item>
- <item> ECHO </item>
- <item> DOECHO </item>
- <item> import </item>
- <item> initialize </item>
- <item> non_terminal </item>
- <item> struct </item>
- <item> unit </item>
- <item> script </item>
- <item> testgroup </item>
- <item> type </item>
- </list>
- <list name="Action">
- <item> C </item>
- <item> add </item>
- <item> also </item>
- <item> and </item>
- <item> as </item>
- <item> as_a </item>
- <item> break </item>
- <item> code </item>
- <item> compute </item>
- <item> computed </item>
- <item> delayed </item>
- <item> do </item>
- <item> else </item>
- <item> each </item>
- <item> emit </item>
- <item> empty </item>
- <item> end </item>
- <item> exit </item>
- <item> finish </item>
- <item> for </item>
- <item> from </item>
- <item> if </item>
- <item> in </item>
- <item> is </item>
- <item> like </item>
- <item> log </item>
- <item> new </item>
- <item> no </item>
- <item> not </item>
- <item> only </item>
- <item> or </item>
- <item> out </item>
- <item> read </item>
- <item> repeat </item>
- <item> return </item>
- <item> reverse </item>
- <item> routine </item>
- <item> step </item>
- <item> then </item>
- <item> to </item>
- <item> traceable </item>
- <item> untraceable </item>
- <item> var </item>
- <item> when </item>
- <item> while </item>
- <item> with </item>
- <item> write </item>
- <item> xor </item>
- </list>
- <list name="Generation">
- <item> before </item>
- <item> by </item>
- <item> choose </item>
- <item> gen </item>
- <item> keep </item>
- <item> keeping </item>
- <item> matches </item>
- <item> next </item>
- <item> select </item>
- <item> sequence </item>
- <item> soft </item>
- <item> using </item>
- </list>
- <list name="Cover">
- <item> address </item>
- <item> cover </item>
- <item> error </item>
- <item> events </item>
- <item> event </item>
- <item> length </item>
- <item> kind </item>
- <item> ranges </item>
- <item> range </item>
- <item> sample </item>
- <item> text </item>
- <item> value </item>
- <item> item </item>
- <item> transition </item>
- <item> illegal </item>
- </list>
- <list name="Simulator">
- <item> always </item>
- <item> all </item>
- <item> basic </item>
- <item> call </item>
- <item> cycles </item>
- <item> cycle </item>
- <item> clock </item>
- <item> change </item>
- <item> check </item>
- <item> expect </item>
- <item> fall </item>
- <item> first </item>
- <item> forever </item>
- <item> idle </item>
- <item> initial </item>
- <item> negedge </item>
- <item> others </item>
- <item> on </item>
- <item> posedge </item>
- <item> rise </item>
- <item> start </item>
- <item> that </item>
- <item> time </item>
- <item> task </item>
- <item> until </item>
- <item> verilog </item>
- <item> vhdl </item>
- <item> wait </item>
- <item> within </item>
- </list>
- <contexts>
-
- <context name="out_comment" attribute="OutSide E code" lineEndContext="#stay">
- <Detect2Chars attribute="code_begin" context="normal" char="&lt;" char1="'" />
- </context>
-
- <context name="normal" attribute="Normal Text" lineEndContext="#stay">
- <DetectChar attribute="Operators" context="#stay" char="{" beginRegion="Region1"/>
- <DetectChar attribute="Operators" context="#stay" char="}" endRegion="Region1"/>
- <HlCHex attribute="Integer" context="#stay" />
- <HlCOct attribute="Integer" context="#stay" />
- <Int attribute="Integer" context="#stay" />
- <Detect2Chars attribute="code_end" context="out_comment" char="'" char1="&gt;" />
- <Detect2Chars attribute="Comment" context="comment" char="-" char1="-" />
- <Detect2Chars attribute="Comment" context="comment" char="/" char1="/" />
- <DetectChar attribute="Vector" context="string" char="&quot;" />
- <AnyChar attribute="Operators" context="#stay" String="'[&amp;&gt;&lt;=:+\-*\|].,;" />
- <keyword attribute="Data Type" context="#stay" String="Type"/>
- <keyword attribute="Function" context="#stay" String="Function"/>
- <keyword attribute="Statement" context="#stay" String="Statement"/>
- <keyword attribute="Action" context="#stay" String="Action"/>
- <keyword attribute="Keyword" context="#stay" String="Generation"/>
- <keyword attribute="Keyword" context="#stay" String="Cover"/>
- <keyword attribute="Keyword" context="#stay" String="Simulator"/>
-
- </context>
-
-
- <context name="comment" attribute="Comment" lineEndContext="#pop" />
-
- <context name="string" attribute="Vector" lineEndContext="#stay" >
- <DetectChar attribute="Vector" context="#pop" char="&quot;" />
- </context>
-
- </contexts>
-
- <itemDatas>
- <itemData name="OutSide E code" defStyleNum="dsComment"/>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="Function" defStyleNum="dsNormal" color="#0000FF" selColor="#00ff00" bold="1" italic="0" />
- <itemData name="Statement" defStyleNum="dsNormal" color="#8080FF" selColor="#00ff00" bold="1" italic="0" />
- <itemData name="Action" defStyleNum="dsNormal" color="#FF8080" selColor="#00ff00" bold="1" italic="0" />
- <itemData name="Data Type" defStyleNum="dsDataType" />
- <itemData name="Comment" defStyleNum="dsComment" />
- <itemData name="Integer" defStyleNum="dsDecVal" />
- <itemData name="Bit" defStyleNum="dsDecVal" />
- <itemData name="Vector" defStyleNum="dsString" />
- <itemData name="Operators" defStyleNum="dsNormal" color="#404000" selColor="#00ff00" bold="0" italic="0" />
- </itemDatas>
-
- </highlighting>
- <general>
- <keywords casesensitive="1" />
- </general>
-</language>
-
-
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Eiffel" version="1.02" kateversion="2.1" section="Sources" extensions="*.e" mimetype="text/x-eiffel-src">
- <highlighting>
- <list name="keywords">
- <item> indexing </item>
- <item> class </item>
- <item> inherit </item>
- <item> creation </item>
- <item> feature </item>
- <item> rename </item>
- <item> redefine </item>
- <item> undefine </item>
- <item> select </item>
- <item> export </item>
- <item> local </item>
- <item> deferred </item>
- <item> do </item>
- <item> is </item>
- <item> once </item>
- <item> alias </item>
- <item> external </item>
- <item> rescue </item>
- <item> debug </item>
- <item> if </item>
- <item> inspect </item>
- <item> from </item>
- <item> else </item>
- <item> elseif </item>
- <item> when </item>
- <item> until </item>
- <item> loop </item>
- <item> then </item>
- <item> obsolete </item>
- <item> end </item>
- </list>
- <list name="assertions">
- <item> check </item>
- <item> ensure </item>
- <item> require </item>
- <item> variant </item>
- <item> invariant </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <Float attribute="Float" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- <RegExpr attribute="Char" context="#stay" String="'.'"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="Comment" char="-" char1="-"/>
- <keyword attribute="Assertions" context="#stay" String="assertions"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Comment" name="Comment" lineEndContext="#pop"/>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="Decimal" defStyleNum="dsDecVal" />
- <itemData name="Float" defStyleNum="dsFloat" />
- <itemData name="Char" defStyleNum="dsChar" />
- <itemData name="String" defStyleNum="dsString" />
- <itemData name="Comment" defStyleNum="dsComment" />
- <itemData name="Assertions" defStyleNum="dsOthers" />
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="--" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="ferite" version="1.02" kateversion="2.1" section="Scripts" extensions="*.fe;*.feh" mimetype="text/x-ferite-src">
- <highlighting>
- <list name="keywords">
- <item> break </item>
- <item> case </item>
- <item> continue </item>
- <item> else </item>
- <item> for </item>
- <item> if </item>
- <item> do </item>
- <item> function </item>
- <item> namespace </item>
- <item> while </item>
- <item> class </item>
- <item> new </item>
- <item> uses </item>
- <item> global </item>
- <item> return </item>
- <item> self </item>
- <item> super </item>
- <item> null </item>
- <item> iferr </item>
- <item> fix </item>
- </list>
- <list name="types">
- <item> number </item>
- <item> void </item>
- <item> string </item>
- <item> array </item>
- <item> object </item>
- <item> final </item>
- <item> static </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Default" >
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <Float attribute="Float" context="#stay">
- <AnyChar String="fF" attribute="Float" context="#stay"/>
- </Float>
- <HlCOct attribute="Octal" context="#stay" />
- <HlCHex attribute="Hex" context="#stay" />
- <Int attribute="Decimal" context="#stay" >
- <StringDetect attribute="Decimal" context="#stay" String="ULL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LUL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LLU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="UL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="U" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="L" insensitive="TRUE"/>
- </Int>
- <HlCChar attribute="Char" context="#stay"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="Comment" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Multiline Comment" char="/" char1="*"/>
- <AnyChar attribute="Symbol" context="#stay" String="!%&amp;()+,-&lt;=&gt;?[]^{|}~"/>
- <StringDetect attribute="Comment" context="Undeffed" String="#if 0" insensitive="FALSE"/>
- <RegExpr attribute="Preprocessor" context="Preprocessor" String="^#"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Comment">
- <RegExpr attribute="Decimal" context="#stay" String="(FIXME|TODO)" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Multiline Comment">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/"/>
- <RegExpr attribute="Decimal" context="#stay" String="(FIXME|TODO)" />
- </context>
- <context attribute="Preprocessor" lineEndContext="#pop" name="Preprocessor">
- <LineContinue attribute="Preprocessor" context="#stay"/>
- <RangeDetect attribute="Prep. Lib" context="#stay" char="&quot;" char1="&quot;"/>
- <RangeDetect attribute="Prep. Lib" context="#stay" char="&lt;" char1="&gt;"/>
- <Detect2Chars attribute="Comment" context="Comment" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Multiline Comment 2" char="/" char1="*"/>
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Multiline Comment 2">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" />
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="unknown" />
- <context attribute="Normal Text" lineEndContext="#pop" name ="unknown 2" />
- <context attribute="Comment" lineEndContext="#stay" name="Undeffed">
- <RegExpr attribute="Decimal" context="#stay" String="(FIXME|TODO)" />
- <RegExpr attribute="Comment" context="#pop" String="^#endif" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- <itemData name="Prep. Lib" defStyleNum="dsOthers"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Fortran" version="1.04" kateversion="2.1" section="Sources" extensions="*.f;*.F;*.for;*.FOR;*.f90;*.F90;*.fpp;*.FPP" mimetype="text/x-fortran-src">
- <highlighting>
- <list name="keywords">
- <item> common </item>
- <item> continue </item>
- <item> block </item>
- <item> data </item>
- <item> date </item>
- <item> function </item>
- <item> include </item>
- <item> parameter </item>
- <item> implicit </item>
- <item> none </item>
- <item> equivalence </item>
- <item> if </item>
- <item> then </item>
- <item> else </item>
- <item> elseif </item>
- <item> endif </item>
- <item> go </item>
- <item> to </item>
- <item> goto </item>
- <item> program </item>
- <item> subroutine </item>
- <item> end </item>
- <item> call </item>
- <item> while </item>
- <item> cycle </item>
- <item> do </item>
- <item> enddo </item>
- <item> for </item>
- <item> break </item>
- <item> pause </item>
- <item> return </item>
- <item> stop </item>
- </list>
- <list name="io_functions">
- <item> access </item>
- <item> backspace </item>
- <item> close </item>
- <item> inquire </item>
- <item> open </item>
- <item> print </item>
- <item> read </item>
- <item> rewind </item>
- <item> write </item>
- <item> format </item>
- </list>
- <list name="maths">
- <item> abs </item>
- <item> acos </item>
- <item> aimag </item>
- <item> aint </item>
- <item> alog </item>
- <item> alog10 </item>
- <item> amax0 </item>
- <item> amax1 </item>
- <item> amin0 </item>
- <item> amin1 </item>
- <item> amod </item>
- <item> anint </item>
- <item> aprime </item>
- <item> asin </item>
- <item> atan </item>
- <item> atan2 </item>
- <item> acos </item>
- <item> cabs </item>
- <item> cexp </item>
- <item> clog </item>
- <item> conjg </item>
- <item> cos </item>
- <item> cosh </item>
- <item> ccos </item>
- <item> csin </item>
- <item> csqrt </item>
- <item> dabs </item>
- <item> dacos </item>
- <item> dasin </item>
- <item> datan </item>
- <item> datan2 </item>
- <item> dconjg </item>
- <item> dcos </item>
- <item> dcosh </item>
- <item> dfloat </item>
- <item> ddmim </item>
- <item> dexp </item>
- <item> dim </item>
- <item> dint </item>
- <item> dlog </item>
- <item> dlog10 </item>
- <item> dmax1 </item>
- <item> dmin1 </item>
- <item> dmod </item>
- <item> dnint </item>
- <item> dsign </item>
- <item> dsin </item>
- <item> dsinh </item>
- <item> dsqrt </item>
- <item> dtan </item>
- <item> dtanh </item>
- <item> exp </item>
- <item> iabs </item>
- <item> idim </item>
- <item> index </item>
- <item> isign </item>
- <item> len </item>
- <item> log </item>
- <item> log10 </item>
- <item> max </item>
- <item> max0 </item>
- <item> max1 </item>
- <item> min </item>
- <item> min0 </item>
- <item> min1 </item>
- <item> mod </item>
- <item> rand </item>
- <item> sign </item>
- <item> sin </item>
- <item> sinh </item>
- <item> sqrt </item>
- <item> tan </item>
- <item> tanh </item>
- </list>
- <list name="types">
- <item> character </item>
- <item> complex </item>
- <item> double </item>
- <item> precision </item>
- <item> real </item>
- <item> real*8 </item>
- <item> integer </item>
- <item> logical </item>
- <item> dimension </item>
- <item> external </item>
- <item> intrinsic </item>
- <item> save </item>
-
- <item> char </item>
- <item> cmplx </item>
- <item> dble </item>
- <item> dcmplx </item>
- <item> float </item>
- <item> ichar </item>
- <item> idint </item>
- <item> ifix </item>
- <item> int </item>
- <item> sngl </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="default" >
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <keyword attribute="IO Function" context="#stay" String="io_functions"/>
- <keyword attribute="Math Intrinsic" context="#stay" String="maths"/>
- <RegExpr attribute="Conditional" context="#stay" String="\.(and|AND|or|OR|eqv|EQV|neqv|NEQV|lt|LT|le|LE|eq|EQ|ne|NE|eqv|EQV|neqv|NEQV|ge|GE|gt|GT|not|NOT|true|TRUE|false|FALSE)\."/>
- <RegExpr attribute="Float" context="#stay" String="[0-9]*\.[0-9]*[dD][+|-]{0,1}[0-9]*"/>
- <Float attribute="Float" context="#stay">
- <AnyChar attribute="Float" context="#stay" String="fFdD"/>
- </Float>
- <Int attribute="Decimal" context="#stay" />
- <HlCChar attribute="Char" context="#stay"/>
- <DetectChar attribute="String" context="strings 1" char="&quot;"/>
- <DetectChar attribute="String" context="strings 2" char="&apos;"/>
- <RegExpr attribute="Preprocessor" context="#stay" String="^(#|cDEC\$|CDEC\$).*$"/>
- <RegExpr attribute="Comment" context="#stay" String="^[cC\*].*$"/>
- <RegExpr attribute="Comment" context="#stay" String="!.*$"/>
- <AnyChar attribute="Symbol" context="#stay" String="!%&amp;()+,-&lt;=&gt;?[]^{|}~"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="strings 1">
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="strings 2">
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&apos;"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- <itemData name="Conditional" defStyleNum="dsOthers" color="#008000" selColor="#ffa0a0" bold="1" italic="0"/>
- <itemData name="IO Function" defStyleNum="dsKeyword" color="#006060" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Math Intrinsic" defStyleNum="dsKeyword" color="#600060" selColor="#ffa0ff" bold="1" italic="0"/>
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="0"/>
- <comments>
- <comment name="singleLine" start="c"/>
- <comment name="singleLine" start="!"/>
- </comments>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="GDL" version="1.0" kateversion="2.0" section="Sources" extensions="*.gdl;*.vcg;*.GDL;*.VCG" mimetype="">
- <highlighting>
- <list name="colors">
- <item> white </item>
- <item> blue </item>
- <item> red </item>
- <item> green </item>
- <item> yellow </item>
- <item> magenta </item>
- <item> cyan </item>
- <item> darkgrey </item>
- <item> darkgray </item>
- <item> darkblue </item>
- <item> darkred </item>
- <item> darkgreen </item>
- <item> darkyellow </item>
- <item> darkmagenta </item>
- <item> darkcyan </item>
- <item> gold </item>
- <item> lightgrey </item>
- <item> lightgray </item>
- <item> lightblue </item>
- <item> lightred </item>
- <item> lightgreen </item>
- <item> lightyellow </item>
- <item> lightmagenta </item>
- <item> lightcyan </item>
- <item> lilac </item>
- <item> turquoise </item>
- <item> aquamarine </item>
- <item> khaki </item>
- <item> purple </item>
- <item> yellowgreen </item>
- <item> pink </item>
- <item> orange </item>
- <item> orchid </item>
- <item> black </item>
- </list>
- <list name="shapes">
- <item> box </item>
- <item> triangle </item>
- <item> circle </item>
- <item> ellipse </item>
- <item> hexagon </item>
- <item> rhomb </item>
- <item> rhomboid </item>
- <item> trapeze </item>
- <item> uptrapeze </item>
- <item> trapezoid </item>
- <item> uptrapezoid </item>
- <item> lparallelogram </item>
- <item> rparallelogram </item>
- </list>
- <list name="states">
- <item> unfolded </item>
- <item> folded </item>
- <item> boxed </item>
- <item> clustered </item>
- <item> wrapped </item>
- <item> exclusive </item>
- <item> white </item>
- </list>
- <list name="algorithms">
- <item> normal </item>
- <item> tree </item>
- <item> forcedir </item>
- <item> dfs </item>
- <item> minbackward </item>
- <item> maxdepth </item>
- <item> maxdepthslow </item>
- <item> mindepth </item>
- <item> mindepthslow </item>
- <item> minindegree </item>
- <item> minoutdegree </item>
- <item> maxindegree </item>
- <item> maxoutdegree </item>
- <item> maxdegree </item>
- <item> mindegree </item>
- </list>
- <list name="forcedir">
- <item> attraction </item>
- <item> repulsion </item>
- <item> randomfactor </item>
- <item> randomimpulse </item>
- <item> randomrounds </item>
- <item> tempscheme </item>
- <item> temptreshold </item>
- <item> tempmin </item>
- <item> tempmax </item>
- </list>
- <list name="magnetic">
- <item> no </item>
- <item> polar </item>
- <item> circular </item>
- <item> polcircular </item>
- <item> orthogonal </item>
- </list>
- <list name="orientation">
- <item> toptobottom </item>
- <item> bottomtotop </item>
- <item> lefttoright </item>
- <item> righttoleft </item>
- <item> top_to_bottom </item>
- <item> bottom_to_top </item>
- <item> left_to_right </item>
- <item> right_to_left </item>
- </list>
- <list name="lines">
- <item> solid </item>
- <item> continuous </item>
- <item> dashed </item>
- <item> dotted </item>
- <item> double </item>
- <item> triple </item>
- <item> invisible </item>
- </list>
- <list name="fisheye">
- <item> pfish </item>
- <item> cfish </item>
- <item> fpfish </item>
- <item> fcfish </item>
- <item> dpfish </item>
- <item> dcfish </item>
- </list>
- <contexts>
- <context name="default" attribute="Normal" lineEndContext="#stay">
- <Detect2Chars attribute="Comment" context="ccomment" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="cppcomment" char="/" char1="*"/>
- <StringDetect attribute="Keyword" context="#stay" String="focus"/>
- <RegExpr attribute="Keyword" context="#stay" String="(graph|edge|node|region|backedge|(left|right|)(bent|)nearedge):"/>
- <RegExpr attribute="Value" context="#stay" String="loc *:"/>
- <StringDetect attribute="Value" context="centry" String="colorentry"/>
- <RegExpr attribute="Value" context="arrowmode" String="arrow_?mode *:"/>
- <RegExpr attribute="Value" context="colorid" String="(foldnode.|node.|)(text|border|)color *:"/>
- <RegExpr attribute="Value" context="colorid" String="(foldedge.|edge.|)(arrow|backarrow|)color *:"/>
- <RegExpr attribute="Value" context="arrow" String="(foldedge.|edge.|)(arrow|backarrow)style *:"/>
- <RegExpr attribute="Value" context="lineid" String="(foldedge.|edge.|)linestyle *:"/>
- <RegExpr attribute="Value" context="lineid" String="(foldnode.|node.|)borderstyle *:"/>
- <RegExpr attribute="Value" context="fishid" String="view *:"/>
- <RegExpr attribute="Value" context="shapeid" String="(foldnode.|node.|)shape"/>
- <RegExpr attribute="Value" context="lquote" String="(source|target)(name|)"/>
- <RegExpr attribute="Value" context="lquote" String="title *:"/>
- <RegExpr attribute="Value" context="lquote" String="(foldnode.|node.|foldedge.|edge.|)label *:"/>
- <RegExpr attribute="Value" context="fontlq" String="(foldnode.|node.|foldedge.|edge.|)fontname *:"/>
- <RegExpr attribute="Value" context="lquote" String="infoname(1|2|3) *:"/>
- <RegExpr attribute="Value" context="lquote" String="(foldnode.|node.|)info(1|2|3) *:"/>
- <RegExpr attribute="Value" context="intval" String="spreadlevel *:"/>
- <RegExpr attribute="Value" context="nodelevel" String="(foldnode.|node.|)(level|vertical_?order) *:"/>
- <RegExpr attribute="Value" context="intval" String="(foldnode.|node.|foldedge.|edge.|)horizontal_?order *:"/>
- <RegExpr attribute="Value" context="stateid" String="stat(e|us) *:"/>
- <RegExpr attribute="Value" context="algid" String="layout_?algorithm *:"/>
- <RegExpr attribute="Value" context="boolean" String="crossing_?optimization *:"/>
- <RegExpr attribute="Value" context="boolean" String="crossing_?phase2 *:"/>
- <RegExpr attribute="Value" context="boolean" String="(dirty_edge_|display_edge_|displayedge|late_edge_|subgraph_?)labels *:"/>
- <RegExpr attribute="Value" context="boolean" String="s?manhatt(a|e)n_?edges *:"/>
- <RegExpr attribute="Value" context="boolean" String="(nodes|near_?edges|edges|splines) *:"/>
- <RegExpr attribute="Value" context="classname" String="classname"/>
- <RegExpr attribute="Value" context="orient" String="orientation *:"/>
- <RegExpr attribute="Value" context="nodealign" String="node_alignment *:"/>
- <RegExpr attribute="Value" context="textmode" String="(foldnode.|node.|)textmode *:"/>
- <RegExpr attribute="Value" context="boolean" String="equal_y_dist *:"/>
- <RegExpr attribute="Value" context="boolean" String="equal_?ydist *:"/>
- <RegExpr attribute="Value" context="weight" String="crossing_?weight *:"/>
- <RegExpr attribute="Value" context="boolean" String="(fast_?|)icons *:"/>
- <RegExpr attribute="Value" context="boolean" String="fine_?tuning *:"/>
- <RegExpr attribute="Value" context="boolean" String="(f?straight_?|priority_)phase *:"/>
- <RegExpr attribute="Value" context="boolean" String="ignore_?singles *:"/>
- <RegExpr attribute="Value" context="boolean" String="(in|out|)port_?sharing *:"/>
- <RegExpr attribute="Value" context="boolean" String="linear_?segments *:"/>
- <RegExpr attribute="Value" context="intval" String="(foldnode.|node.|)(height|width|borderwidth|stretch|shrink) *:"/>
- <RegExpr attribute="Value" context="intval" String="(foldedge.|edge.|)(arrowsize|backarrowsize|thickness|class|priority) *:"/>
- <RegExpr attribute="Value" context="intval" String="anchor *:"/>
- <RegExpr attribute="Value" context="intval" String="iconcolors *:"/>
- <RegExpr attribute="Value" context="intval" String="hidden *:"/>
- <RegExpr attribute="Value" context="boolean" String="energetic *:"/>
- <RegExpr attribute="Value" context="intval" String="layout_(up|down|near|spline)factor *:"/>
- <RegExpr attribute="Value" context="intval" String="border +(x|y) *:"/>
- <RegExpr attribute="Value" context="intval" String="splinefactor *:"/>
- <RegExpr attribute="Value" context="floatval" String="(gravity|tempfactor|treefactor) *:"/>
- <RegExpr attribute="Value" context="intval" String="(xspace|xbase|xmax|xraster|x) *:"/>
- <RegExpr attribute="Value" context="intval" String="(yspace|ybase|ymax|yraster|y) *:"/>
- <RegExpr attribute="Value" context="intval" String="(xlraster|xlspace) *:"/>
- <RegExpr attribute="Value" context="intval" String="magnetic_force(1|2) *:"/>
- <RegExpr attribute="Value" context="magnor" String="magnetic_field(1|2) *:"/>
- <RegExpr attribute="Value" context="intval" String="(a|b|c|fd|p|r|s)(max) *:"/>
- <RegExpr attribute="Value" context="intval" String="(c|p|r)(min) *:"/>
- <keyword attribute="Value" context="intval" String="forcedir"/>
- <RegExpr attribute="Value" context="scaling" String="scaling *:"/>
- <RegExpr attribute="Value" context="lquote" String="useraction(name|cmd)(1|2|3|4) *:"/>
- </context>
- <context name="string" attribute="String" lineEndContext="#stay">
- <DetectChar attribute="String" context="default" char="&quot;"/>
- <Detect2Chars attribute="Char" context="#stay" char="\" char1="&quot;"/>
- <RegExpr attribute="Char" context="#stay" String="\\(n|a|t|b)"/>
- <RegExpr attribute="Char" context="#stay" String="\\fi(0|1|2)[0-9][0-9]"/>
- <RegExpr attribute="Char" context="#stay" String="\\f(u|I|b|B|n|[0-9][0-9])"/>
- </context>
- <context name="scaling" attribute="Normal" lineEndContext="#stay">
- <StringDetect attribute="Datatype" context="default" String="maxspect"/>
- <Float attribute="Float" context="default"/>
- </context>
- <context name="ccomment" attribute="Comment" lineEndContext="default">
- </context>
- <context name="cppcomment" attribute="Comment" lineEndContext="#stay">
- <Detect2Chars attribute="Comment" context="default" char="*" char1="/"/>
- </context>
- <context name="colorid" attribute="Normal" lineEndContext="#stay">
- <keyword attribute="Datatype" context="default" String="colors"/>
- <RegExpr attribute="Datatype" context="default" String="[0-9][0-9]?"/>
- </context>
- <context name="shapeid" attribute="Normal" lineEndContext="#stay">
- <keyword attribute="Datatype" context="default" String="shapes"/>
- </context>
- <context name="lquote" attribute="Normal" lineEndContext="#stay">
- <DetectChar attribute="String" context="string" char="&quot;"/>
- </context>
- <context name="stateid" attribute="Normal" lineEndContext="#stay">
- <keyword attribute="Datatype" context="default" String="states"/>
- </context>
- <context name="algid" attribute="Normal" lineEndContext="#stay">
- <keyword attribute="Datatype" context="default" String="algorithms"/>
- </context>
- <context name="fishid" attribute="Normal" lineEndContext="#stay">
- <keyword attribute="Datatype" context="default" String="fisheye"/>
- </context>
- <context name="boolean" attribute="Normal" lineEndContext="#stay">
- <RegExpr attribute="Datatype" context="default" String="(yes|no)"/>
- </context>
- <context name="lineid" attribute="Normal" lineEndContext="#stay">
- <keyword attribute="Datatype" context="default" String="lines"/>
- </context>
- <context name="intval" attribute="Normal" lineEndContext="#stay">
- <Int attribute="Integer" context="longint"/>
- </context>
- <context name="longint" attribute="Normal" lineEndContext="default">
- <Int attribute="Integer" context="longint"/>
- <RegExpr attribute="Normal" context="default" String="\ "/>
- </context>
- <context name="centry" attribute="Normal" lineEndContext="default">
- <RegExpr attribute="Value" context="cecolon" String="[0-9][0-9]?"/>
- </context>
- <context name="rgb" attribute="Normal" lineEndContext="#stay">
- <RegExpr attribute="Integer" context="default" String="[0-9][0-9]?[0-9]? +[0-9][0-9]?[0-9]? +[0-9][0-9]?[0-9]?"/>
- </context>
- <context name="floatval" attribute="Normal" lineEndContext="#stay">
- <Float attribute="Float" context="default"/>
- </context>
- <context name="fontlq" attribute="Normal" lineEndContext="#stay">
- <DetectChar attribute="Datatype" context="fontbase" char="&quot;"/>
- </context>
- <context name="fontbase" attribute="Normal" lineEndContext="#stay">
- <RegExpr attribute="Datatype" context="fontsize" String="((tim|ncen)(R|B|I|BI)|(cour|helv)(R|B|O|BO)|symb)"/>
- </context>
- <context name="fontsize" attribute="Normal" lineEndContext="#stay">
- <RegExpr attribute="Datatype" context="#stay" String="(08|10|12|14|18|24)(.vcf|)"/>
- <DetectChar attribute="Datatype" context="default" char="&quot;"/>
- </context>
- <context name="arrow" attribute="Normal" lineEndContext="#stay">
- <RegExpr attribute="Datatype" context="default" String="(solid|line|none)"/>
- </context>
- <context name="arrowmode" attribute="Normal" lineEndContext="#stay">
- <RegExpr attribute="Datatype" context="default" String="(free|fixed)"/>
- </context>
- <context name="magnor" attribute="Normal" lineEndContext="#stay">
- <keyword attribute="Datatype" context="default" String="magnetic"/>
- <keyword attribute="Datatype" context="default" String="orientation"/>
- </context>
- <context name="orient" attribute="Normal" lineEndContext="#stay">
- <keyword attribute="Datatype" context="default" String="orientation"/>
- </context>
- <context name="nodealign" attribute="Normal" lineEndContext="#stay">
- <RegExpr attribute="Datatype" context="default" String="(top|center|bottom)"/>
- </context>
- <context name="nodelevel" attribute="Normal" lineEndContext="#stay">
- <StringDetect attribute="Datatype" context="default" String="maxlevel"/>
- <Int attribute="Integer" context="longint"/>
- </context>
- <context name="classname" attribute="Normal" lineEndContext="#stay">
- <RegExpr attribute="Value" context="#stay" String="[0-9]+"/>
- <DetectChar attribute="Value" context="lquote" char=":"/>
- </context>
- <context name="cecolon" attribute="Normal" lineEndContext="#stay">
- <DetectChar attribute="Value" context="rgb" char=":"/>
- </context>
- <context name="weight" attribute="Normal" lineEndContext="#stay">
- <RegExpr attribute="Datatype" context="default" String="(medianbary|barymedian|bary|median)"/>
- </context>
- <context name="textmode" attribute="Normal" lineEndContext="#stay">
- <RegExpr attribute="Datatype" context="default" String="(center|left_justify|right_justify)"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal" defStyleNum="dsNormal"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Integer" defStyleNum="dsDecVal"/>
- <itemData name="Datatype" defStyleNum="dsDataType"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Value" defStyleNum="dsOthers"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/"/>
- </comments>
- <keywords casesensitive="1"/>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!--
-
-*************************************************************************
-* *
-* Syntax highlighting for the GNU Assembler *
-* Copyright (C) 2002, John Zaitseff *
-* *
-*************************************************************************
-
-Updated: Roland Pabel <roland@pabel.name>
-Date: 15th August, 2002
-Version: 1.01
-
-Author: John Zaitseff <J.Zaitseff@zap.org.au>
-Date: 15th April, 2002
-Version: 1.0
-
-This file contains the XML syntax highlighting description for the GNU
-Assembler, for KATE, the KDE Advanced Editor. Keywords have been taken
-directly from the GNU Assembler source code (read.c).
-
-Known problems: Floating point highlighting does not work correctly.
-
-This program, including associated files, is free software. You may
-distribute 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. 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, Inc.,
-59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
--->
-
-<language name="GNU Assembler" version="1.04" kateversion="2.1" section="Sources"
- extensions="*.s;*.S" mimetype="text/x-asm"
- author="John Zaitseff (J.Zaitseff@zap.org.au), Roland Pabel (roland@pabel.name)" license="GPL">
- <highlighting>
- <list name="keywords">
- <item>.abort</item>
- <item>.align</item>
- <item>.appfile</item>
- <item>.appline</item>
- <item>.ascii</item>
- <item>.asciz</item>
- <item>.balign</item>
- <item>.balignl</item>
- <item>.balignw</item>
- <item>.byte</item>
- <item>.comm</item>
- <item>.common.s</item>
- <item>.common</item>
- <item>.data</item>
- <item>.dc.b</item>
- <item>.dc.d</item>
- <item>.dc.l</item>
- <item>.dc.s</item>
- <item>.dc.w</item>
- <item>.dc.x</item>
- <item>.dc</item>
- <item>.dcb.b</item>
- <item>.dcb.d</item>
- <item>.dcb.l</item>
- <item>.dcb.s</item>
- <item>.dcb.w</item>
- <item>.dcb.x</item>
- <item>.dcb</item>
- <item>.debug</item>
- <item>.def</item>
- <item>.desc</item>
- <item>.dim</item>
- <item>.double</item>
- <item>.ds.b</item>
- <item>.ds.d</item>
- <item>.ds.l</item>
- <item>.ds.p</item>
- <item>.ds.s</item>
- <item>.ds.w</item>
- <item>.ds.x</item>
- <item>.ds</item>
- <item>.dsect</item>
- <item>.eject</item>
- <item>.else</item>
- <item>.elsec</item>
- <item>.elseif</item>
- <item>.end</item>
- <item>.endc</item>
- <item>.endef</item>
- <item>.endfunc</item>
- <item>.endif</item>
- <item>.endm</item>
- <item>.endr</item>
- <item>.equ</item>
- <item>.equiv</item>
- <item>.err</item>
- <item>.exitm</item>
- <item>.extend</item>
- <item>.extern</item>
- <item>.fail</item>
- <item>.file</item>
- <item>.fill</item>
- <item>.float</item>
- <item>.format</item>
- <item>.func</item>
- <item>.global</item>
- <item>.globl</item>
- <item>.hidden</item>
- <item>.hword</item>
- <item>.ident</item>
- <item>.if</item>
- <item>.ifc</item>
- <item>.ifdef</item>
- <item>.ifeq</item>
- <item>.ifeqs</item>
- <item>.ifge</item>
- <item>.ifgt</item>
- <item>.ifle</item>
- <item>.iflt</item>
- <item>.ifnc</item>
- <item>.ifndef</item>
- <item>.ifne</item>
- <item>.ifnes</item>
- <item>.ifnotdef</item>
- <item>.include</item>
- <item>.int</item>
- <item>.internal</item>
- <item>.irep</item>
- <item>.irepc</item>
- <item>.irp</item>
- <item>.irpc</item>
- <item>.lcomm</item>
- <item>.lflags</item>
- <item>.line</item>
- <item>.linkonce</item>
- <item>.list</item>
- <item>.llen</item>
- <item>.ln</item>
- <item>.long</item>
- <item>.lsym</item>
- <item>.macro</item>
- <item>.mexit</item>
- <item>.name</item>
- <item>.noformat</item>
- <item>.nolist</item>
- <item>.nopage</item>
- <item>.octa</item>
- <item>.offset</item>
- <item>.org</item>
- <item>.p2align</item>
- <item>.p2alignl</item>
- <item>.p2alignw</item>
- <item>.page</item>
- <item>.plen</item>
- <item>.popsection</item>
- <item>.previous</item>
- <item>.print</item>
- <item>.protected</item>
- <item>.psize</item>
- <item>.purgem</item>
- <item>.pushsection</item>
- <item>.quad</item>
- <item>.rep</item>
- <item>.rept</item>
- <item>.rva</item>
- <item>.sbttl</item>
- <item>.scl</item>
- <item>.sect.s</item>
- <item>.sect</item>
- <item>.section.s</item>
- <item>.section</item>
- <item>.set</item>
- <item>.short</item>
- <item>.single</item>
- <item>.size</item>
- <item>.skip</item>
- <item>.sleb128</item>
- <item>.space</item>
- <item>.spc</item>
- <item>.stabd</item>
- <item>.stabn</item>
- <item>.stabs</item>
- <item>.string</item>
- <item>.struct</item>
- <item>.subsection</item>
- <item>.symver</item>
- <item>.tag</item>
- <item>.text</item>
- <item>.title</item>
- <item>.ttl</item>
- <item>.type</item>
- <item>.uleb128</item>
- <item>.use</item>
- <item>.val</item>
- <item>.version</item>
- <item>.vtable_entry</item>
- <item>.vtable_inherit</item>
- <item>.weak</item>
- <item>.word</item>
- <item>.xcom</item>
- <item>.xdef</item>
- <item>.xref</item>
- <item>.xstabs</item>
- <item>.zero</item>
- <!-- Directives specific to ARM -->
- <item>.arm</item>
- <item>.bss</item>
- <item>.code</item>
- <item>.even</item>
- <item>.force_thumb</item>
- <item>.ldouble</item>
- <item>.loc</item>
- <item>.ltorg</item>
- <item>.packed</item>
- <item>.pool</item>
- <item>.req</item>
- <item>.thumb</item>
- <item>.thumb_func</item>
- <item>.thumb_set</item>
- </list>
-
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <RegExpr attribute="Label" context="#stay" String="^\s*[A-Za-z0-9_.$]+:" />
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <HlCOct attribute="Octal" context="#stay" />
- <HlCHex attribute="Hex" context="#stay" />
- <RegExpr attribute="Binary" context="#stay" String="0[bB][01]+" />
- <Int attribute="Decimal" context="#stay" />
- <RegExpr attribute="Float" context="#stay" String="0[fFeEdD][-+]?[0-9]*\.?[0-9]*[eE]?[-+]?[0-9]+" />
- <RegExpr attribute="Normal Text" context="#stay" String="[A-Za-z_.$][A-Za-z0-9_.$]*" />
- <RegExpr attribute="Char" context="#stay" String="'(\\x[0-9a-fA-F][0-9a-fA-F]?|\\[0-7]?[0-7]?[0-7]?|\\.|.)" />
- <DetectChar attribute="String" context="String" char="&quot;" />
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="*" />
- <DetectChar attribute="Comment" context="Commentar 2" char="@" />
- <DetectChar attribute="Comment" context="Commentar 2" char=";" />
- <AnyChar attribute="Symbol" context="#stay" String="!#%&amp;*()+,-&lt;=&gt;?/:[]^{|}~" />
- <RegExpr attribute="Preprocessor" context="Preprocessor" String="^#" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar 1">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" />
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Commentar 2" />
- <context attribute="Preprocessor" lineEndContext="#pop" name="Preprocessor" />
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="Some Context" />
- <HlCStringChar attribute="String Char" context="#stay" />
- <DetectChar attribute="String" context="#pop" char="&quot;" />
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Some Context" />
- </contexts>
-
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Label" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="Decimal" defStyleNum="dsDecVal" />
- <itemData name="Octal" defStyleNum="dsBaseN" />
- <itemData name="Hex" defStyleNum="dsBaseN" />
- <itemData name="Binary" defStyleNum="dsBaseN" />
- <itemData name="Float" defStyleNum="dsFloat" />
- <itemData name="Char" defStyleNum="dsChar" />
- <itemData name="String" defStyleNum="dsString" />
- <itemData name="String Char" defStyleNum="dsChar" />
- <itemData name="Symbol" defStyleNum="dsNormal" />
- <itemData name="Comment" defStyleNum="dsComment" />
- <itemData name="Preprocessor" defStyleNum="dsOthers" />
- </itemDatas>
- </highlighting>
-
- <general>
- <comments>
- <comment name="singleLine" start=";" />
- <comment name="singleLine" start="@" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" weakDeliminator="_.$" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!-- Haskell syntax highlighting by Marcel Martin <mmar@freenet.de> -->
-<language name="Haskell" version="1.02" kateversion="2.1" section="Sources"
- extensions="*.hs"
- author="Marcel Martin (mmar@freenet.de)" license="">
- <highlighting>
- <list name="keywords">
- <item> case </item>
- <item> class </item>
- <item> data </item>
- <item> deriving </item>
- <item> do </item>
- <item> else </item>
- <item> if </item>
- <item> in </item>
- <item> infixl </item>
- <item> infixr </item>
- <item> instance </item>
- <item> let </item>
- <item> module </item>
- <item> of </item>
- <item> primitive </item>
- <item> then </item>
- <item> type </item>
- <item> where </item>
- </list>
- <list name="infix operators">
- <item> quot </item>
- <item> rem </item>
- <item> div </item>
- <item> mod </item>
- <item> elem </item>
- <item> notElem </item>
- <item> seq </item>
- </list>
- <list name="functions">
- <!--
- These operators are not handled yet.
- <item> !! </item>
- <item> % </item>
- <item> && </item>
- <item> $! </item>
- <item> $ </item>
- <item> * </item>
- <item> ** </item>
- <item> - </item>
- <item> . </item>
- <item> /= </item>
- <item> < </item>
- <item> <= </item>
- <item> =<< </item>
- <item> == </item>
- <item> > </item>
- <item> >= </item>
- <item> >> </item>
- <item> >>= </item>
- <item> ^ </item>
- <item> ^^ </item>
- <item> ++ </item>
- <item> || </item>
- //-->
-
- <item> FilePath </item>
- <item> IOError </item>
- <item> abs </item>
- <item> acos </item>
- <item> acosh </item>
- <item> all </item>
- <item> and </item>
- <item> any </item>
- <item> appendFile </item>
- <item> approxRational </item>
- <item> asTypeOf </item>
- <item> asin </item>
- <item> asinh </item>
- <item> atan </item>
- <item> atan2 </item>
- <item> atanh </item>
- <item> basicIORun </item>
- <item> break </item>
- <item> catch </item>
- <item> ceiling </item>
- <item> chr </item>
- <item> compare </item>
- <item> concat </item>
- <item> concatMap </item>
- <item> const </item>
- <item> cos </item>
- <item> cosh </item>
- <item> curry </item>
- <item> cycle </item>
- <item> decodeFloat </item>
- <item> denominator </item>
- <item> digitToInt </item>
- <item> div </item>
- <item> divMod </item>
- <item> drop </item>
- <item> dropWhile </item>
- <item> either </item>
- <item> elem </item>
- <item> encodeFloat </item>
- <item> enumFrom </item>
- <item> enumFromThen </item>
- <item> enumFromThenTo </item>
- <item> enumFromTo </item>
- <item> error </item>
- <item> even </item>
- <item> exp </item>
- <item> exponent </item>
- <item> fail </item>
- <item> filter </item>
- <item> flip </item>
- <item> floatDigits </item>
- <item> floatRadix </item>
- <item> floatRange </item>
- <item> floor </item>
- <item> fmap </item>
- <item> foldl </item>
- <item> foldl1 </item>
- <item> foldr </item>
- <item> foldr1 </item>
- <item> fromDouble </item>
- <item> fromEnum </item>
- <item> fromInt </item>
- <item> fromInteger </item>
- <item> fromIntegral </item>
- <item> fromRational </item>
- <item> fst </item>
- <item> gcd </item>
- <item> getChar </item>
- <item> getContents </item>
- <item> getLine </item>
- <item> head </item>
- <item> id </item>
- <item> inRange </item>
- <item> index </item>
- <item> init </item>
- <item> intToDigit </item>
- <item> interact </item>
- <item> ioError </item>
- <item> isAlpha </item>
- <item> isAlphaNum </item>
- <item> isAscii </item>
- <item> isControl </item>
- <item> isDenormalized </item>
- <item> isDigit </item>
- <item> isHexDigit </item>
- <item> isIEEE </item>
- <item> isInfinite </item>
- <item> isLower </item>
- <item> isNaN </item>
- <item> isNegativeZero </item>
- <item> isOctDigit </item>
- <item> isPrint </item>
- <item> isSpace </item>
- <item> isUpper </item>
- <item> iterate </item>
- <item> last </item>
- <item> lcm </item>
- <item> length </item>
- <item> lex </item>
- <item> lexDigits </item>
- <item> lexLitChar </item>
- <item> lines </item>
- <item> log </item>
- <item> logBase </item>
- <item> lookup </item>
- <item> map </item>
- <item> mapM </item>
- <item> mapM_ </item>
- <item> max </item>
- <item> maxBound </item>
- <item> maximum </item>
- <item> maybe </item>
- <item> min </item>
- <item> minBound </item>
- <item> minimum </item>
- <item> mod </item>
- <item> negate </item>
- <item> not </item>
- <item> notElem </item>
- <item> null </item>
- <item> numerator </item>
- <item> odd </item>
- <item> or </item>
- <item> ord </item>
- <item> otherwise </item>
- <item> pi </item>
- <item> pred </item>
- <item> primExitWith </item>
- <item> print </item>
- <item> product </item>
- <item> properFraction </item>
- <item> putChar </item>
- <item> putStr </item>
- <item> putStrLn </item>
- <item> quot </item>
- <item> quotRem </item>
- <item> range </item>
- <item> rangeSize </item>
- <item> read </item>
- <item> readDec </item>
- <item> readFile </item>
- <item> readFloat </item>
- <item> readHex </item>
- <item> readIO </item>
- <item> readInt </item>
- <item> readList </item>
- <item> readLitChar </item>
- <item> readLn </item>
- <item> readOct </item>
- <item> readParen </item>
- <item> readSigned </item>
- <item> reads </item>
- <item> readsPrec </item>
- <item> realToFrac </item>
- <item> recip </item>
- <item> rem </item>
- <item> repeat </item>
- <item> replicate </item>
- <item> return </item>
- <item> reverse </item>
- <item> round </item>
- <item> scaleFloat </item>
- <item> scanl </item>
- <item> scanl1 </item>
- <item> scanr </item>
- <item> scanr1 </item>
- <item> seq </item>
- <item> sequence </item>
- <item> sequence_ </item>
- <item> show </item>
- <item> showChar </item>
- <item> showInt </item>
- <item> showList </item>
- <item> showLitChar </item>
- <item> showParen </item>
- <item> showSigned </item>
- <item> showString </item>
- <item> shows </item>
- <item> showsPrec </item>
- <item> significand </item>
- <item> signum </item>
- <item> sin </item>
- <item> sinh </item>
- <item> snd </item>
- <item> span </item>
- <item> splitAt </item>
- <item> sqrt </item>
- <item> subtract </item>
- <item> succ </item>
- <item> sum </item>
- <item> tail </item>
- <item> take </item>
- <item> takeWhile </item>
- <item> tan </item>
- <item> tanh </item>
- <item> threadToIOResult </item>
- <item> toEnum </item>
- <item> toInt </item>
- <item> toInteger </item>
- <item> toLower </item>
- <item> toRational </item>
- <item> toUpper </item>
- <item> truncate </item>
- <item> uncurry </item>
- <item> undefined </item>
- <item> unlines </item>
- <item> until </item>
- <item> unwords </item>
- <item> unzip </item>
- <item> unzip3 </item>
- <item> userError </item>
- <item> words </item>
- <item> writeFile </item>
- <item> zip </item>
- <item> zip3 </item>
- <item> zipWith </item>
- <item> zipWith3 </item>
- </list>
- <list name="type constructors">
- <item> Bool </item>
- <item> Char </item>
- <item> Double </item>
- <item> Either </item>
- <item> Float </item>
- <item> IO </item>
- <item> Integer </item>
- <item> Int </item>
- <item> Maybe </item>
- <item> Ordering </item>
- <item> Rational </item>
- <item> Ratio </item>
- <item> ReadS </item>
- <item> ShowS </item>
- <item> String </item>
-
- </list>
- <list name="classes">
- <item> Bounded </item>
- <item> Enum </item>
- <item> Eq </item>
- <item> Floating </item>
- <item> Fractional </item>
- <item> Functor </item>
- <item> Integral </item>
- <item> Ix </item>
- <item> Monad </item>
- <item> Num </item>
- <item> Ord </item>
- <item> Read </item>
- <item> RealFloat </item>
- <item> RealFrac </item>
- <item> Real </item>
- <item> Show </item>
- </list>
- <list name="data constructors">
- <item> EQ </item>
- <item> False </item>
- <item> GT </item>
- <item> Just </item>
- <item> LT </item>
- <item> Left </item>
- <item> Nothing </item>
- <item> Right </item>
- <item> True </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="normal">
- <Detect2Chars attribute="Comment" context="comment_multi_line" char="{" char1="-" />
- <Detect2Chars attribute="Comment" context="comment_single_line" char="-" char1="-" />
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Class" context="#stay" String="classes" />
- <keyword attribute="Type Constructor" context="#stay" String="type constructors" />
- <keyword attribute="Function" context="#stay" String="functions" />
- <keyword attribute="Data Constructor" context="#stay" String="data constructors" />
- <DetectChar attribute="String" context="string" char="&quot;" />
- <DetectChar attribute="Infix Operator" context="infix" char="`"/>
- <RegExpr attribute="Normal Text" context="#stay" String="[A-Za-z0-9_][']+" />
- <DetectChar attribute="Char" context="single_char" char="'" />
- <RegExpr attribute="Function Definition" context="#stay" String="[a-z_]+[A-Za-z_0-9]*'*\s*::" />
- <Float attribute="Float" context="#stay" />
- <Int attribute="Decimal" context="#stay" />
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="comment_single_line" />
- <context attribute="Comment" lineEndContext="#stay" name="comment_multi_line">
- <Detect2Chars attribute="Comment" context="#pop" char="-" char1="}" />
- </context>
- <context attribute="String" lineEndContext="#stay" name="string">
- <RegExpr attribute="String" context="#stay" String="\\." />
- <DetectChar attribute="String" context="#pop" char="&quot;" />
- </context>
- <context attribute="Infix Operator" lineEndContext="#stay" name="infix">
- <DetectChar attribute="Infix Operator" context="#pop" char="`"/>
- </context>
- <context attribute="Char" lineEndContext="#pop" name="single_char">
- <RegExpr attribute="Char" context="#stay" String="\\." />
- <DetectChar attribute="Char" context="#pop" char="'" />
- </context>
- <context attribute="Function Definition" lineEndContext="#pop" name="function_definition">
- <DetectChar attribute="Function Definition" context="#pop" char=";" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Function" defStyleNum="dsOthers"/>
- <itemData name="Function Definition" defStyleNum="dsOthers"/>
- <itemData name="Class" defStyleNum="dsKeyword"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Constructor" defStyleNum="dsOthers"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Data Constructor" defStyleNum="dsKeyword"/>
- <itemData name="Type Constructor" defStyleNum="dsDataType"/>
- <itemData name="Infix Operator" defStyleNum="dsOthers"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="--" />
- <comment name="multiLine" start="{-" end="-}" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="HTML" version="1.05" kateversion="2.1" section="Markup" extensions="*.html;*.htm;*.shtml;*.shtm" mimetype="text/html">
- <highlighting>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="normal">
- <StringDetect attribute="Comment" context="comment" String="&lt;!--"/>
- <StringDetect attribute="Keyword" context="javascript_hook" String="&lt;SCRIPT" insensitive="TRUE" beginRegion="Script" />
- <StringDetect attribute="Keyword" context="CSS_hook" String="&lt;style" insensitive="TRUE" beginRegion="Style" />
-
- <RegExpr attribute="Keyword" context="tagname" String="&lt;\s*\/?\s*[a-zA-Z0-9_]*" />
- </context>
-
- <context attribute="Identifier" lineEndContext="#stay" name="tagname">
- <DetectChar attribute="Keyword" context="#pop" char="&gt;"/>
- <RegExpr attribute="Normal Text" context="values" String="\s*=\s*"/>
- </context>
-
- <context attribute="Wrong Values" lineEndContext="#stay" name="values">
- <RegExpr attribute="Types" context="#pop" String="\s*#?[a-zA-Z0-9]*" />
- <DetectChar attribute="Types" context="string" char="&quot;" />
- </context>
-
- <context attribute="Types" lineEndContext="#stay" name="string">
- <DetectChar attribute="Types" context="#pop#pop" char="&quot;" />
- </context>
-
- <context attribute="Comment" lineEndContext="#stay" name="comment">
- <StringDetect attribute="Comment" context="#pop" String="--&gt;"/>
- </context>
-
- <context attribute="Identifier" lineEndContext="#stay" name="javascript_hook">
- <DetectChar attribute="Keyword" context="javascript" char="&gt;"/>
- <RegExpr attribute="Normal Text" context="values" String="\s*=\s*"/>
- </context>
- <context attribute="Normal Text" lineEndContext="#stay" name="javascript">
- <Detect2Chars attribute="Comment" char="/" char1="/" context="javascript_comment"/>
- <StringDetect attribute="Keyword" context="#pop#pop" String="&lt;/SCRIPT&gt;" insensitive="TRUE" endRegion="Script"/>
- <IncludeRules context="##JavaScript"/>
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="javascript_comment">
- <StringDetect attribute="Keyword" context="#pop#pop#pop" String="&lt;/SCRIPT&gt;" insensitive="TRUE" endRegion="Script" />
- <RegExpr attribute="Wrong Values" context="#stay" String="(FIXME|TODO)" />
- </context>
-
- <context attribute="Identifier" lineEndContext="#stay" name="CSS_hook">
- <DetectChar attribute="Keyword" context="CSS" char="&gt;"/>
- <RegExpr attribute="Normal Text" context="values" String="\s*=\s*"/>
- </context>
- <context attribute="Normal Text" lineEndContext="#stay" name="CSS">
- <IncludeRules context="##CSS"/>
- <StringDetect attribute="Keyword" context="#pop#pop" String="&lt;/style&gt;" insensitive="TRUE" endRegion="Style"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Identifier" defStyleNum="dsOthers"/>
- <itemData name="Types" defStyleNum="dsDataType"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Wrong Values" defStyleNum="dsNormal" color="#ff0000" selColor="#ffffff" italic="0" bold="1"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="multiLine" start="&lt;!--" end="//--&gt;" />
- </comments>
- <keywords casesensitive="0" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Quake, Wolfenstein, Half-Life" version="1.02" kateversion="2.1" section="Games" extensions="*.cfg" mimetype="">
-
-<highlighting>
-<list name="Commands">
-<item> ForceCloseComman </item>
-<item> _config_com_baud </item>
-<item> _config_com_modem </item>
-<item> _vid_default_mode </item>
-<item> _vid_default_mode_win </item>
-<item> _vid_wait_override </item>
-<item> _windowed_mouse </item>
-<item> addip </item>
-<item> addressbook </item>
-<item> adjust_crosshair </item>
-<item> advancedupdate </item>
-<item> allow_download </item>
-<item> allow_download_maps </item>
-<item> allow_download_models </item>
-<item> allow_download_skins </item>
-<item> allow_download_sounds </item>
-<item> allskins </item>
-<item> appenddemo </item>
-<item> autosave </item>
-<item> ban </item>
-<item> banClient </item>
-<item> banUser </item>
-<item> banid </item>
-<item> baseskin </item>
-<item> begin </item>
-<item> bf </item>
-<item> bgetmod </item>
-<item> bindlist </item>
-<item> block_switch </item>
-<item> bottomcolor </item>
-<item> buyNow </item>
-<item> buyequip </item>
-<item> cache_endgather </item>
-<item> cache_flush </item>
-<item> cache_mapchange </item>
-<item> cache_print </item>
-<item> cache_profile </item>
-<item> cache_setindex </item>
-<item> cache_startgather </item>
-<item> cache_usedfile </item>
-<item> cancelselect </item>
-<item> cd </item>
-<item> centerview </item>
-<item> changeVectors </item>
-<item> changelevel </item>
-<item> changelevel2 </item>
-<item> changing </item>
-<item> chase_active </item>
-<item> cinematic </item>
-<item> cl_deadbodyfilter </item>
-<item> cl_gibfilter </item>
-<item> cl_hightrack </item>
-<item> cl_hudswap </item>
-<item> cl_messages </item>
-<item> cl_nodelta </item>
-<item> cl_nolerp </item>
-<item> cl_nopred </item>
-<item> cl_predict_players </item>
-<item> cl_rate </item>
-<item> cl_sbar </item>
-<item> cl_sbar_separator </item>
-<item> cl_shownet </item>
-<item> cl_sidespeed </item>
-<item> cl_solid_players </item>
-<item> cl_warncmd </item>
-<item> cl_writecfg </item>
-<item> clear </item>
-<item> clearplayers </item>
-<item> clientinfo </item>
-<item> clientkick </item>
-<item> cmd </item>
-<item> cmdline </item>
-<item> cmdlist </item>
-<item> color </item>
-<item> commands </item>
-<item> condebug </item>
-<item> condump </item>
-<item> configstrings </item>
-<item> confirm_quit </item>
-<item> connect </item>
-<item> contimes </item>
-<item> coop </item>
-<item> crash </item>
-<item> credits </item>
-<item> cropimages </item>
-<item> crosshair </item>
-<item> cvar_restart </item>
-<item> cvarlist </item>
-<item> d_mipcap </item>
-<item> d_subdiv16 </item>
-<item> deathmatch </item>
-<item> delta_clear </item>
-<item> delta_stats </item>
-<item> demo </item>
-<item> demolist </item>
-<item> demomap </item>
-<item> demos </item>
-<item> developer </item>
-<item> devmap </item>
-<item> dir </item>
-<item> disconnect </item>
-<item> dlfile </item>
-<item> dmoptions </item>
-<item> download </item>
-<item> drawradar </item>
-<item> drop </item>
-<item> dropclient </item>
-<item> dumpuser </item>
-<item> edict </item>
-<item> edictcount </item>
-<item> edicts </item>
-<item> endmovie </item>
-<item> entities </item>
-<item> envmap </item>
-<item> error </item>
-<item> escape </item>
-<item> exec </item>
-<item> exit </item>
-<item> fastsprites </item>
-<item> fdir </item>
-<item> filterban </item>
-<item> firstperson </item>
-<item> floodprot </item>
-<item> floodprotmsg </item>
-<item> flush </item>
-<item> fly </item>
-<item> force_centerview </item>
-<item> fov </item>
-<item> fraglogfile </item>
-<item> freelook </item>
-<item> freeze </item>
-<item> front </item>
-<item> fs_openedList </item>
-<item> fs_referencedList </item>
-<item> fullinfo </item>
-<item> fullserverinfo </item>
-<item> game </item>
-<item> gameCompleteStatus </item>
-<item> gamedir </item>
-<item> gamemap </item>
-<item> gameversion </item>
-<item> getcertificate </item>
-<item> gfxinfo </item>
-<item> gg </item>
-<item> gib </item>
-<item> gibload </item>
-<item> gibstats </item>
-<item> give </item>
-<item> gl_affinemodels </item>
-<item> gl_clear </item>
-<item> gl_colorlights </item>
-<item> gl_constretch </item>
-<item> gl_cull </item>
-<item> gl_dlight_lightmap </item>
-<item> gl_dlight_polyblend </item>
-<item> gl_dlight_smooth </item>
-<item> gl_fb_bmodels </item>
-<item> gl_fb_models </item>
-<item> gl_finish </item>
-<item> gl_fires </item>
-<item> gl_flashblend </item>
-<item> gl_keeptjunctions </item>
-<item> gl_lerp_anim </item>
-<item> gl_lightmode </item>
-<item> gl_max_size </item>
-<item> gl_multitexture </item>
-<item> gl_nobind </item>
-<item> gl_nocolors </item>
-<item> gl_picmip </item>
-<item> gl_playermip </item>
-<item> gl_polyblend </item>
-<item> gl_reportjunctions </item>
-<item> gl_sky_clip </item>
-<item> gl_skymultipass </item>
-<item> gl_smoothmodels </item>
-<item> gl_texsort </item>
-<item> gl_texturemode </item>
-<item> gl_triplebuffer </item>
-<item> gl_ztrick </item>
-<item> globalservers </item>
-<item> god </item>
-<item> gun </item>
-<item> gun_model </item>
-<item> gun_next </item>
-<item> gun_prev </item>
-<item> gunsmoke </item>
-<item> heartbeat </item>
-<item> help </item>
-<item> hideconsole </item>
-<item> hideradar </item>
-<item> host_speeds </item>
-<item> hostname </item>
-<item> hpkextract </item>
-<item> hpklist </item>
-<item> hpkremove </item>
-<item> hpkval </item>
-<item> hud_centerid </item>
-<item> imagelist </item>
-<item> impulse </item>
-<item> imt </item>
-<item> in_bind </item>
-<item> in_paste_buffer </item>
-<item> in_restart </item>
-<item> in_unbind </item>
-<item> info </item>
-<item> interp </item>
-<item> invdrop </item>
-<item> inven </item>
-<item> invnext </item>
-<item> invnextp </item>
-<item> invnextw </item>
-<item> invprev </item>
-<item> invprevp </item>
-<item> invprevw </item>
-<item> invuse </item>
-<item> joinserver </item>
-<item> joy </item>
-<item> joy_advancedupdate </item>
-<item> joy_enable </item>
-<item> joyadvanced </item>
-<item> joyadvancedupdat </item>
-<item> joyadvancedupdate </item>
-<item> joyname </item>
-<item> joystick </item>
-<item> keys </item>
-<item> kick </item>
-<item> kill </item>
-<item> killserver </item>
-<item> lefthand </item>
-<item> link </item>
-<item> list </item>
-<item> listdemo </item>
-<item> listen </item>
-<item> listid </item>
-<item> listip </item>
-<item> listmaps </item>
-<item> load </item>
-<item> loadas8bit </item>
-<item> loadgame </item>
-<item> loading </item>
-<item> loadsky </item>
-<item> loadtranslations </item>
-<item> loc </item>
-<item> localinfo </item>
-<item> localservers </item>
-<item> log </item>
-<item> logaddress </item>
-<item> logfile </item>
-<item> lookspring </item>
-<item> lookstrafe </item>
-<item> m_filter </item>
-<item> main </item>
-<item> map </item>
-<item> map_restart </item>
-<item> maplist </item>
-<item> maps </item>
-<item> maxplayers </item>
-<item> max_smokepuffs </item>
-<item> max_shells </item>
-<item> mcache </item>
-<item> meminfo </item>
-<item> menu </item>
-<item> menu_addressbook </item>
-<item> menu_credits </item>
-<item> menu_help </item>
-<item> menu_keys </item>
-<item> menu_load </item>
-<item> menu_loadgame </item>
-<item> menu_main </item>
-<item> menu_multiplayer </item>
-<item> menu_options </item>
-<item> menu_playerconfig </item>
-<item> menu_quit </item>
-<item> menu_save </item>
-<item> menu_savegame </item>
-<item> menu_setup </item>
-<item> menu_select </item>
-<item> menu_singleplayer </item>
-<item> menu_startserver </item>
-<item> menu_video </item>
-<item> menu_dmoptions </item>
-<item> menu_game </item>
-<item> menu_joinserver </item>
-<item> messagemode </item>
-<item> messagemode2 </item>
-<item> messagemode3 </item>
-<item> messagemode4 </item>
-<item> model </item>
-<item> modelist </item>
-<item> modellist </item>
-<item> msg </item>
-<item> multiplayer </item>
-<item> music </item>
-<item> name </item>
-<item> net_stats </item>
-<item> new </item>
-<item> next </item>
-<item> nextul </item>
-<item> nightvision </item>
-<item> no_pogo_stick </item>
-<item> noaim </item>
-<item> noclip </item>
-<item> noexit </item>
-<item> nomonsters </item>
-<item> noskins </item>
-<item> nosound </item>
-<item> notarget </item>
-<item> options </item>
-<item> packet </item>
-<item> password </item>
-<item> path </item>
-<item> pausable </item>
-<item> pause </item>
-<item> paused </item>
-<item> ping </item>
-<item> pingservers </item>
-<item> play </item>
-<item> playdemo </item>
-<item> playerconfig </item>
-<item> players </item>
-<item> playvol </item>
-<item> pushlatency </item>
-<item> pointfile </item>
-<item> ppdemostart </item>
-<item> pr_boundscheck </item>
-<item> precache </item>
-<item> prespawn </item>
-<item> prev </item>
-<item> profile </item>
-<item> profilequit </item>
-<item> prog </item>
-<item> quit </item>
-<item> r_drawentities </item>
-<item> r_drawflat </item>
-<item> r_draworder </item>
-<item> r_drawviewmodel </item>
-<item> r_dspeeds </item>
-<item> r_dynamic </item>
-<item> r_fullbright </item>
-<item> r_lightmap </item>
-<item> r_netgraph </item>
-<item> r_netgraph_box </item>
-<item> r_norefresh </item>
-<item> r_novis </item>
-<item> r_numedges </item>
-<item> r_numsurfs </item>
-<item> r_particles </item>
-<item> r_polymodelstats </item>
-<item> r_reportsurfout </item>
-<item> r_shadows </item>
-<item> r_speeds </item>
-<item> r_timegraph </item>
-<item> r_wateralpha </item>
-<item> r_waterripple </item>
-<item> r_waterwarp </item>
-<item> r_zgraph </item>
-<item> rcon </item>
-<item> rcon_password </item>
-<item> reconnect </item>
-<item> record </item>
-<item> registered </item>
-<item> reload </item>
-<item> removedemo </item>
-<item> removeid </item>
-<item> removeip </item>
-<item> rerecord </item>
-<item> reset </item>
-<item> resetrcon </item>
-<item> restart </item>
-<item> retry </item>
-<item> s_disable_a3d </item>
-<item> s_enable_a3d </item>
-<item> s_info </item>
-<item> s_list </item>
-<item> s_stop </item>
-<item> samelevel </item>
-<item> save </item>
-<item> savegame </item>
-<item> savetranslations </item>
-<item> score </item>
-<item> screenshot </item>
-<item> screenshotJPEG </item>
-<item> sectorlist </item>
-<item> sendents </item>
-<item> serverinfo </item>
-<item> serverprofile </item>
-<item> serverrecord </item>
-<item> serverstatus </item>
-<item> serverstop </item>
-<item> setRecommended </item>
-<item> setdemoinfo </item>
-<item> setenv </item>
-<item> setinfo </item>
-<item> setmaster </item>
-<item> setrom </item>
-<item> shaderlist </item>
-<item> show_fps </item>
-<item> show_time </item>
-<item> showdrop </item>
-<item> showinfo </item>
-<item> showip </item>
-<item> showpackets </item>
-<item> showpause </item>
-<item> showram </item>
-<item> showturtle </item>
-<item> shutdownserver </item>
-<item> singlePlayLink </item>
-<item> sizedown </item>
-<item> sizeup </item>
-<item> skill </item>
-<item> skin </item>
-<item> skinlist </item>
-<item> skins </item>
-<item> sky </item>
-<item> skyboxlist </item>
-<item> slist </item>
-<item> slot1 </item>
-<item> slot10 </item>
-<item> slot2 </item>
-<item> slot3 </item>
-<item> slot4 </item>
-<item> slot5 </item>
-<item> slot6 </item>
-<item> slot7 </item>
-<item> slot8 </item>
-<item> slot9 </item>
-<item> snap </item>
-<item> snapall </item>
-<item> snapshot </item>
-<item> snapto </item>
-<item> snd </item>
-<item> snd_noextraupdate </item>
-<item> snd_restart </item>
-<item> snd_show </item>
-<item> soundfade </item>
-<item> soundinfo </item>
-<item> soundlist </item>
-<item> spawn </item>
-<item> spdevmap </item>
-<item> speak </item>
-<item> special </item>
-<item> specmode </item>
-<item> spectator </item>
-<item> spectator_password </item>
-<item> spk </item>
-<item> spmap </item>
-<item> startLimboMode </item>
-<item> startSingleplayer </item>
-<item> startdemos </item>
-<item> startmovie </item>
-<item> startserver </item>
-<item> stat </item>
-<item> stats </item>
-<item> status </item>
-<item> stop </item>
-<item> stopLimboMode </item>
-<item> stopdemo </item>
-<item> stoprecord </item>
-<item> stopsound </item>
-<item> stopul </item>
-<item> streamingsound </item>
-<item> stuffcmd </item>
-<item> stuffcmds </item>
-<item> sv </item>
-<item> sv_allow_log </item>
-<item> sv_allow_pings </item>
-<item> sv_allow_status </item>
-<item> sv_gamedir </item>
-<item> sv_highchars </item>
-<item> sv_mapcheck </item>
-<item> sv_nostep </item>
-<item> sv_spectatormaxspeed </item>
-<item> sv_spetalk </item>
-<item> sv_maplist </item>
-<item> swapdemo </item>
-<item> sys_cpuid </item>
-<item> sys_dead_sleep </item>
-<item> sys_extrasleep </item>
-<item> sys_nostdout </item>
-<item> systeminfo </item>
-<item> taginfo </item>
-<item> team </item>
-<item> teamplay </item>
-<item> tell </item>
-<item> test </item>
-<item> test2 </item>
-<item> time </item>
-<item> thirdperson </item>
-<item> timedemo </item>
-<item> timeleft </item>
-<item> timerefresh </item>
-<item> toggle </item>
-<item> togglebrowser </item>
-<item> togglechat </item>
-<item> toggleconsole </item>
-<item> togglemenu </item>
-<item> topcolor </item>
-<item> touchFile </item>
-<item> trackplayer </item>
-<item> ui_restart </item>
-<item> unalias </item>
-<item> unbindall </item>
-<item> updatehunkusage </item>
-<item> updatescreen </item>
-<item> upload </item>
-<item> use </item>
-<item> user </item>
-<item> userinfo </item>
-<item> users </item>
-<item> v_centerspeed </item>
-<item> v_cshift </item>
-<item> v_idlescale </item>
-<item> version </item>
-<item> vid </item>
-<item> vid_center </item>
-<item> vid_config_x </item>
-<item> vid_describecurrentmode </item>
-<item> vid_describemode </item>
-<item> vid_describemodes </item>
-<item> vid_forcemode </item>
-<item> vid_fullscreen </item>
-<item> vid_fullscreen_mode </item>
-<item> vid_minimize </item>
-<item> vid_nopageflip </item>
-<item> vid_nummodes </item>
-<item> vid_restart </item>
-<item> vid_stretch_by_2 </item>
-<item> vid_testmode </item>
-<item> vid_windowed </item>
-<item> vid_windowed_mode </item>
-<item> vid_front </item>
-<item> video </item>
-<item> viewframe </item>
-<item> viewmodel </item>
-<item> viewnext </item>
-<item> viewpos </item>
-<item> viewprev </item>
-<item> vminfo </item>
-<item> vmprofile </item>
-<item> voice_showbanned </item>
-<item> votemap </item>
-<item> vstr </item>
-<item> wait </item>
-<item> watervis </item>
-<item> wave </item>
-<item> weapon </item>
-<item> weapon_knife </item>
-<item> weaplast </item>
-<item> weapnext </item>
-<item> weapprev </item>
-<item> windowsr_drawentities </item>
-<item> writecfg </item>
-<item> writeconfig </item>
-<item> writeid </item>
-<item> writeip </item>
-<item> z_stats </item>
-</list>
-
-
-<list name="Variables">
-<item> ah </item>
-<item> ActiveAction </item>
-<item> _cl_color </item>
-<item> _cl_name </item>
-<item> _config_com_baud </item>
-<item> _config_com_irq </item>
-<item> _config_com_modem </item>
-<item> _config_com_port </item>
-<item> _config_modem_clear </item>
-<item> _config_modem_dialtype </item>
-<item> _config_modem_hangup </item>
-<item> _config_modem_init </item>
-<item> _snd_mixahead </item>
-<item> _vid_default_mode </item>
-<item> _vid_default_mode_win </item>
-<item> _vid_wait_override </item>
-<item> _windowed_mouse </item>
-<item> address </item>
-<item> adr </item>
-<item> adr0 </item>
-<item> adr1 </item>
-<item> adr2 </item>
-<item> adr3 </item>
-<item> adr4 </item>
-<item> adr5 </item>
-<item> adr6 </item>
-<item> adr7 </item>
-<item> adr8 </item>
-<item> advanced </item>
-<item> advaxisr </item>
-<item> advaxisu </item>
-<item> advaxisv </item>
-<item> advaxisx </item>
-<item> advaxisy </item>
-<item> advaxisz </item>
-<item> airaccelerate </item>
-<item> allow </item>
-<item> allow_download_players </item>
-<item> ambient_fade </item>
-<item> ambient_level </item>
-<item> anglespeedkey </item>
-<item> arch </item>
-<item> array </item>
-<item> arrays </item>
-<item> att </item>
-<item> auto </item>
-<item> autoskins </item>
-<item> b </item>
-<item> bgmbuffer </item>
-<item> bgmvolume </item>
-<item> bit </item>
-<item> bitdepth </item>
-<item> blend </item>
-<item> bob </item>
-<item> bob_pitch </item>
-<item> bob_roll </item>
-<item> bob_up </item>
-<item> bot_aasoptimize </item>
-<item> bot_challenge </item>
-<item> bot_debug </item>
-<item> bot_developer </item>
-<item> bot_enable </item>
-<item> bot_fastchat </item>
-<item> bot_forceclustering </item>
-<item> bot_forcereachability </item>
-<item> bot_forcewrite </item>
-<item> bot_grapple </item>
-<item> bot_groundonly </item>
-<item> bot_interbreedbots </item>
-<item> bot_interbreedchar </item>
-<item> bot_interbreedcycle </item>
-<item> bot_interbreedwrite </item>
-<item> bot_maxdebugpolys </item>
-<item> bot_miniplayers </item>
-<item> bot_minplayers </item>
-<item> bot_nochat </item>
-<item> bot_pause </item>
-<item> bot_reachability </item>
-<item> bot_reloadcharacters </item>
-<item> bot_report </item>
-<item> bot_rocketjump </item>
-<item> bot_saveroutingcache </item>
-<item> bot_testclusters </item>
-<item> bot_testichat </item>
-<item> bot_testrchat </item>
-<item> bot_testsolid </item>
-<item> bot_thinktime </item>
-<item> bot_visualizejumppads </item>
-<item> brighten </item>
-<item> brightness </item>
-<item> broken </item>
-<item> cd </item>
-<item> cd_loopcount </item>
-<item> cd_looptrack </item>
-<item> cd_nocd </item>
-<item> cd_plugin </item>
-<item> centermove </item>
-<item> centerspeed </item>
-<item> centertime </item>
-<item> cg_autoactivate </item>
-<item> cg_autoswitch </item>
-<item> cg_blinktime </item>
-<item> cg_bloodTime </item>
-<item> cg_bobpitch </item>
-<item> cg_bobroll </item>
-<item> cg_bobup </item>
-<item> cg_brassTime </item>
-<item> cg_cameraOrbitDelay </item>
-<item> cg_clipboardName </item>
-<item> cg_coronafardist </item>
-<item> cg_coronas </item>
-<item> cg_crosshairAlpha </item>
-<item> cg_crosshairHealth </item>
-<item> cg_crosshairSize </item>
-<item> cg_crosshairX </item>
-<item> cg_crosshairY </item>
-<item> cg_currentSelectedPlayer </item>
-<item> cg_currentSelectedPlayerName </item>
-<item> cg_cursorHints </item>
-<item> cg_cycleAllWeaps </item>
-<item> cg_deferPlayers </item>
-<item> cg_descriptiveText </item>
-<item> cg_draw2D </item>
-<item> cg_draw3dIcons </item>
-<item> cg_drawAllWeaps </item>
-<item> cg_drawAmmoWarning </item>
-<item> cg_drawAttacker </item>
-<item> cg_drawCompass </item>
-<item> cg_drawCrosshair </item>
-<item> cg_drawCrosshairNames </item>
-<item> cg_drawCrosshairPickups </item>
-<item> cg_drawFPGun </item>
-<item> cg_drawFPS </item>
-<item> cg_drawFrags </item>
-<item> cg_drawGun </item>
-<item> cg_drawIcons </item>
-<item> cg_drawNotifyText </item>
-<item> cg_drawRewards </item>
-<item> cg_drawSnapshot </item>
-<item> cg_drawSpreadScale </item>
-<item> cg_drawStatus </item>
-<item> cg_drawTeamOverlay </item>
-<item> cg_drawTimer </item>
-<item> cg_emptyswitch </item>
-<item> cg_fov </item>
-<item> cg_forcemodel </item>
-<item> cg_gibs </item>
-<item> cg_hudAlpha </item>
-<item> cg_hudFiles </item>
-<item> cg_lagometer </item>
-<item> cg_marks </item>
-<item> cg_marktime </item>
-<item> cg_noplayeranims </item>
-<item> cg_nopredict </item>
-<item> cg_noTaunt </item>
-<item> cg_noVoiceChats </item>
-<item> cg_noVoiceText </item>
-<item> cg_particleDist </item>
-<item> cg_particleLOD </item>
-<item> cg_popupLimboMenu </item>
-<item> cg_predictItems </item>
-<item> cg_quickMessageAlt </item>
-<item> cg_railTrailTime </item>
-<item> cg_recoilPitch </item>
-<item> cg_reticleBrightness </item>
-<item> cg_reticleType </item>
-<item> cg_runpitch </item>
-<item> cg_runroll </item>
-<item> cg_scorePlums </item>
-<item> cg_selectedPlayer </item>
-<item> cg_selectedPlayerName </item>
-<item> cg_shadows </item>
-<item> cg_showblood </item>
-<item> cg_simpleItems </item>
-<item> cg_skybox </item>
-<item> cg_stereoSeparation </item>
-<item> cg_teamChatHeight </item>
-<item> cg_teamChatTime </item>
-<item> cg_teamChatsOnly </item>
-<item> cg_thirdperson </item>
-<item> cg_thirdpersonrange </item>
-<item> cg_thirdPersonAngle </item>
-<item> cg_useWeapsForZoom </item>
-<item> cg_uselessNostalgia </item>
-<item> cg_viewsize </item>
-<item> cg_voiceSpriteTime </item>
-<item> cg_weaponCycleDelay </item>
-<item> cg_wolfparticles </item>
-<item> cg_zoomDefaultBinoc </item>
-<item> cg_zoomDefaultFG </item>
-<item> cg_zoomDefaultSniper </item>
-<item> cg_zoomDefaultSnooper </item>
-<item> cg_zoomStepBinoc </item>
-<item> cg_zoomStepFG </item>
-<item> cg_zoomStepSnooper </item>
-<item> cg_zoomfov </item>
-<item> cg_zoomstepsniper </item>
-<item> chase_active </item>
-<item> chase_back </item>
-<item> chase_right </item>
-<item> chase_up </item>
-<item> cheats </item>
-<item> cl </item>
-<item> cl_allowDownload </item>
-<item> cl_anglespeedkey </item>
-<item> cl_anonymous </item>
-<item> cl_autoexec </item>
-<item> cl_autoskins </item>
-<item> cl_avidemo </item>
-<item> cl_backspeed </item>
-<item> cl_blend </item>
-<item> cl_bob </item>
-<item> cl_bobcycle </item>
-<item> cl_bobup </item>
-<item> cl_bypassMouseInput </item>
-<item> cl_cacheGathering </item>
-<item> cl_camera_maxpitch </item>
-<item> cl_camera_maxyaw </item>
-<item> cl_chasecam </item>
-<item> cl_chatmode </item>
-<item> cl_conXOffset </item>
-<item> cl_crossx </item>
-<item> cl_crossy </item>
-<item> cl_cshift_bonus </item>
-<item> cl_cshift_content </item>
-<item> cl_cshift_damage </item>
-<item> cl_cshift_powerup </item>
-<item> cl_debugMove </item>
-<item> cl_debugTranslation </item>
-<item> cl_demospeed </item>
-<item> cl_entities </item>
-<item> cl_footsteps </item>
-<item> cl_forceavidemo </item>
-<item> cl_forwardspeed </item>
-<item> cl_freelook </item>
-<item> cl_freezeDemo </item>
-<item> cl_gun </item>
-<item> cl_hidefrags </item>
-<item> cl_hightrack </item>
-<item> cl_hudswap </item>
-<item> cl_language </item>
-<item> cl_lights </item>
-<item> cl_maxPing </item>
-<item> cl_maxfps </item>
-<item> cl_maxpackets </item>
-<item> cl_motd </item>
-<item> cl_motdString </item>
-<item> cl_mouseAccel </item>
-<item> cl_movespeedkey </item>
-<item> cl_nodelta </item>
-<item> cl_nofake </item>
-<item> cl_nolerp </item>
-<item> cl_nopred </item>
-<item> cl_noprint </item>
-<item> cl_noskins </item>
-<item> cl_packetdup </item>
-<item> cl_parsesay </item>
-<item> cl_particles </item>
-<item> cl_paused </item>
-<item> cl_pitchspeed </item>
-<item> cl_predict </item>
-<item> cl_predict_players </item>
-<item> cl_predict_players2 </item>
-<item> cl_observercrosshair </item>
-<item> cl_quakerc </item>
-<item> cl_rollangle </item>
-<item> cl_rollspeed </item>
-<item> cl_run </item>
-<item> cl_running </item>
-<item> cl_serverStatusResendTime </item>
-<item> cl_showfps </item>
-<item> cl_showSend </item>
-<item> cl_showServerCommands </item>
-<item> cl_showTimeDelta </item>
-<item> cl_showmiss </item>
-<item> cl_showmouserate </item>
-<item> cl_shownet </item>
-<item> cl_shownuments </item>
-<item> cl_sidespeed </item>
-<item> cl_stats </item>
-<item> cl_stereo </item>
-<item> cl_stereo_separation </item>
-<item> cl_testblend </item>
-<item> cl_testentities </item>
-<item> cl_testlights </item>
-<item> cl_testparticles </item>
-<item> cl_timeNudge </item>
-<item> cl_timeout </item>
-<item> cl_upspeed </item>
-<item> cl_verstring </item>
-<item> cl_visibleClients </item>
-<item> cl_vwep </item>
-<item> cl_waitForFire </item>
-<item> cl_wavefilerecord </item>
-<item> cl_yawspeed </item>
-<item> clear </item>
-<item> clearcolor </item>
-<item> clientport </item>
-<item> cm_playerCurveClip </item>
-<item> cmd_highchars </item>
-<item> cmd_warncmd </item>
-<item> cmdlist </item>
-<item> color </item>
-<item> color1 </item>
-<item> color2 </item>
-<item> com_blood </item>
-<item> com_buildScript </item>
-<item> com_cameraMode </item>
-<item> com_dropsim </item>
-<item> com_hunkMegs </item>
-<item> com_hunkused </item>
-<item> com_introplayed </item>
-<item> com_maxfps </item>
-<item> com_recommendedSet </item>
-<item> com_showtrace </item>
-<item> com_soundMegs </item>
-<item> com_speeds </item>
-<item> com_zoneMegs </item>
-<item> compiled </item>
-<item> con_debug </item>
-<item> con_notifytime </item>
-<item> con_restricted </item>
-<item> conspeed </item>
-<item> contrast </item>
-<item> coop </item>
-<item> crosshair </item>
-<item> crosshaircolor </item>
-<item> cull </item>
-<item> d_mipcap </item>
-<item> d_mipscale </item>
-<item> deathmatch </item>
-<item> debug_protocol </item>
-<item> debuggraph </item>
-<item> dedicated </item>
-<item> devdll </item>
-<item> developer </item>
-<item> dlabs </item>
-<item> dmflags </item>
-<item> dm </item>
-<item> down </item>
-<item> download </item>
-<item> drawall </item>
-<item> drawbuffer </item>
-<item> drawentities </item>
-<item> drawflat </item>
-<item> draworder </item>
-<item> drawworld </item>
-<item> driver </item>
-<item> dspeeds </item>
-<item> dynamic </item>
-<item> easter_eggs </item>
-<item> edgefriction </item>
-<item> empty </item>
-<item> enforcetime </item>
-<item> entities </item>
-<item> entlatency </item>
-<item> ext </item>
-<item> filter </item>
-<item> filterban </item>
-<item> finish </item>
-<item> fixedtime </item>
-<item> flashblend </item>
-<item> flood </item>
-<item> flood_msgs </item>
-<item> flood_persecond </item>
-<item> flood_waitdelay </item>
-<item> flushmap </item>
-<item> footsteps </item>
-<item> forward </item>
-<item> forwardsensitivity </item>
-<item> forwardspeed </item>
-<item> forwardthreshold </item>
-<item> fov </item>
-<item> fraglimit </item>
-<item> freelook </item>
-<item> fs_basegame </item>
-<item> fs_basepath </item>
-<item> fs_cdpath </item>
-<item> fs_copyfiles </item>
-<item> fs_debug </item>
-<item> fs_game </item>
-<item> fs_globalcfg </item>
-<item> fs_homepath </item>
-<item> fs_pluginpath </item>
-<item> fs_restrict </item>
-<item> fs_sharepath </item>
-<item> fs_skinbase </item>
-<item> fs_usercfg </item>
-<item> fs_userpath </item>
-<item> fullbright </item>
-<item> fullscreen </item>
-<item> g_allowvote </item>
-<item> g_altStopwatchMode </item>
-<item> g_arenasFile </item>
-<item> g_blueTeam </item>
-<item> g_botsFile </item>
-<item> g_complaintlimit </item>
-<item> g_currentRound </item>
-<item> g_friendlyFire </item>
-<item> g_gameskill </item>
-<item> g_gametype </item>
-<item> g_maxlives </item>
-<item> g_minGameClients </item>
-<item> g_missionStats </item>
-<item> g_nextTimeLimit </item>
-<item> g_noTeamSwitching </item>
-<item> g_redTeam </item>
-<item> g_select_empty </item>
-<item> g_spAwards </item>
-<item> g_spScores1 </item>
-<item> g_spScores2 </item>
-<item> g_spScores3 </item>
-<item> g_spScores4 </item>
-<item> g_spScores5 </item>
-<item> g_spSkill </item>
-<item> g_spVideos </item>
-<item> g_userAlliedRespawnTime </item>
-<item> g_userAxisRespawnTime </item>
-<item> g_userTimeLimit </item>
-<item> game </item>
-<item> gamecfg </item>
-<item> gamedate </item>
-<item> gamedir </item>
-<item> gamename </item>
-<item> gamestate </item>
-<item> gamma </item>
-<item> gender </item>
-<item> gender_auto </item>
-<item> gl_3dlabs_broken </item>
-<item> gl_allow_software </item>
-<item> gl_bitdepth </item>
-<item> gl_clear </item>
-<item> gl_conalpha </item>
-<item> gl_conspin </item>
-<item> gl_cshiftpercent </item>
-<item> gl_cull </item>
-<item> gl_drawbuffer </item>
-<item> gl_driver </item>
-<item> gl_dynamic </item>
-<item> gl_ext_compiled_vertex_array </item>
-<item> gl_ext_multitexture </item>
-<item> gl_ext_palettedtexture </item>
-<item> gl_ext_pointparameters </item>
-<item> gl_ext_swapinterval </item>
-<item> gl_finish </item>
-<item> gl_flashblend </item>
-<item> gl_keeptjunctions </item>
-<item> gl_lightmap </item>
-<item> gl_lightmap_align </item>
-<item> gl_lightmap_subimage </item>
-<item> gl_lockpvs </item>
-<item> gl_log </item>
-<item> gl_max_size </item>
-<item> gl_mesh_cache </item>
-<item> gl_mode </item>
-<item> gl_modulate </item>
-<item> gl_monolightmap </item>
-<item> gl_nobind </item>
-<item> gl_nocolors </item>
-<item> gl_nosubimage </item>
-<item> gl_occlusion </item>
-<item> gl_particle_att_a </item>
-<item> gl_particle_att_b </item>
-<item> gl_particle_att_c </item>
-<item> gl_particle_max_size </item>
-<item> gl_particle_min_size </item>
-<item> gl_particle_mip </item>
-<item> gl_particle_size </item>
-<item> gl_picmip </item>
-<item> gl_playermip </item>
-<item> gl_polyblend </item>
-<item> gl_reporttjunctions </item>
-<item> gl_round_down </item>
-<item> gl_saturatelighting </item>
-<item> gl_screenshot_byte_swap </item>
-<item> gl_shadows </item>
-<item> gl_showtris </item>
-<item> gl_sky_debug </item>
-<item> gl_sky_divide </item>
-<item> gl_skymip </item>
-<item> gl_smoothmodels </item>
-<item> gl_subdivide_size </item>
-<item> gl_swapinterval </item>
-<item> gl_texsort </item>
-<item> gl_texturealphamode </item>
-<item> gl_texturemode </item>
-<item> gl_texturesolidmode </item>
-<item> gl_triplebuffer </item>
-<item> gl_vertex_arrays </item>
-<item> gl_ztrick </item>
-<item> graphheight </item>
-<item> graphscale </item>
-<item> graphshift </item>
-<item> gravity </item>
-<item> gun </item>
-<item> gun_x </item>
-<item> gun_y </item>
-<item> gun_z </item>
-<item> hand </item>
-<item> handicap </item>
-<item> head </item>
-<item> headModel </item>
-<item> headmodel </item>
-<item> host </item>
-<item> host_framerate </item>
-<item> host_speeds </item>
-<item> hostname </item>
-<item> hostport </item>
-<item> hud_fastswitch </item>
-<item> in </item>
-<item> in_amp </item>
-<item> in_bind_imt </item>
-<item> in_debugjoystick </item>
-<item> in_dga </item>
-<item> in_dga_mouseaccel </item>
-<item> in_dgamouse </item>
-<item> in_grab </item>
-<item> in_joystick </item>
-<item> in_midi </item>
-<item> in_mouse </item>
-<item> in_mouse_amp </item>
-<item> in_mouse_filter </item>
-<item> in_mouse_pre_amp </item>
-<item> in_pre_amp </item>
-<item> initsound </item>
-<item> intensity </item>
-<item> ip </item>
-<item> ip_clientport </item>
-<item> ip_hostport </item>
-<item> ipx </item>
-<item> ipx_clientport </item>
-<item> ipx_hostport </item>
-<item> journal </item>
-<item> joy </item>
-<item> joy_advanced </item>
-<item> joy_advaxisr </item>
-<item> joy_advaxisu </item>
-<item> joy_advaxisv </item>
-<item> joy_advaxisx </item>
-<item> joy_advaxisy </item>
-<item> joy_advaxisz </item>
-<item> joy_amp </item>
-<item> joy_device </item>
-<item> joy_forwardsensitivity </item>
-<item> joy_forwardthreshold </item>
-<item> joy_name </item>
-<item> joy_pitchsensitivity </item>
-<item> joy_pitchthreshold </item>
-<item> joy_pre_amp </item>
-<item> joy_sensitivity </item>
-<item> joy_sidesensitivity </item>
-<item> joy_sidethreshold </item>
-<item> joy_threshold </item>
-<item> joy_upsensitivity </item>
-<item> joy_upthreshold </item>
-<item> joy_yawsensitivity </item>
-<item> joy_yawthreshold </item>
-<item> joyadvanced </item>
-<item> joyadvaxisr </item>
-<item> joyadvaxisu </item>
-<item> joyadvaxisv </item>
-<item> joyadvaxisx </item>
-<item> joyadvaxisy </item>
-<item> joyadvaxisz </item>
-<item> joyaxis1 </item>
-<item> joyaxis2 </item>
-<item> joyaxis3 </item>
-<item> joyaxis4 </item>
-<item> joyaxis5 </item>
-<item> joyaxis6 </item>
-<item> joyaxis7 </item>
-<item> joyaxis8 </item>
-<item> joyforwardsensitivity </item>
-<item> joyforwardthreshold </item>
-<item> joyname </item>
-<item> joypitchsensitivity </item>
-<item> joypitchthreshold </item>
-<item> joysidesensitivity </item>
-<item> joysidethreshold </item>
-<item> joystick </item>
-<item> joywwhack1 </item>
-<item> joywwhack2 </item>
-<item> joyyawsensitivity </item>
-<item> joyyawthreshold </item>
-<item> khz </item>
-<item> lcd_x </item>
-<item> lcd_yaw </item>
-<item> lerpmodels </item>
-<item> lightmap </item>
-<item> lights </item>
-<item> limit </item>
-<item> listen </item>
-<item> loadas </item>
-<item> loadas8bit </item>
-<item> localid </item>
-<item> lockpvs </item>
-<item> log </item>
-<item> log_stats </item>
-<item> logfile </item>
-<item> lookspring </item>
-<item> lookstrafe </item>
-<item> loopcount </item>
-<item> looptrack </item>
-<item> m_filter </item>
-<item> m_forward </item>
-<item> m_pitch </item>
-<item> m_side </item>
-<item> m_yaw </item>
-<item> mapname </item>
-<item> maps </item>
-<item> max </item>
-<item> maxclients </item>
-<item> maxedges </item>
-<item> maxentities </item>
-<item> maxfps </item>
-<item> maxplayers </item>
-<item> maxspectators </item>
-<item> maxsurfs </item>
-<item> maxvelocity </item>
-<item> min </item>
-<item> mipcap </item>
-<item> mipscale </item>
-<item> mixahead </item>
-<item> mode </item>
-<item> model </item>
-<item> models </item>
-<item> modex </item>
-<item> modulate </item>
-<item> monolightmap </item>
-<item> mouse </item>
-<item> mp_currentPlayerType </item>
-<item> mp_currentTeam </item>
-<item> mp_playerType </item>
-<item> mp_team </item>
-<item> mp_weapon </item>
-<item> mp_autokick </item>
-<item> mp_autoteambalance </item>
-<item> mp_c4timer </item>
-<item> mp_flashlight </item>
-<item> mp_footsteps </item>
-<item> mp_forcechasecam </item>
-<item> mp_freezetime </item>
-<item> mp_friendlyfire </item>
-<item> mp_hostagepenalty </item>
-<item> mp_limitteams </item>
-<item> mp_logmessages </item>
-<item> mp_mapvoteration </item>
-<item> mp_roundtime </item>
-<item> mp_timelimit </item>
-<item> mp_tkpunish </item>
-<item> msg </item>
-<item> msgs </item>
-<item> multitexture </item>
-<item> name </item>
-<item> net_graph </item>
-<item> net_ip </item>
-<item> net_messagetimeout </item>
-<item> net_noudp </item>
-<item> net_port </item>
-<item> net_qport </item>
-<item> net_restart </item>
-<item> netdosexpire </item>
-<item> netdosvalues </item>
-<item> netgraph </item>
-<item> nextdemo </item>
-<item> nextmap </item>
-<item> nextserver </item>
-<item> noalttab </item>
-<item> nobind </item>
-<item> nocd </item>
-<item> nocull </item>
-<item> nodelta </item>
-<item> noexit </item>
-<item> nomonsters </item>
-<item> norefresh </item>
-<item> noreload </item>
-<item> noskins </item>
-<item> nosound </item>
-<item> nosubimage </item>
-<item> novis </item>
-<item> palettedtexture </item>
-<item> particle </item>
-<item> particles </item>
-<item> password </item>
-<item> pausable </item>
-<item> persecond </item>
-<item> picmip </item>
-<item> pitch </item>
-<item> pitchsensitivity </item>
-<item> pitchspeed </item>
-<item> pitchthreshold </item>
-<item> playermip </item>
-<item> players </item>
-<item> pointparameters </item>
-<item> polyblend </item>
-<item> polymodelstats </item>
-<item> port </item>
-<item> pr_checkextensions </item>
-<item> pr_deadbeef_ents </item>
-<item> pr_deadbeef_locals </item>
-<item> pr_debug </item>
-<item> pr_source_path </item>
-<item> precache </item>
-<item> predict </item>
-<item> primary </item>
-<item> printspeed </item>
-<item> protocol </item>
-<item> public </item>
-<item> pushlatency </item>
-<item> qport </item>
-<item> r_aliastransadj </item>
-<item> r_aliastransbase </item>
-<item> r_allowExtensions </item>
-<item> r_allowSoftwareGL </item>
-<item> r_ambient </item>
-<item> r_ambientScale </item>
-<item> r_bonesDebug </item>
-<item> r_cache </item>
-<item> r_cacheModels </item>
-<item> r_cacheShaders </item>
-<item> r_clear </item>
-<item> r_clearcolor </item>
-<item> r_colorMipLevels </item>
-<item> r_colorbits </item>
-<item> r_compressModels </item>
-<item> r_customaspect </item>
-<item> r_customheight </item>
-<item> r_customwidth </item>
-<item> r_debugSort </item>
-<item> r_debugSurface </item>
-<item> r_debuglight </item>
-<item> r_depthbits </item>
-<item> r_detailtextures </item>
-<item> r_directedScale </item>
-<item> r_displayRefresh </item>
-<item> r_dlightBacks </item>
-<item> r_dlight_lightmap </item>
-<item> r_dlight_max </item>
-<item> r_drawBuffer </item>
-<item> r_drawSun </item>
-<item> r_drawentities </item>
-<item> r_drawexplosions </item>
-<item> r_drawflat </item>
-<item> r_draworder </item>
-<item> r_drawviewmodel </item>
-<item> r_drawworld </item>
-<item> r_dspeeds </item>
-<item> r_dynamic </item>
-<item> r_dynamiclight </item>
-<item> r_explosionclip </item>
-<item> r_exportCompressedModels </item>
-<item> r_ext_compiled_vertex_array </item>
-<item> r_ext_compress_textures </item>
-<item> r_ext_compressed_textures </item>
-<item> r_ext_gamma_control </item>
-<item> r_ext_multitexture </item>
-<item> r_ext_texture_env_add </item>
-<item> r_facePlaneCull </item>
-<item> r_fastsky </item>
-<item> r_finish </item>
-<item> r_firecolor </item>
-<item> r_flareFade </item>
-<item> r_flareSize </item>
-<item> r_flares </item>
-<item> r_fullbright </item>
-<item> r_fullscreen </item>
-<item> r_gamma </item>
-<item> r_glDriver </item>
-<item> r_glIgnoreWicked3D </item>
-<item> r_graphheight </item>
-<item> r_highQualit </item>
-<item> r_highQualityVideo </item>
-<item> r_ignore </item>
-<item> r_ignoreFastPath </item>
-<item> r_ignoreGLErrors </item>
-<item> r_ignorehwgamma </item>
-<item> r_inGameVideo </item>
-<item> r_intensity </item>
-<item> r_lastValidRenderer </item>
-<item> r_lerpmodels </item>
-<item> r_lightmap </item>
-<item> r_lightmap_components </item>
-<item> r_lockpvs </item>
-<item> r_lodCurveError </item>
-<item> r_lodbias </item>
-<item> r_lodscale </item>
-<item> r_logFile </item>
-<item> r_lowMemTextureSize </item>
-<item> r_lowMemTextureThreshold </item>
-<item> r_mapOverBrightBits </item>
-<item> r_maxedges </item>
-<item> r_maxpolys </item>
-<item> r_maxpolyverts </item>
-<item> r_maxsurfs </item>
-<item> r_measureOverdraw </item>
-<item> r_mirroralpha </item>
-<item> r_mode </item>
-<item> r_netgraph </item>
-<item> r_netgraph_alpha </item>
-<item> r_nobind </item>
-<item> r_nocull </item>
-<item> r_nocurves </item>
-<item> r_noportals </item>
-<item> r_norefresh </item>
-<item> r_novis </item>
-<item> r_numedges </item>
-<item> r_numsurfs </item>
-<item> r_offsetfactor </item>
-<item> r_offsetunits </item>
-<item> r_overBrightBits </item>
-<item> r_particles_max </item>
-<item> r_particles_style </item>
-<item> r_picmip </item>
-<item> r_picmip2 </item>
-<item> r_polymodelstats </item>
-<item> r_portalOnly </item>
-<item> r_preloadTextures </item>
-<item> r_previousglDriver </item>
-<item> r_primitives </item>
-<item> r_printShaders </item>
-<item> r_railCoreWidth </item>
-<item> r_railSegmentLength </item>
-<item> r_railWidth </item>
-<item> r_reportedgeout </item>
-<item> r_reportsurfout </item>
-<item> r_rmse </item>
-<item> r_roundImagesDown </item>
-<item> r_saveFontData </item>
-<item> r_shadows </item>
-<item> r_showImages </item>
-<item> r_showSmp </item>
-<item> r_showcluster </item>
-<item> r_shownormals </item>
-<item> r_showsky </item>
-<item> r_showtris </item>
-<item> r_simpleMipMaps </item>
-<item> r_singleShader </item>
-<item> r_skipBackEnd </item>
-<item> r_skyname </item>
-<item> r_smp </item>
-<item> r_speeds </item>
-<item> r_stencilbits </item>
-<item> r_stereo </item>
-<item> r_subdivisions </item>
-<item> r_swapInterval </item>
-<item> r_textureMode </item>
-<item> r_texturebits </item>
-<item> r_timegraph </item>
-<item> r_uiFullScreen </item>
-<item> r_verbose </item>
-<item> r_vertexLight </item>
-<item> r_wateralpha </item>
-<item> r_waterwarp </item>
-<item> r_wolffog </item>
-<item> r_zfar </item>
-<item> r_znear </item>
-<item> rate </item>
-<item> rcon </item>
-<item> rconAddress </item>
-<item> rconPassword </item>
-<item> rcon_address </item>
-<item> rcon_password </item>
-<item> reconnect </item>
-<item> ref </item>
-<item> registered </item>
-<item> reportedgeout </item>
-<item> reportsurfout </item>
-<item> roll </item>
-<item> rollangle </item>
-<item> rollspeed </item>
-<item> round </item>
-<item> run </item>
-<item> run_pitch </item>
-<item> run_roll </item>
-<item> s_compression </item>
-<item> s_defaultsound </item>
-<item> s_doppler </item>
-<item> s_initsound </item>
-<item> s_khz </item>
-<item> s_loadas8bit </item>
-<item> s_mixPreStep </item>
-<item> s_mixahead </item>
-<item> s_musicvolume </item>
-<item> s_mute </item>
-<item> s_nocompressed </item>
-<item> s_usingA3D </item>
-<item> s_primary </item>
-<item> s_separation </item>
-<item> s_show </item>
-<item> s_testsound </item>
-<item> s_volume </item>
-<item> s_wavonly </item>
-<item> samelevel </item>
-<item> saturatelighting </item>
-<item> saved1 </item>
-<item> saved2 </item>
-<item> saved3 </item>
-<item> saved4 </item>
-<item> savedgamecfg </item>
-<item> scr </item>
-<item> scr_centertime </item>
-<item> scr_consize </item>
-<item> scr_conspeed </item>
-<item> scr_drawall </item>
-<item> scr_ofsx </item>
-<item> scr_ofsy </item>
-<item> scr_ofsz </item>
-<item> scr_printspeed </item>
-<item> scr_showpause </item>
-<item> scr_showturtle </item>
-<item> scratch1 </item>
-<item> scratch2 </item>
-<item> scratch3 </item>
-<item> scratch4 </item>
-<item> screenshot </item>
-<item> select </item>
-<item> sensitivity </item>
-<item> separation </item>
-<item> server1 </item>
-<item> server10 </item>
-<item> server11 </item>
-<item> server12 </item>
-<item> server13 </item>
-<item> server14 </item>
-<item> server15 </item>
-<item> server16 </item>
-<item> server2 </item>
-<item> server3 </item>
-<item> server4 </item>
-<item> server5 </item>
-<item> server6 </item>
-<item> server7 </item>
-<item> server8 </item>
-<item> server9 </item>
-<item> serverprofile </item>
-<item> sex </item>
-<item> shadows </item>
-<item> show </item>
-<item> showclamp </item>
-<item> showdrop </item>
-<item> showmiss </item>
-<item> shownet </item>
-<item> showpackets </item>
-<item> showpause </item>
-<item> showram </item>
-<item> showtrace </item>
-<item> showtris </item>
-<item> showturtle </item>
-<item> side </item>
-<item> sidesensitivity </item>
-<item> sidespeed </item>
-<item> sidethreshold </item>
-<item> size </item>
-<item> skill </item>
-<item> skin </item>
-<item> skymip </item>
-<item> snaps </item>
-<item> snd_bits </item>
-<item> snd_device </item>
-<item> snd_interp </item>
-<item> snd_loadas8bit </item>
-<item> snd_mixahead </item>
-<item> snd_noextraupdate </item>
-<item> snd_oss_mmaped </item>
-<item> snd_output </item>
-<item> snd_phasesep </item>
-<item> snd_rate </item>
-<item> snd_render </item>
-<item> snd_show </item>
-<item> snd_stereo </item>
-<item> snd_volumesep </item>
-<item> sndbits </item>
-<item> sndchannels </item>
-<item> snddevice </item>
-<item> sndspeed </item>
-<item> software </item>
-<item> sounds </item>
-<item> spectator </item>
-<item> spectator_password </item>
-<item> speeds </item>
-<item> stats </item>
-<item> stereo </item>
-<item> stipplealpha </item>
-<item> surfcacheoverride </item>
-<item> sv </item>
-<item> sv_accelerate </item>
-<item> sv_aim </item>
-<item> sv_airaccelerate </item>
-<item> sv_allowAnonymous </item>
-<item> sv_allowDownload </item>
-<item> sv_cheats </item>
-<item> sv_enforcetime </item>
-<item> sv_floodProtect </item>
-<item> sv_fps </item>
-<item> sv_friction </item>
-<item> sv_gravity </item>
-<item> sv_hostname </item>
-<item> sv_idealpitchscale </item>
-<item> sv_keywords </item>
-<item> sv_killserver </item>
-<item> sv_mapChecksum </item>
-<item> sv_master1 </item>
-<item> sv_master2 </item>
-<item> sv_master3 </item>
-<item> sv_master4 </item>
-<item> sv_master5 </item>
-<item> sv_maxPing </item>
-<item> sv_maxRate </item>
-<item> sv_maxclients </item>
-<item> sv_maxrate </item>
-<item> sv_maxspeed </item>
-<item> sv_maxtic </item>
-<item> sv_maxvelocity </item>
-<item> sv_minPing </item>
-<item> sv_minqfversion </item>
-<item> sv_mintic </item>
-<item> sv_netdosprotect </item>
-<item> sv_noreload </item>
-<item> sv_nostep </item>
-<item> sv_onlyVisibleClients </item>
-<item> sv_padPackets </item>
-<item> sv_pakNames </item>
-<item> sv_paks </item>
-<item> sv_paused </item>
-<item> sv_phs </item>
-<item> sv_privateClients </item>
-<item> sv_privatePassword </item>
-<item> sv_progs </item>
-<item> sv_pure </item>
-<item> sv_reconnect_limit </item>
-<item> sv_reconnectlimit </item>
-<item> sv_referencedPakNames </item>
-<item> sv_referencedPaks </item>
-<item> sv_restartround </item>
-<item> sv_rollangle </item>
-<item> sv_rollspeed </item>
-<item> sv_running </item>
-<item> sv_serverid </item>
-<item> sv_showAverageBPS </item>
-<item> sv_showloss </item>
-<item> sv_spectalk </item>
-<item> sv_stopspeed </item>
-<item> sv_timefmt </item>
-<item> sv_timekick </item>
-<item> sv_timekick_fuzz </item>
-<item> sv_timekick_interval </item>
-<item> sv_timeout </item>
-<item> sv_timestamps </item>
-<item> sv_wateraccelerate </item>
-<item> sv_waterfriction </item>
-<item> sv_zombietime </item>
-<item> sw </item>
-<item> sw_allow_modex </item>
-<item> sw_clearcolor </item>
-<item> sw_drawflat </item>
-<item> sw_draworder </item>
-<item> sw_maxedges </item>
-<item> sw_maxsurfs </item>
-<item> sw_mipcap </item>
-<item> sw_mipscale </item>
-<item> sw_mode </item>
-<item> sw_polymodelstats </item>
-<item> sw_reportedgeout </item>
-<item> sw_reportsurfout </item>
-<item> sw_stipplealpha </item>
-<item> sw_surfcacheoverride </item>
-<item> sw_waterwarp </item>
-<item> swapinterval </item>
-<item> sys_cpustring </item>
-<item> sys_nostdout </item>
-<item> sys_sleep </item>
-<item> sys_ticrate </item>
-<item> team </item>
-<item> team_headmodel </item>
-<item> team_model </item>
-<item> teamplay </item>
-<item> teamtask </item>
-<item> temp1 </item>
-<item> testblend </item>
-<item> testentities </item>
-<item> testlights </item>
-<item> testparticles </item>
-<item> testsound </item>
-<item> texturealphamode </item>
-<item> texturemode </item>
-<item> texturesolidmode </item>
-<item> timedemo </item>
-<item> timegraph </item>
-<item> timelimit </item>
-<item> timeout </item>
-<item> timescale </item>
-<item> topcolor </item>
-<item> triplebuffer </item>
-<item> ttycon </item>
-<item> ui_Q3Model </item>
-<item> ui_actualNetGametype </item>
-<item> ui_bigFont </item>
-<item> ui_browserGameType </item>
-<item> ui_browserMaster </item>
-<item> ui_browserShowEmpty </item>
-<item> ui_browserShowFriendlyFire </item>
-<item> ui_browserShowFull </item>
-<item> ui_browserShowMaxlives </item>
-<item> ui_browserShowTourney </item>
-<item> ui_browserSortKey </item>
-<item> ui_cdkeychecked </item>
-<item> ui_class </item>
-<item> ui_cmd </item>
-<item> ui_ctf_capturelimit </item>
-<item> ui_ctf_friendly </item>
-<item> ui_ctf_timelimit </item>
-<item> ui_currentMap </item>
-<item> ui_currentNetMap </item>
-<item> ui_dedicated </item>
-<item> ui_ffa_fraglimit </item>
-<item> ui_ffa_timelimit </item>
-<item> ui_gametype </item>
-<item> ui_glCustom </item>
-<item> ui_isSpectator </item>
-<item> ui_joinGametype </item>
-<item> ui_limboMode </item>
-<item> ui_limboObjective </item>
-<item> ui_limboOptions </item>
-<item> ui_limboPrevOptions </item>
-<item> ui_mapIndex </item>
-<item> ui_master </item>
-<item> ui_menuFiles </item>
-<item> ui_mousePitch </item>
-<item> ui_netGametype </item>
-<item> ui_netSource </item>
-<item> ui_notebookCurrentPage </item>
-<item> ui_objective </item>
-<item> ui_prevClass </item>
-<item> ui_prevTeam </item>
-<item> ui_prevWeapon </item>
-<item> ui_serverStatusTimeOut </item>
-<item> ui_singlePlayerActive </item>
-<item> ui_smallFont </item>
-<item> ui_spSelection </item>
-<item> ui_team </item>
-<item> ui_teamArenaFirstRun </item>
-<item> ui_team_fraglimit </item>
-<item> ui_team_friendly </item>
-<item> ui_team_timelimit </item>
-<item> ui_tourney_fraglimit </item>
-<item> ui_tourney_timelimit </item>
-<item> ui_userAlliedRespawnTime </item>
-<item> ui_userAxisRespawnTime </item>
-<item> ui_userTimeLimit </item>
-<item> ui_weapon </item>
-<item> up </item>
-<item> upsensitivity </item>
-<item> upspeed </item>
-<item> upthreshold </item>
-<item> username </item>
-<item> v_centermove </item>
-<item> v_centerspeed </item>
-<item> v_idlescale </item>
-<item> v_ipitch_cycle </item>
-<item> v_ipitch_level </item>
-<item> v_iroll_cycle </item>
-<item> v_iroll_level </item>
-<item> v_iuaw_cycle </item>
-<item> v_iyaw_cycle </item>
-<item> v_iyaw_level </item>
-<item> v_kickpitch </item>
-<item> v_kickroll </item>
-<item> v_kicktime </item>
-<item> version </item>
-<item> vertex </item>
-<item> vid </item>
-<item> vid_config_x </item>
-<item> vid_config_y </item>
-<item> vid_fullscreen </item>
-<item> vid_fullscreen_mode </item>
-<item> vid_gamma </item>
-<item> vid_height </item>
-<item> vid_mode </item>
-<item> vid_nopageflip </item>
-<item> vid_ref </item>
-<item> vid_system_gamma </item>
-<item> vid_use8bit </item>
-<item> vid_wait </item>
-<item> vid_width </item>
-<item> vid_window_x </item>
-<item> vid_window_y </item>
-<item> vid_windowed_mode </item>
-<item> vid_xpos </item>
-<item> vid_ypos </item>
-<item> viewlog </item>
-<item> viewsize </item>
-<item> vm_cgame </item>
-<item> vm_game </item>
-<item> vm_ui </item>
-<item> volume </item>
-<item> vwep </item>
-<item> waitdelay </item>
-<item> waterwarp </item>
-<item> wavonly </item>
-<item> win </item>
-<item> win_noalttab </item>
-<item> win_hinstance </item>
-<item> win_wndproc </item>
-<item> xpos </item>
-<item> yaw </item>
-<item> yawsensitivity </item>
-<item> yawspeed </item>
-<item> yawthreshold </item>
-<item> ypos </item>
-<item> zombietime </item>
-<item> ztrick </item>
-</list>
-
-
-<list name="Actions">
-<item> +attack </item>
-<item> +ttack2 </item>
-<item> +alt1 </item>
-<item> +activate </item>
-<item> +back </item>
-<item> +break </item>
-<item> +button0 </item>
-<item> +button1 </item>
-<item> +button10 </item>
-<item> +button11 </item>
-<item> +button12 </item>
-<item> +button13 </item>
-<item> +button14 </item>
-<item> +button2 </item>
-<item> +button3 </item>
-<item> +button4 </item>
-<item> +button5 </item>
-<item> +button6 </item>
-<item> +button7 </item>
-<item> +button8 </item>
-<item> +button9 </item>
-<item> +camdistance </item>
-<item> +camin </item>
-<item> +cammousemove </item>
-<item> +camout </item>
-<item> +campitchdown </item>
-<item> +campitchup </item>
-<item> +camyawleft </item>
-<item> +camyawright </item>
-<item> +commandmenu </item>
-<item> +dropweapon </item>
-<item> +duck </item>
-<item> +forward </item>
-<item> +graph </item>
-<item> +jlook </item>
-<item> +jump </item>
-<item> +kick </item>
-<item> +klook </item>
-<item> +leanleft </item>
-<item> +leanright </item>
-<item> +left </item>
-<item> +lookdown </item>
-<item> +lookup </item>
-<item> +mlook </item>
-<item> +movedown </item>
-<item> +moveleft </item>
-<item> +moveright </item>
-<item> +moveup </item>
-<item> +nvgadjust </item>
-<item> +quickgren </item>
-<item> +reload </item>
-<item> +right </item>
-<item> +salute </item>
-<item> +score </item>
-<item> +showscores </item>
-<item> +speed </item>
-<item> +sprint </item>
-<item> +strafe </item>
-<item> +use </item>
-<item> +useitem </item>
-<item> +voicerecord </item>
-<item> +wbutton7 </item>
-<item> +zoom </item>
-<item> -activate </item>
-<item> -alt1 </item>
-<item> -attack </item>
-<item> -attack2 </item>
-<item> -back </item>
-<item> -break </item>
-<item> -button0 </item>
-<item> -button1 </item>
-<item> -button10 </item>
-<item> -button11 </item>
-<item> -button12 </item>
-<item> -button13 </item>
-<item> -button14 </item>
-<item> -button2 </item>
-<item> -button3 </item>
-<item> -button4 </item>
-<item> -button5 </item>
-<item> -button6 </item>
-<item> -button7 </item>
-<item> -button8 </item>
-<item> -button9 </item>
-<item> -camdistance </item>
-<item> -camin </item>
-<item> -cammousemove </item>
-<item> -camout </item>
-<item> -campitchdown </item>
-<item> -campitchup </item>
-<item> -camyawleft </item>
-<item> -camyawright </item>
-<item> -commandmenu </item>
-<item> -dropweapon </item>
-<item> -duck </item>
-<item> -forward </item>
-<item> -graph </item>
-<item> -jlook </item>
-<item> -jump </item>
-<item> -kick </item>
-<item> -klook </item>
-<item> -leanleft </item>
-<item> -leanright </item>
-<item> -left </item>
-<item> -lookdown </item>
-<item> -lookup </item>
-<item> -mlook </item>
-<item> -movedown </item>
-<item> -moveleft </item>
-<item> -moveright </item>
-<item> -moveup </item>
-<item> -nvgadjust </item>
-<item> -quickgren </item>
-<item> -reload </item>
-<item> -right </item>
-<item> -salute </item>
-<item> -score </item>
-<item> -showscores </item>
-<item> -speed </item>
-<item> -sprint </item>
-<item> -strafe </item>
-<item> -use </item>
-<item> -useitem </item>
-<item> -voicerecord </item>
-<item> -wbutton7 </item>
-<item> -zoom </item>
-</list>
-
-
-<list name="KeyTypes">
-<item> * </item>
-<item> [ </item>
-<item> ] </item>
-<item> \ </item>
-<item> / </item>
-<item> ' </item>
-<item> = </item>
-<item> - </item>
-<item> + </item>
-<item> , </item>
-<item> . </item>
-<item> ` </item>
-<item> ~ </item>
-<item> 1 </item>
-<item> 2 </item>
-<item> 3 </item>
-<item> 4 </item>
-<item> 5 </item>
-<item> 6 </item>
-<item> 7 </item>
-<item> 8 </item>
-<item> 9 </item>
-<item> 0 </item>
-<item> a </item>
-<item> b </item>
-<item> c </item>
-<item> d </item>
-<item> e </item>
-<item> f </item>
-<item> g </item>
-<item> h </item>
-<item> i </item>
-<item> j </item>
-<item> k </item>
-<item> l </item>
-<item> m </item>
-<item> n </item>
-<item> o </item>
-<item> p </item>
-<item> q </item>
-<item> r </item>
-<item> s </item>
-<item> t </item>
-<item> u </item>
-<item> v </item>
-<item> x </item>
-<item> w </item>
-<item> y </item>
-<item> z </item>
-<item> ALT </item>
-<item> AUX1 </item>
-<item> AUX10 </item>
-<item> AUX11 </item>
-<item> AUX12 </item>
-<item> AUX13 </item>
-<item> AUX14 </item>
-<item> AUX15 </item>
-<item> AUX16 </item>
-<item> AUX17 </item>
-<item> AUX18 </item>
-<item> AUX2 </item>
-<item> AUX20 </item>
-<item> AUX21 </item>
-<item> AUX22 </item>
-<item> AUX23 </item>
-<item> AUX24 </item>
-<item> AUX25 </item>
-<item> AUX26 </item>
-<item> AUX27 </item>
-<item> AUX28 </item>
-<item> AUX29 </item>
-<item> AUX3 </item>
-<item> AUX30 </item>
-<item> AUX31 </item>
-<item> AUX32 </item>
-<item> AUX4 </item>
-<item> AUX5 </item>
-<item> AUX6 </item>
-<item> AUX7 </item>
-<item> AUX8 </item>
-<item> AUX9 </item>
-<item> BACKSPACE </item>
-<item> CTRL </item>
-<item> DEL </item>
-<item> DOWNARROW </item>
-<item> END </item>
-<item> ENTER </item>
-<item> ESCAPE </item>
-<item> F1 </item>
-<item> F10 </item>
-<item> F11 </item>
-<item> F12 </item>
-<item> F2 </item>
-<item> F3 </item>
-<item> F4 </item>
-<item> F5 </item>
-<item> F6 </item>
-<item> F7 </item>
-<item> F8 </item>
-<item> F9 </item>
-<item> HOME </item>
-<item> INS </item>
-<item> JOY1 </item>
-<item> JOY2 </item>
-<item> JOY3 </item>
-<item> JOY4 </item>
-<item> KP_SLASH </item>
-<item> KP_5 </item>
-<item> KP_UPARROW </item>
-<item> KP_LEFTARROW </item>
-<item> KP_RIGHTARROW </item>
-<item> KP_DOWNARROW </item>
-<item> KP_HOME </item>
-<item> KP_END </item>
-<item> KP_PGUP </item>
-<item> KP_PGDN </item>
-<item> KP_INS </item>
-<item> KP_DEL </item>
-<item> LEFTARROW </item>
-<item> MOUSE1 </item>
-<item> MOUSE2 </item>
-<item> MOUSE3 </item>
-<item> MWHEELDOWN </item>
-<item> MWHEELUP </item>
-<item> PAUSE </item>
-<item> PGDN </item>
-<item> PGUP </item>
-<item> RIGHTARROW </item>
-<item> SEMICOLON </item>
-<item> CAPSLOCK </item>
-<item> SHIFT </item>
-<item> SPACE </item>
-<item> TAB </item>
-<item> UPARROW </item>
-</list>
-
- <list name="Symbols">
- <item> ; </item>
- <item> $ </item>
- </list>
- <list name="BindFamily">
- <item> bind </item>
- <item> unbind </item>
- </list>
- <list name="setFamily">
- <item> set </item>
- <item> seta </item>
- <item> setu </item>
- <item> sets </item>
- </list>
- <list name="PrintsString">
- <item> echo </item>
- <item> say_team </item>
- <item> say </item>
- </list>
-
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal Text">
- <keyword attribute="Command" context="Arg area" String="Commands"/>
- <keyword attribute="Variable" context="Arg area" String="Variables"/>
- <keyword attribute="Action" context="#stay" String="Actions"/>
- <keyword attribute="Symbol" context="#stay" String="Symbols"/>
- <keyword attribute="Command" context="Bind phrase" String="BindFamily"/>
- <keyword attribute="Command" context="Alias phrase" String="setFamily"/>
- <keyword attribute="Command" context="Echo" String="PrintsString"/>
- <StringDetect attribute="Command" context="Alias phrase" String="alias" insensitive="TRUE"/>
- <keyword attribute="Command" context="Echo" String="PrintsString"/>
- <DetectChar attribute="Symbol" context="#stay" char="$"/>
- <Detect2Chars attribute="Comment" context="Comment" char="/" char1="/"/>
- </context>
- <context attribute="Comment" lineEndContext="Normal Text" name="Comment"/>
- <context attribute="String" lineEndContext="Normal Text" name="String">
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Normal Text" lineEndContext="Normal Text" name="Arg area">
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Float attribute="Float" context="#stay"/>
- <Int attribute="Int" context="#stay"/>
- <DetectChar attribute="Symbol" context="#pop" char=";"/>
- <Detect2Chars attribute="Comment" context="Comment" char="/" char1="/"/>
- <DetectChar attribute="Symbol" context="Normal Text" char="$"/>
- </context>
- <context attribute="Normal Text" lineEndContext="Normal Text" name="Arg area in sub phrase">
- <Float attribute="Float" context="#stay"/>
- <Int attribute="Int" context="#stay"/>
- <Detect2Chars attribute="Comment" context="Comment" char="/" char1="/"/>
- <DetectChar attribute="Symbol" context="#pop" char=";"/>
- </context>
- <context attribute="Normal Text" lineEndContext="Normal Text" name="Sub phrase">
- <keyword attribute="Command" context="Arg area in sub phrase" String="Commands"/>
- <keyword attribute="Variable" context="Arg area in sub phrase" String="Variables"/>
- <keyword attribute="Action" context="#stay" String="Actions"/>
- <keyword attribute="Symbol" context="#stay" String="Symbols"/>
- <keyword attribute="Command" context="Bind phrase" String="BindFamily"/>
- <keyword attribute="Command" context="Normal Text" String="setFamily"/>
- <keyword attribute="Command" context="Echo" String="PrintsString"/>
- <StringDetect attribute="Command" context="Alias phrase" String="alias"/>
- <Detect2Chars attribute="Comment" context="Comment" char="/" char1="/"/>
- <DetectChar attribute="Symbol" context="#stay" char=";"/>
- <Int attribute="Int" context="#stay"/>
- <DetectChar attribute="Symbol" context="#pop" char=";"/>
- </context>
- <context attribute="Normal Text" lineEndContext="Normal Text" name="Bind phrase">
- <keyword attribute="Hex" context="Sub phrase" String="KeyTypes"/>
- </context>
- <context attribute="Identifier" lineEndContext="Normal Text" name="Alias phrase">
- <DetectChar attribute="Identifier" context="Sub phrase" char=" "/>
- </context>
- <context attribute="String" lineEndContext="Normal Text" name="Echo">
- <DetectChar attribute="Symbol" context="#pop" char=";"/>
- <Detect2Chars attribute="Comment" context="Comment" char="/" char1="/"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Command" defStyleNum="dsKeyword" />
- <itemData name="Action" defStyleNum="dsNormal" color="#ffcc00" italic="1" selColor="#00ff00" bold="1" />
- <itemData name="Variable" defStyleNum="dsNormal" color="#0000ff" italic="1" selColor="#00ff00" bold="1" />
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Comment" defStyleNum="dsComment" />
- <itemData name="Float" defStyleNum="dsFloat" />
- <itemData name="Int" defStyleNum="dsFloat" />
- <itemData name="String" defStyleNum="dsNormal" color="#ff0000" italic="1" selColor="#00ff00" bold="0" />
- <itemData name="String Char" defStyleNum="dsChar" />
- <itemData name="Hex" defStyleNum="dsBaseN" />
- <itemData name="Symbol" defStyleNum="dsOthers" />
- <itemData name="Identifier" defStyleNum="dsDataType" />
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//"/>
- </comments>
- <keywords weakDeliminator=",+~-=/\.[]$" additionalDeliminator="&quot;;$" casesensitive="0"/>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="IDL" version="1.03" kateversion="2.1" section="Sources" extensions="*.idl" mimetype="text/x-idl-src">
- <highlighting>
- <list name="keywords">
- <item> any </item>
- <item> attribute </item>
- <item> case </item>
- <item> const </item>
- <item> context </item>
- <item> default </item>
- <item> enum </item>
- <item> exception </item>
- <item> FALSE </item>
- <item> fixed </item>
- <item> public </item>
- <item> in </item>
- <item> inout </item>
- <item> interface </item>
- <item> module </item>
- <item> Object </item>
- <item> oneway </item>
- <item> out </item>
- <item> raises </item>
- <item> readonly </item>
- <item> sequence </item>
- <item> struct </item>
- <item> switch </item>
- <item> TRUE </item>
- <item> typedef </item>
- <item> unsigned </item>
- <item> union </item>
- </list>
- <list name="types">
- <item> boolean </item>
- <item> char </item>
- <item> double </item>
- <item> float </item>
- <item> long </item>
- <item> octet </item>
- <item> short </item>
- <item> string </item>
- <item> void </item>
- <item> wchar </item>
- <item> wstring </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Data Type" context="#stay" String="types" />
- <HlCOct attribute="Octal" context="#stay"/>
- <HlCHex attribute="Hex" context="#stay"/>
- <HlCChar attribute="Char" context="#stay"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*"/>
- <AnyChar attribute="Symbol" context="#stay" String="!%&amp;()+,-&lt;=&gt;?[]^{|}~"/>
- <StringDetect attribute="Comment" context="Some Context3" String="#if 0" insensitive="FALSE"/>
- <RegExpr attribute="Preprocessor" context="Preprocessor" String="^#"/>
- </context>
- <context attribute="String" lineEndContext="#stay" name="String">
- <LineContinue attribute="String" context="Some Context"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Commentar 1">
- <RegExpr attribute="Decimal" context="#stay" String="(FIXME|TODO)" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar 2">
- <RegExpr attribute="Decimal" context="#stay" String="(FIXME|TODO)" />
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/"/>
- </context>
- <context attribute="Preprocessor" lineEndContext="#pop" name="Preprocessor">
- <LineContinue attribute="Preprocessor" context="Some Context2"/>
- <RangeDetect attribute="Prep. Lib" context="#stay" char="&quot;" char1="&quot;"/>
- <RangeDetect attribute="Prep. Lib" context="#stay" char="&lt;" char1="&gt;"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar/Preprocessor" char="/" char1="*"/>
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar/Preprocessor">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" />
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Some Context"/>
- <context attribute="Normal Text" lineEndContext="#pop" name="Some Context2"/>
- <context attribute="Normal Text" lineEndContext="#stay" name="Some Context3">
- <RegExpr attribute="Decimal" context="#stay" String="(FIXME|TODO)" />
- <RegExpr attribute="Comment" context="#pop" String="^#endif" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- <itemData name="Prep. Lib" defStyleNum="dsOthers"/> <!--,Qt::darkYellow,Qt::yellow,false,false)); -->
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="ILERPG" version="1.02" kateversion="2.1" section="Sources" extensions="QRPGLESRC.*" mimetype="text/x-ilerpg-src" casesensitive="0">
- <highlighting>
- <list name="biffs">
- <item> ABS </item>
- <item> ADDR </item>
- <item> CHAR </item>
- <item> DECH </item>
- <item> DECPOS </item>
- <item> DEC </item>
- <item> EDITC </item>
- <item> EDITFLT </item>
- <item> EDITW </item>
- <item> ELEM </item>
- <item> EOF </item>
- <item> EQUAL </item>
- <item> ERROR </item>
- <item> FLOAT </item>
- <item> FOUND </item>
- <item> INTH </item>
- <item> INT </item>
- <item> LEN </item>
- <item> NULLIND </item>
- <item> OPEN </item>
- <item> PADDR </item>
- <item> PARMS </item>
- <item> REPLACE </item>
- <item> SCAN </item>
- <item> SIZE </item>
- <item> STATUS </item>
- <item> STR </item>
- <item> SUBST </item>
- <item> TRIMR </item>
- <item> TRIML </item>
- <item> TRIM </item>
- <item> UNSH </item>
- <item> UNS </item>
- </list>
- <list name="opcodes">
- <item> Z-ADD </item>
- <item> Z-SUB </item>
- <item> ACQ </item>
- <item> ADDDUR </item>
- <item> ADD </item>
- <item> ALLOC </item>
- <item> ANDGT </item>
- <item> ANDLT </item>
- <item> ANDEQ </item>
- <item> ANDNE </item>
- <item> ANDGE </item>
- <item> ANDLE </item>
- <item> AND </item>
- <item> BEGSR </item>
- <item> BITOFF </item>
- <item> BITON </item>
- <item> CABGT </item>
- <item> CABLT </item>
- <item> CABEQ </item>
- <item> CABNE </item>
- <item> CABGE </item>
- <item> CABLE </item>
- <item> CAB </item>
- <item> CALLB </item>
- <item> CALLP </item>
- <item> CALL </item>
- <item> CASGT </item>
- <item> CASLT </item>
- <item> CASEQ </item>
- <item> CASNE </item>
- <item> CASGE </item>
- <item> CASLE </item>
- <item> CAS </item>
- <item> CAT </item>
- <item> CHAIN </item>
- <item> CHECKR </item>
- <item> CHECK </item>
- <item> CLEAR </item>
- <item> CLOSE </item>
- <item> COMMIT </item>
- <item> COMP </item>
- <item> DEALLOC </item>
- <item> DEFINE </item>
- <item> DELETE </item>
- <item> DIV </item>
- <item> DOWGT </item>
- <item> DOWLT </item>
- <item> DOWEQ </item>
- <item> DOWNE </item>
- <item> DOWGE </item>
- <item> DOWLE </item>
- <item> DOUGT </item>
- <item> DOULT </item>
- <item> DOUEQ </item>
- <item> DOUNE </item>
- <item> DOUGE </item>
- <item> DOULE </item>
- <item> DOU </item>
- <item> DOW </item>
- <item> DO </item>
- <item> DSPLY </item>
- <item> DUMP </item>
- <item> ELSE </item>
- <item> ENDCS </item>
- <item> ENDDO </item>
- <item> ENDIF </item>
- <item> ENDSL </item>
- <item> ENDSR </item>
- <item> END </item>
- <item> EVAL </item>
- <item> EXCEPT </item>
- <item> EXFMT </item>
- <item> EXSR </item>
- <item> EXTRCT </item>
- <item> FEOD </item>
- <item> FORCE </item>
- <item> GOTO </item>
- <item> IFGT </item>
- <item> IFLT </item>
- <item> IFEQ </item>
- <item> IFNE </item>
- <item> IFGE </item>
- <item> IFLE </item>
- <item> IF </item>
- <item> IN </item>
- <item> ITER </item>
- <item> KFLD </item>
- <item> KLIST </item>
- <item> LEAVE </item>
- <item> LOOKUP </item>
- <item> MHHZO </item>
- <item> MHLZO </item>
- <item> MLHZO </item>
- <item> MLLZO </item>
- <item> MOVE </item>
- <item> MOVEA </item>
- <item> MOVEL </item>
- <item> MULT </item>
- <item> MVR </item>
- <item> NEXT </item>
- <item> OCCUR </item>
- <item> OPEN </item>
- <item> ORGT </item>
- <item> ORLT </item>
- <item> OREQ </item>
- <item> ORNE </item>
- <item> ORGE </item>
- <item> ORLE </item>
- <item> OR </item>
- <item> OTHER </item>
- <item> OUT </item>
- <item> PARM </item>
- <item> PLIST </item>
- <item> POST </item>
- <item> READC </item>
- <item> READE </item>
- <item> READPE </item>
- <item> READP </item>
- <item> READ </item>
- <item> REALLOC </item>
- <item> REL </item>
- <item> RESET </item>
- <item> RETURN </item>
- <item> ROLBK </item>
- <item> SCAN </item>
- <item> SELECT </item>
- <item> SETGT </item>
- <item> SETLL </item>
- <item> SETOFF </item>
- <item> SETON </item>
- <item> SHTDN </item>
- <item> SORTA </item>
- <item> SQRT </item>
- <item> SUBDUR </item>
- <item> SUBST </item>
- <item> SUB </item>
- <item> TAG </item>
- <item> TESTB </item>
- <item> TESTN </item>
- <item> TESTZ </item>
- <item> TEST </item>
- <item> TIME </item>
- <item> UNLOCK </item>
- <item> UPDATE </item>
- <item> WHENGT </item>
- <item> WHENLT </item>
- <item> WHENEQ </item>
- <item> WHENNR </item>
- <item> WHENGE </item>
- <item> WHENLE </item>
- <item> WHEN </item>
- <item> WRITE </item>
- <item> XFOOT </item>
- <item> XLATE </item>
- <item> *BLANKS </item>
- </list>
-
- <contexts>
-
- <context attribute="Normal Text" lineEndContext="#stay" name="Default">
- <RegExpr attribute="Comment" context="context3" String="[POIHFDC ]?\*"/>
- <RegExpr attribute="Keyword" context="context1" String="[POIHFDC]"/>
- </context>
-
- <context attribute="Normal Text" lineEndContext="#pop" name="context1">
- <keyword attribute="Keyword" context="#stay" String="opcodes"/>
- <DetectChar attribute="Biff" context="context7" char="%"/>
- <DetectChar attribute="Constant" context="context3" char="'"/>
- <Float attribute="Float" context="#stay"/>
- <RegExpr attribute="Hex" context="#stay" String="[Xx]'[0-9|a-f|A-f]{2,}'"/>
-
- <Int attribute="Decimal" context="#stay">
- <StringDetect attribute="Decimal" context="#stay" String="ULL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LUL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LLU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="UL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="U" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="L" insensitive="TRUE"/>
- </Int>
- </context>
-
- <context attribute="Comment" lineEndContext="#pop" name="context3">
- <RegExpr attribute="BoldComment" context="#stay" String="\(*(FIXME|TODO)\)*" />
- <RegExpr attribute="BoldComment" context="#stay" String="\(*(NOTE:)\)*" />
- <DetectChar attribute="BoldComment" context="context6" char="!"/>
- <RegExpr attribute="DivideComment" context="#stay" String="-|="/>
- </context>
-
- <context attribute="Constant" lineEndContext="#stay" name="context4">
- <DetectChar attribute="Constant" context="#pop" char="'"/>
- </context>
-
- <context attribute="Constant" lineEndContext="#stay" name="context5">
- <RegExpr attribute="Normal Text" context="#stay" String="[FHDICO]"/>
- <DetectChar attribute="Constant" context="#pop" char=" "/>
- </context>
- <context attribute="Keyword" lineEndContext="#pop#pop" name="context6">
- </context>
- <context attribute="BoldComment" lineEndContext="Default" name="context7">
- <DetectChar attribute="BoldComment" context="context3" char="!"/>
- </context>
- <context attribute="Biff" lineEndContext="#pop#pop#pop" name="context8">
- <keyword attribute="Biff" context="#pop#pop" String="biffs"/>
- <DetectChar attribute="Biff" context="#pop#pop" char=" "/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="Biff" defStyleNum="dsKeyword" />
- <itemData name="RegExpr" defStyleNum="dsBaseN" />
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Decimal" defStyleNum="dsDecVal" />
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Base-N" defStyleNum="dsBaseN" />
- <itemData name="Float" defStyleNum="dsFloat" />
- <itemData name="Char" defStyleNum="dsChar" />
- <itemData name="Constant" defStyleNum="dsNormal" color="#FF0000" selColor="#000000" bold="0" italic="0"/>
- <itemData name="Fill" defStyleNum="dsNormal" color="#FF6347" selColor="#000000" bold="0" italic="0"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="BoldComment" defStyleNum="dsNormal" color="#CD853F" selColor="#808080" bold="1" italic="1"/>
- <itemData name="DivideComment" defStyleNum="dsComment" bold="1"/>
- <itemData name="Directive" defStyleNum="dsOthers"/>
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="0" />
- </general>
-</language>
-
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!-- author: Giancarlo Niccolai (giancarlo@niccolai.ws) -->
-<!-- This file is released under GPL license 2.0 or any later version at your choice. -->
-<!-- $Id: inform.xml,v 1.4 2004/02/03 20:26:06 cullmann Exp $ -->
-<language name="Inform" version="1.21" kateversion="2.1" section="Sources"
- extensions="*.inf;*.h" mimetype="text/x-inform-src"
- author="Giancarlo Niccolai (giancarlo@niccolai.ws)" license="GPL">
-<highlighting>
- <list name="keywords">
- <item> if </item>
- <item> for </item>
- <item> else </item>
- <item> box </item>
- <item> break </item>
- <item> continue </item>
- <item> do </item>
- <item> until </item>
- <item> font </item>
- <item> give </item>
- <item> inversion </item>
- <item> jump </item>
- <item> on </item>
- <item> to </item>
- <item> move </item>
- <item> new_line </item>
- <item> objectloop </item>
- <item> print </item>
- <item> print_ret </item>
- <item> quit </item>
- <item> read </item>
- <item> remove </item>
- <item> restore </item>
- <item> return </item>
- <item> rtrue </item>
- <item> rfalse </item>
- <item> save </item>
- <item> spaces </item>
- <item> spring </item>
- <item> style </item>
- <item> switch </item>
- </list>
-
- <list name="functions">
- <item> metaclass </item>
- <item> parent </item>
- <item> child </item>
- <item> children </item>
- <item> Achieved </item>
- <item> AddToScope </item>
- <item> allowpushdir </item>
- <item> CDefArt </item>
- <item> ChangeDefault </item>
- <item> DefArt </item>
- <item> DoMenu </item>
- <item> EnglishNumber </item>
- <item> HasLightSource </item>
- <item> InDefArt </item>
- <item> Locale </item>
- <item> LoopOverScope </item>
- <item> NextWord </item>
- <item> NextWordStopped </item>
- <item> NounDomain </item>
- <item> ObjectIsUntouchable </item>
- <item> OffersLight </item>
- <item> PlaceInScope </item>
- <item> PlayerTo </item>
- <item> PrintShortName </item>
- <item> ScopeWithin </item>
- <item> SetTime </item>
- <item> StartDaemon </item>
- <item> StartTimer </item>
- <item> StopDaemon </item>
- <item> StopTimer </item>
- <item> TestScope </item>
- <item> TryNumber </item>
- <item> UnsignedCompare </item>
- <item> WordAddress </item>
- <item> WordLenght </item>
- <item> WriteListFrom </item>
- <item> YesOrNo </item>
- <item> ZRegion </item>
- </list>
- <list name="actions">
- <item> Pronouns </item>
- <item> Quit </item>
- <item> Restore </item>
- <item> Save </item>
- <item> Verify </item>
- <item> Restart </item>
- <item> ScriptOn </item>
- <item> ScriptOff </item>
- <item> NotifyOn </item>
- <item> NotifyOff </item>
- <item> Places </item>
- <item> Objects </item>
- <item> Score </item>
- <item> FullScore </item>
- <item> Version </item>
- <item> LMode1 </item>
- <item> LMode2 </item>
- <item> LMode3 </item>
- <item> Inv </item>
-
-
- <item> Inv </item>
- <item> InvTall </item>
- <item> InvWide </item>
- <item> Take </item>
- <item> Drop </item>
- <item> Empty </item>
- <item> Enter </item>
- <item> Exit </item>
- <item> GetOff </item>
- <item> Go </item>
- <item> GoIn </item>
- <item> Look </item>
- <item> Examine </item>
- <item> Search </item>
- <item> Give </item>
- <item> Show </item>
- <item> Unlock </item>
- <item> Lock </item>
- <item> SwitchOn </item>
- <item> SwitchOff </item>
- <item> Open </item>
- <item> Close </item>
- <item> Disrobe </item>
- <item> Wear </item>
- <item> Eat </item>
-
- <item> LetGo </item>
- <item> Receive </item>
- <item> Insert </item>
- <item> PutOn </item>
- <item> Transfer </item>
- <item> Empty </item>
- <item> EmptyT </item>
- <item> GetOff </item>
- <item> GoIn </item>
- <item> Listen </item>
- <item> Taste </item>
- <item> Touch </item>
-
- <item> Pull </item>
- <item> Push </item>
- <item> Wave </item>
- <item> Turn </item>
- <item> PushDir </item>
- <item> ThrowAt </item>
- <item> ThrownAt </item>
- <item> JumpOn </item>
- <item> Drink </item>
- <item> Attack </item>
- <item> Tie </item>
- <item> Fill </item>
- <item> Swing </item>
- <item> Blow </item>
- <item> Rub </item>
- <item> Set </item>
- <item> SetTo </item>
- <item> Buy </item>
- <item> Climb </item>
- <item> Squeeze </item>
- <item> Climb </item>
- <item> Burn </item>
- <item> Cut </item>
- <item> Dig </item>
-
- <item> Consult </item>
- <item> Tell </item>
- <item> Answer </item>
- <item> Ask </item>
- <item> AskFor </item>
- <item> Kiss </item>
-
- <item> Sleep </item>
- <item> Sing </item>
- <item> WaveHands </item>
- <item> Swim </item>
- <item> Sorry </item>
- <item> Sing </item>
- <item> Strong </item>
- <item> Mild </item>
- <item> Smell </item>
- <item> Pray </item>
- <item> Jump </item>
- <item> Think </item>
- <item> VagueGo </item>
- <item> Yes </item>
- <item> No </item>
- <item> Sing </item>
- </list>
-
- <list name="special_vals" >
- <item> String </item>
- <item> Routine </item>
- <item> bold </item>
- <item> roman </item>
- <item> underline </item>
- <item> fixed </item>
- <item> nothing </item>
- <item> true </item>
- <item> false </item>
- <item> on </item>
- <item> off </item>
- <item> sender </item>
- <item> self </item>
- <item> location </item>
- <item> score </item>
- <item> action </item>
- <item> actor </item>
- <item> noun </item>
- <item> second </item>
- <item> the_time </item>
- <item> consult_from </item>
- <item> consult_words </item>
- <item> wn </item>
- <item> actors_location </item>
- <item> buffer </item>
- <item> player </item>
- </list>
-
- <list name="pragmas" >
- <item> Ifdef </item>
- <item> Ifndef </item>
- <item> Iftrue </item>
- <item> Iffalse </item>
- <item> Ifnot </item>
- <item> Endif </item>
- <item> End </item>
- <item> Abbreviate </item>
- <item> Array </item>
- <item> Attribute </item>
- <item> Constant </item>
- <item> Default </item>
- <item> Extend </item>
- <item> Global </item>
- <item> Ifnot </item>
- <item> Iftrue </item>
- <item> Iffalse </item>
- <item> Import </item>
- <item> Include </item>
- <item> Link </item>
- <item> Lowstring </item>
- <item> Message </item>
- <item> Property </item>
- <item> Release </item>
- <item> Replace </item>
- <item> Serial </item>
- <item> Switches </item>
- <item> Statusline </item>
- <item> score </item>
- <item> System_file </item>
- <item> Verb </item>
- </list>
-
- <list name="inline_pragmas" >
- <item> #ifdef </item>
- <item> #else </item>
- <item> #ifndef </item>
- <item> #endif </item>
- </list>
-
- <list name="operators">
- <item> has </item>
- <item> hasn't </item>
- <item> in </item>
- <item> notin </item>
- <item> provides </item>
- <item> ofclass </item>
- <item> or </item>
- </list>
-
- <list name="ClassDeclOps">
- <item> with </item>
- <item> private </item>
- <item> has </item>
- </list>
-
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="TopLevel">
- <DetectChar attribute="Comment" context="comment" char="!" />
- <DetectChar attribute="String" context="string" char="&quot;" />
- <RegExpr attribute="Function" context="funcdef" beginRegion="reg_function"
- String="[[]\s*[a-zA-Z_]+[a-zA-Z_0-9]*" />
-
- <RegExpr String="^ *object |^ *class " attribute="Pragma"
- context="ClassDecl"
- insensitive="TRUE" beginRegion="reg_class" />
-
- <keyword attribute="Pragma" context="#stay" String="pragmas" />
- <keyword attribute="Pragma" context="#stay" String="inline_pragmas" />
-
- <RegExpr attribute="Operator" context="#stay" String="--?>" />
- <RegExpr attribute="Normal Text" context="#stay" String="[a-zA-Z_]+[0-9]*" />
- <RegExpr attribute="Number" context="#stay" String="\$[0-9a-fA-F]{1,4}" />
- <RegExpr attribute="Number" context="#stay" String="[0-9]+" />
- </context>
-
- <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
- <DetectChar attribute="Comment" context="comment" char="!" />
- <DetectChar attribute="String" context="string" char="&quot;" />
- <DetectChar attribute="Word" context="word" char="'" />
- <keyword attribute="Pragma" context="#stay" String="inline_pragmas" />
- <RegExpr attribute="Operator" context="#stay" String="--?>" />
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Actions" context="#stay" String="actions" />
- <keyword attribute="PredefFunction" context="#stay" String="functions" />
- <keyword attribute="Values" context="#stay" String="special_vals" />
- <keyword attribute="Operator" context="#stay" String="operators" />
- <RegExpr attribute="Actions" context="#stay" String="##[a-zA-Z_]+[a-zA-Z_0-9]*" />
- <RegExpr attribute="OpCode" context="#stay" String="@[a-zA-Z_]+[a-zA-Z_0-9]*" />
- <RegExpr attribute="Number" context="#stay" String="\$[0-9a-fA-F]{1,4}" />
- <RegExpr String="[a-zA-Z_]+[a-zA-Z_0-9]*" attribute="Normal Text" context="#stay" />
- <RegExpr attribute="Number" context="#stay" String="[0-9]+" />
- <DetectChar char="{" attribute="Keyword" context="#stay"
- beginRegion="reg_compound" />
- <DetectChar char="}" attribute="Keyword" context="#stay"
- endRegion="reg_compound" />
- <RegExpr attribute="Operator" context="#stay" String="[%&amp;()+-&lt;=&gt;{|}~]"/>
- </context>
-
- <context attribute="Normal Text" lineEndContext="#stay" name="PropDefVal rules">
- <DetectChar attribute="Comment" context="comment" char="!" />
- <DetectChar attribute="String" context="string" char="&quot;" />
- <DetectChar attribute="Word" context="word" char="'" />
- <DetectChar attribute="Function" context="prop_func_def" char="[" beginRegion="reg_prop_def_func" />
- <DetectChar attribute="Operator" context="#pop" char="," />
- <RegExpr attribute="Number" context="#stay" String="\$[0-9a-fA-F]{1,4}" />
- <RegExpr attribute="Number" context="#stay" String="[0-9]+" />
- </context>
-
-
- <context name="funcdef" attribute="Normal Text" lineEndContext="#stay" >
- <IncludeRules context="Normal" />
- <Detect2Chars attribute="Function" context="#pop" char="]" char1=";"
- endRegion="reg_function"/>
- </context>
-
- <context name="ClassDecl" attribute="Normal Text" lineEndContext="ClassDecl_1">
- <IncludeRules context="PropDefVal rules" />
- </context>
-
- <context name="ClassDecl_1" attribute="Normal Text" lineEndContext="#stay">
- <RegExpr String="^[\t ]*has " attribute="Keyword" context="has_decl" insensitive="TRUE"/>
- <keyword String="ClassDeclOps" attribute="Keyword" context="#stay" />
- <RegExpr String="[a-zA-Z_]+[a-zA-Z_0-9]*" context = "prop_def"
- attribute="Function"/>
- <DetectChar char=";" context="#pop" attribute="Pragma" endRegion="reg_class"/>
- </context>
-
-
- <context attribute="Word" lineEndContext="#pop" name="word">
- <DetectChar attribute="Word" context="#pop" char="'" />
- </context>
-
- <context attribute="String" lineEndContext="#stay" name="string">
- <DetectChar attribute="String" context="#pop" char="&quot;" />
- </context>
-
- <context name="prop_func_def" attribute="Normal Text" lineEndContext="#stay">
- <DetectChar context="#pop" char="]" attribute="Function"
- endRegion="reg_prop_func"/>
- <IncludeRules context="Normal" />
- </context>
-
- <context name="prop_def" attribute="Normal Text" lineEndContext="#stay" >
- <DetectChar char="," context="#pop" attribute="Function"
- endRegion="reg_prop"/>
- <DetectChar char=";" context="#pop#pop#pop" attribute="Pragma" endRegion="reg_class"/>
- <DetectChar char="[" context="prop_func_def" attribute="Function"
- beginRegion="reg_prop_func"/>
- <IncludeRules context="PropDefVal rules" />
- </context>
-
- <context name="has_decl" attribute="Normal Text" lineEndContext="#stay" >
- <DetectChar char=";" context="#pop#pop#pop" attribute="Pragma" endRegion="reg_class"/>
- <IncludeRules context="PropDefVal rules" />
- </context>
-
- <context attribute="Comment" lineEndContext="#pop" name="comment"/>
-
- </contexts>
-
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Actions" defStyleNum="dsDataType" color="#E06060" selColor="#400000" bold="0" italic="0"/>
- <itemData name="Operator" defStyleNum="dsBaseN" color="#A01060" selColor="#400040" bold="0" italic="0"/>
- <itemData name="Number" defStyleNum="dsDecVal" color="#5050C0" selColor="#000000" bold="0" italic="0"/>
- <itemData name="OpCode" defStyleNum="dsDecVal" color="#3015F0" selColor="#000000" bold="1" italic="0"/>
- <itemData name="Values" defStyleNum="dsBaseN" color="#7020F0" selColor="#400000" bold="1" italic="0" />
- <itemData name="Pragma" defStyleNum="dsOthers" color="#109010" selColor="#400000" bold="1" italic="0" />
- <itemData name="PredefFunction" defStyleNum="dsNormal" color="#000090" selColor="#ffffff" bold="1" italic="0"/>
- <itemData name="Function" defStyleNum="dsNormal" color="#000090" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Comment" defStyleNum="dsComment" color="#707070" selColor="#ffffff" bold="0" italic="1"/>
- <itemData name="String" defStyleNum="dsString" color="#007000" selColor="#007000" bold="0" italic="0"/>
- <itemData name="Word" defStyleNum="dsString" color="#007000" selColor="#007000" bold="0" italic="1"/>
- </itemDatas>
-</highlighting>
-<general>
- <comments>
- <comment name="singleLine" start="!" />
- </comments>
- <keywords casesensitive="1" />
-</general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Java" version="1.08" kateversion="2.1" section="Sources" extensions="*.java" mimetype="text/x-java">
- <highlighting>
- <list name="java14">
- <item> AbstractAction </item>
- <item> AbstractBorder </item>
- <item> AbstractButton </item>
- <item> AbstractCellEditor </item>
- <item> AbstractCollection </item>
- <item> AbstractColorChooserPanel </item>
- <item> AbstractDocument </item>
- <item> AbstractDocument.AttributeContext </item>
- <item> AbstractDocument.Content </item>
- <item> AbstractDocument.ElementEdit </item>
- <item> AbstractInterruptibleChannel </item>
- <item> AbstractLayoutCache </item>
- <item> AbstractLayoutCache.NodeDimensions </item>
- <item> AbstractList </item>
- <item> AbstractListModel </item>
- <item> AbstractMap </item>
- <item> AbstractMethodError </item>
- <item> AbstractPreferences </item>
- <item> AbstractSelectableChannel </item>
- <item> AbstractSelectionKey </item>
- <item> AbstractSelector </item>
- <item> AbstractSequentialList </item>
- <item> AbstractSet </item>
- <item> AbstractSpinnerModel </item>
- <item> AbstractTableModel </item>
- <item> AbstractUndoableEdit </item>
- <item> AbstractWriter </item>
- <item> AccessControlContext </item>
- <item> AccessControlException </item>
- <item> AccessController </item>
- <item> AccessException </item>
- <item> Accessible </item>
- <item> AccessibleAction </item>
- <item> AccessibleBundle </item>
- <item> AccessibleComponent </item>
- <item> AccessibleContext </item>
- <item> AccessibleEditableText </item>
- <item> AccessibleExtendedComponent </item>
- <item> AccessibleExtendedTable </item>
- <item> AccessibleHyperlink </item>
- <item> AccessibleHypertext </item>
- <item> AccessibleIcon </item>
- <item> AccessibleKeyBinding </item>
- <item> AccessibleObject </item>
- <item> AccessibleRelation </item>
- <item> AccessibleRelationSet </item>
- <item> AccessibleResourceBundle </item>
- <item> AccessibleRole </item>
- <item> AccessibleSelection </item>
- <item> AccessibleState </item>
- <item> AccessibleStateSet </item>
- <item> AccessibleTable </item>
- <item> AccessibleTableModelChange </item>
- <item> AccessibleText </item>
- <item> AccessibleValue </item>
- <item> AccountExpiredException </item>
- <item> Acl </item>
- <item> AclEntry </item>
- <item> AclNotFoundException </item>
- <item> Action </item>
- <item> ActionEvent </item>
- <item> ActionListener </item>
- <item> ActionMap </item>
- <item> ActionMapUIResource </item>
- <item> Activatable </item>
- <item> ActivateFailedException </item>
- <item> ActivationDesc </item>
- <item> ActivationException </item>
- <item> ActivationGroup </item>
- <item> ActivationGroup_Stub </item>
- <item> ActivationGroupDesc </item>
- <item> ActivationGroupDesc.CommandEnvironment </item>
- <item> ActivationGroupID </item>
- <item> ActivationID </item>
- <item> ActivationInstantiator </item>
- <item> ActivationMonitor </item>
- <item> ActivationSystem </item>
- <item> Activator </item>
- <item> ActiveEvent </item>
- <item> AdapterActivator </item>
- <item> AdapterActivatorOperations </item>
- <item> AdapterAlreadyExists </item>
- <item> AdapterAlreadyExistsHelper </item>
- <item> AdapterInactive </item>
- <item> AdapterInactiveHelper </item>
- <item> AdapterNonExistent </item>
- <item> AdapterNonExistentHelper </item>
- <item> AddressHelper </item>
- <item> Adjustable </item>
- <item> AdjustmentEvent </item>
- <item> AdjustmentListener </item>
- <item> Adler32 </item>
- <item> AffineTransform </item>
- <item> AffineTransformOp </item>
- <item> AlgorithmParameterGenerator </item>
- <item> AlgorithmParameterGeneratorSpi </item>
- <item> AlgorithmParameters </item>
- <item> AlgorithmParameterSpec </item>
- <item> AlgorithmParametersSpi </item>
- <item> AllPermission </item>
- <item> AlphaComposite </item>
- <item> AlreadyBound </item>
- <item> AlreadyBoundException </item>
- <item> AlreadyBoundHelper </item>
- <item> AlreadyBoundHolder </item>
- <item> AlreadyConnectedException </item>
- <item> AncestorEvent </item>
- <item> AncestorListener </item>
- <item> Annotation </item>
- <item> Any </item>
- <item> AnyHolder </item>
- <item> AnySeqHelper </item>
- <item> AnySeqHelper </item>
- <item> AnySeqHolder </item>
- <item> AppConfigurationEntry </item>
- <item> AppConfigurationEntry.LoginModuleControlFlag </item>
- <item> Applet </item>
- <item> AppletContext </item>
- <item> AppletInitializer </item>
- <item> AppletStub </item>
- <item> ApplicationException </item>
- <item> Arc2D </item>
- <item> Arc2D.Double </item>
- <item> Arc2D.Float </item>
- <item> Area </item>
- <item> AreaAveragingScaleFilter </item>
- <item> ARG_IN </item>
- <item> ARG_INOUT </item>
- <item> ARG_OUT </item>
- <item> ArithmeticException </item>
- <item> Array </item>
- <item> Array </item>
- <item> ArrayIndexOutOfBoundsException </item>
- <item> ArrayList </item>
- <item> Arrays </item>
- <item> ArrayStoreException </item>
- <item> AssertionError </item>
- <item> AsyncBoxView </item>
- <item> AsynchronousCloseException </item>
- <item> Attr </item>
- <item> Attribute </item>
- <item> Attribute </item>
- <item> AttributedCharacterIterator </item>
- <item> AttributedCharacterIterator.Attribute </item>
- <item> AttributedString </item>
- <item> AttributeException </item>
- <item> AttributeInUseException </item>
- <item> AttributeList </item>
- <item> AttributeList </item>
- <item> AttributeListImpl </item>
- <item> AttributeModificationException </item>
- <item> Attributes </item>
- <item> Attributes </item>
- <item> Attributes </item>
- <item> Attributes.Name </item>
- <item> AttributeSet </item>
- <item> AttributeSet </item>
- <item> AttributeSet.CharacterAttribute </item>
- <item> AttributeSet.ColorAttribute </item>
- <item> AttributeSet.FontAttribute </item>
- <item> AttributeSet.ParagraphAttribute </item>
- <item> AttributeSetUtilities </item>
- <item> AttributesImpl </item>
- <item> AudioClip </item>
- <item> AudioFileFormat </item>
- <item> AudioFileFormat.Type </item>
- <item> AudioFileReader </item>
- <item> AudioFileWriter </item>
- <item> AudioFormat </item>
- <item> AudioFormat.Encoding </item>
- <item> AudioInputStream </item>
- <item> AudioPermission </item>
- <item> AudioSystem </item>
- <item> AuthenticationException </item>
- <item> AuthenticationNotSupportedException </item>
- <item> Authenticator </item>
- <item> AuthPermission </item>
- <item> Autoscroll </item>
- <item> AWTError </item>
- <item> AWTEvent </item>
- <item> AWTEventListener </item>
- <item> AWTEventListenerProxy </item>
- <item> AWTEventMulticaster </item>
- <item> AWTException </item>
- <item> AWTKeyStroke </item>
- <item> AWTPermission </item>
- <item> BackingStoreException </item>
- <item> BAD_CONTEXT </item>
- <item> BAD_INV_ORDER </item>
- <item> BAD_OPERATION </item>
- <item> BAD_PARAM </item>
- <item> BAD_POLICY </item>
- <item> BAD_POLICY_TYPE </item>
- <item> BAD_POLICY_VALUE </item>
- <item> BAD_TYPECODE </item>
- <item> BadKind </item>
- <item> BadLocationException </item>
- <item> BadPaddingException </item>
- <item> BandCombineOp </item>
- <item> BandedSampleModel </item>
- <item> BasicArrowButton </item>
- <item> BasicAttribute </item>
- <item> BasicAttributes </item>
- <item> BasicBorders </item>
- <item> BasicBorders.ButtonBorder </item>
- <item> BasicBorders.FieldBorder </item>
- <item> BasicBorders.MarginBorder </item>
- <item> BasicBorders.MenuBarBorder </item>
- <item> BasicBorders.RadioButtonBorder </item>
- <item> BasicBorders.RolloverButtonBorder </item>
- <item> BasicBorders.SplitPaneBorder </item>
- <item> BasicBorders.ToggleButtonBorder </item>
- <item> BasicButtonListener </item>
- <item> BasicButtonUI </item>
- <item> BasicCheckBoxMenuItemUI </item>
- <item> BasicCheckBoxUI </item>
- <item> BasicColorChooserUI </item>
- <item> BasicComboBoxEditor </item>
- <item> BasicComboBoxEditor.UIResource </item>
- <item> BasicComboBoxRenderer </item>
- <item> BasicComboBoxRenderer.UIResource </item>
- <item> BasicComboBoxUI </item>
- <item> BasicComboPopup </item>
- <item> BasicDesktopIconUI </item>
- <item> BasicDesktopPaneUI </item>
- <item> BasicDirectoryModel </item>
- <item> BasicEditorPaneUI </item>
- <item> BasicFileChooserUI </item>
- <item> BasicFormattedTextFieldUI </item>
- <item> BasicGraphicsUtils </item>
- <item> BasicHTML </item>
- <item> BasicIconFactory </item>
- <item> BasicInternalFrameTitlePane </item>
- <item> BasicInternalFrameUI </item>
- <item> BasicLabelUI </item>
- <item> BasicListUI </item>
- <item> BasicLookAndFeel </item>
- <item> BasicMenuBarUI </item>
- <item> BasicMenuItemUI </item>
- <item> BasicMenuUI </item>
- <item> BasicOptionPaneUI </item>
- <item> BasicOptionPaneUI.ButtonAreaLayout </item>
- <item> BasicPanelUI </item>
- <item> BasicPasswordFieldUI </item>
- <item> BasicPermission </item>
- <item> BasicPopupMenuSeparatorUI </item>
- <item> BasicPopupMenuUI </item>
- <item> BasicProgressBarUI </item>
- <item> BasicRadioButtonMenuItemUI </item>
- <item> BasicRadioButtonUI </item>
- <item> BasicRootPaneUI </item>
- <item> BasicScrollBarUI </item>
- <item> BasicScrollPaneUI </item>
- <item> BasicSeparatorUI </item>
- <item> BasicSliderUI </item>
- <item> BasicSpinnerUI </item>
- <item> BasicSplitPaneDivider </item>
- <item> BasicSplitPaneUI </item>
- <item> BasicStroke </item>
- <item> BasicTabbedPaneUI </item>
- <item> BasicTableHeaderUI </item>
- <item> BasicTableUI </item>
- <item> BasicTextAreaUI </item>
- <item> BasicTextFieldUI </item>
- <item> BasicTextPaneUI </item>
- <item> BasicTextUI </item>
- <item> BasicTextUI.BasicCaret </item>
- <item> BasicTextUI.BasicHighlighter </item>
- <item> BasicToggleButtonUI </item>
- <item> BasicToolBarSeparatorUI </item>
- <item> BasicToolBarUI </item>
- <item> BasicToolTipUI </item>
- <item> BasicTreeUI </item>
- <item> BasicViewportUI </item>
- <item> BatchUpdateException </item>
- <item> BeanContext </item>
- <item> BeanContextChild </item>
- <item> BeanContextChildComponentProxy </item>
- <item> BeanContextChildSupport </item>
- <item> BeanContextContainerProxy </item>
- <item> BeanContextEvent </item>
- <item> BeanContextMembershipEvent </item>
- <item> BeanContextMembershipListener </item>
- <item> BeanContextProxy </item>
- <item> BeanContextServiceAvailableEvent </item>
- <item> BeanContextServiceProvider </item>
- <item> BeanContextServiceProviderBeanInfo </item>
- <item> BeanContextServiceRevokedEvent </item>
- <item> BeanContextServiceRevokedListener </item>
- <item> BeanContextServices </item>
- <item> BeanContextServicesListener </item>
- <item> BeanContextServicesSupport </item>
- <item> BeanContextServicesSupport.BCSSServiceProvider </item>
- <item> BeanContextSupport </item>
- <item> BeanContextSupport.BCSIterator </item>
- <item> BeanDescriptor </item>
- <item> BeanInfo </item>
- <item> Beans </item>
- <item> BevelBorder </item>
- <item> Bidi </item>
- <item> BigDecimal </item>
- <item> BigInteger </item>
- <item> BinaryRefAddr </item>
- <item> BindException </item>
- <item> Binding </item>
- <item> Binding </item>
- <item> BindingHelper </item>
- <item> BindingHolder </item>
- <item> BindingIterator </item>
- <item> BindingIteratorHelper </item>
- <item> BindingIteratorHolder </item>
- <item> BindingIteratorOperations </item>
- <item> BindingIteratorPOA </item>
- <item> BindingListHelper </item>
- <item> BindingListHolder </item>
- <item> BindingType </item>
- <item> BindingTypeHelper </item>
- <item> BindingTypeHolder </item>
- <item> BitSet </item>
- <item> Blob </item>
- <item> BlockView </item>
- <item> Book </item>
- <item> Boolean </item>
- <item> BooleanControl </item>
- <item> BooleanControl.Type </item>
- <item> BooleanHolder </item>
- <item> BooleanSeqHelper </item>
- <item> BooleanSeqHolder </item>
- <item> Border </item>
- <item> BorderFactory </item>
- <item> BorderLayout </item>
- <item> BorderUIResource </item>
- <item> BorderUIResource.BevelBorderUIResource </item>
- <item> BorderUIResource.CompoundBorderUIResource </item>
- <item> BorderUIResource.EmptyBorderUIResource </item>
- <item> BorderUIResource.EtchedBorderUIResource </item>
- <item> BorderUIResource.LineBorderUIResource </item>
- <item> BorderUIResource.MatteBorderUIResource </item>
- <item> BorderUIResource.TitledBorderUIResource </item>
- <item> BoundedRangeModel </item>
- <item> Bounds </item>
- <item> Bounds </item>
- <item> Box </item>
- <item> Box.Filler </item>
- <item> BoxedValueHelper </item>
- <item> BoxLayout </item>
- <item> BoxView </item>
- <item> BreakIterator </item>
- <item> Buffer </item>
- <item> BufferCapabilities </item>
- <item> BufferCapabilities.FlipContents </item>
- <item> BufferedImage </item>
- <item> BufferedImageFilter </item>
- <item> BufferedImageOp </item>
- <item> BufferedInputStream </item>
- <item> BufferedOutputStream </item>
- <item> BufferedReader </item>
- <item> BufferedWriter </item>
- <item> BufferOverflowException </item>
- <item> BufferStrategy </item>
- <item> BufferUnderflowException </item>
- <item> Button </item>
- <item> ButtonGroup </item>
- <item> ButtonModel </item>
- <item> ButtonUI </item>
- <item> Byte </item>
- <item> ByteArrayInputStream </item>
- <item> ByteArrayOutputStream </item>
- <item> ByteBuffer </item>
- <item> ByteChannel </item>
- <item> ByteHolder </item>
- <item> ByteLookupTable </item>
- <item> ByteOrder </item>
- <item> Calendar </item>
- <item> CallableStatement </item>
- <item> Callback </item>
- <item> CallbackHandler </item>
- <item> CancelablePrintJob </item>
- <item> CancelledKeyException </item>
- <item> CannotProceed </item>
- <item> CannotProceedException </item>
- <item> CannotProceedHelper </item>
- <item> CannotProceedHolder </item>
- <item> CannotRedoException </item>
- <item> CannotUndoException </item>
- <item> Canvas </item>
- <item> CardLayout </item>
- <item> Caret </item>
- <item> CaretEvent </item>
- <item> CaretListener </item>
- <item> CDATASection </item>
- <item> CellEditor </item>
- <item> CellEditorListener </item>
- <item> CellRendererPane </item>
- <item> Certificate </item>
- <item> Certificate </item>
- <item> Certificate </item>
- <item> Certificate.CertificateRep </item>
- <item> CertificateEncodingException </item>
- <item> CertificateEncodingException </item>
- <item> CertificateException </item>
- <item> CertificateException </item>
- <item> CertificateExpiredException </item>
- <item> CertificateExpiredException </item>
- <item> CertificateFactory </item>
- <item> CertificateFactorySpi </item>
- <item> CertificateNotYetValidException </item>
- <item> CertificateNotYetValidException </item>
- <item> CertificateParsingException </item>
- <item> CertificateParsingException </item>
- <item> CertPath </item>
- <item> CertPath.CertPathRep </item>
- <item> CertPathBuilder </item>
- <item> CertPathBuilderException </item>
- <item> CertPathBuilderResult </item>
- <item> CertPathBuilderSpi </item>
- <item> CertPathParameters </item>
- <item> CertPathValidator </item>
- <item> CertPathValidatorException </item>
- <item> CertPathValidatorResult </item>
- <item> CertPathValidatorSpi </item>
- <item> CertSelector </item>
- <item> CertStore </item>
- <item> CertStoreException </item>
- <item> CertStoreParameters </item>
- <item> CertStoreSpi </item>
- <item> ChangedCharSetException </item>
- <item> ChangeEvent </item>
- <item> ChangeListener </item>
- <item> Channel </item>
- <item> ChannelBinding </item>
- <item> Channels </item>
- <item> Character </item>
- <item> Character.Subset </item>
- <item> Character.UnicodeBlock </item>
- <item> CharacterCodingException </item>
- <item> CharacterData </item>
- <item> CharacterIterator </item>
- <item> CharArrayReader </item>
- <item> CharArrayWriter </item>
- <item> CharBuffer </item>
- <item> CharConversionException </item>
- <item> CharHolder </item>
- <item> CharSeqHelper </item>
- <item> CharSeqHolder </item>
- <item> CharSequence </item>
- <item> Charset </item>
- <item> CharsetDecoder </item>
- <item> CharsetEncoder </item>
- <item> CharsetProvider </item>
- <item> Checkbox </item>
- <item> CheckboxGroup </item>
- <item> CheckboxMenuItem </item>
- <item> CheckedInputStream </item>
- <item> CheckedOutputStream </item>
- <item> Checksum </item>
- <item> Choice </item>
- <item> ChoiceCallback </item>
- <item> ChoiceFormat </item>
- <item> Chromaticity </item>
- <item> Cipher </item>
- <item> CipherInputStream </item>
- <item> CipherOutputStream </item>
- <item> CipherSpi </item>
- <item> Class </item>
- <item> ClassCastException </item>
- <item> ClassCircularityError </item>
- <item> ClassDesc </item>
- <item> ClassFormatError </item>
- <item> ClassLoader </item>
- <item> ClassNotFoundException </item>
- <item> ClientRequestInfo </item>
- <item> ClientRequestInfoOperations </item>
- <item> ClientRequestInterceptor </item>
- <item> ClientRequestInterceptorOperations </item>
- <item> Clip </item>
- <item> Clipboard </item>
- <item> ClipboardOwner </item>
- <item> Clob </item>
- <item> Cloneable </item>
- <item> CloneNotSupportedException </item>
- <item> ClosedByInterruptException </item>
- <item> ClosedChannelException </item>
- <item> ClosedSelectorException </item>
- <item> CMMException </item>
- <item> Codec </item>
- <item> CodecFactory </item>
- <item> CodecFactoryHelper </item>
- <item> CodecFactoryOperations </item>
- <item> CodecOperations </item>
- <item> CoderMalfunctionError </item>
- <item> CoderResult </item>
- <item> CodeSets </item>
- <item> CodeSource </item>
- <item> CodingErrorAction </item>
- <item> CollationElementIterator </item>
- <item> CollationKey </item>
- <item> Collator </item>
- <item> Collection </item>
- <item> CollectionCertStoreParameters </item>
- <item> Collections </item>
- <item> Color </item>
- <item> ColorChooserComponentFactory </item>
- <item> ColorChooserUI </item>
- <item> ColorConvertOp </item>
- <item> ColorModel </item>
- <item> ColorSelectionModel </item>
- <item> ColorSpace </item>
- <item> ColorSupported </item>
- <item> ColorUIResource </item>
- <item> ComboBoxEditor </item>
- <item> ComboBoxModel </item>
- <item> ComboBoxUI </item>
- <item> ComboPopup </item>
- <item> COMM_FAILURE </item>
- <item> Comment </item>
- <item> CommunicationException </item>
- <item> Comparable </item>
- <item> Comparator </item>
- <item> Compiler </item>
- <item> CompletionStatus </item>
- <item> CompletionStatusHelper </item>
- <item> Component </item>
- <item> ComponentAdapter </item>
- <item> ComponentColorModel </item>
- <item> ComponentEvent </item>
- <item> ComponentIdHelper </item>
- <item> ComponentInputMap </item>
- <item> ComponentInputMapUIResource </item>
- <item> ComponentListener </item>
- <item> ComponentOrientation </item>
- <item> ComponentSampleModel </item>
- <item> ComponentUI </item>
- <item> ComponentView </item>
- <item> Composite </item>
- <item> CompositeContext </item>
- <item> CompositeName </item>
- <item> CompositeView </item>
- <item> CompoundBorder </item>
- <item> CompoundControl </item>
- <item> CompoundControl.Type </item>
- <item> CompoundEdit </item>
- <item> CompoundName </item>
- <item> Compression </item>
- <item> ConcurrentModificationException </item>
- <item> Configuration </item>
- <item> ConfigurationException </item>
- <item> ConfirmationCallback </item>
- <item> ConnectException </item>
- <item> ConnectException </item>
- <item> ConnectIOException </item>
- <item> Connection </item>
- <item> ConnectionEvent </item>
- <item> ConnectionEventListener </item>
- <item> ConnectionPendingException </item>
- <item> ConnectionPoolDataSource </item>
- <item> ConsoleHandler </item>
- <item> Constructor </item>
- <item> Container </item>
- <item> ContainerAdapter </item>
- <item> ContainerEvent </item>
- <item> ContainerListener </item>
- <item> ContainerOrderFocusTraversalPolicy </item>
- <item> ContentHandler </item>
- <item> ContentHandler </item>
- <item> ContentHandlerFactory </item>
- <item> ContentModel </item>
- <item> Context </item>
- <item> Context </item>
- <item> ContextList </item>
- <item> ContextNotEmptyException </item>
- <item> ContextualRenderedImageFactory </item>
- <item> Control </item>
- <item> Control </item>
- <item> Control.Type </item>
- <item> ControlFactory </item>
- <item> ControllerEventListener </item>
- <item> ConvolveOp </item>
- <item> CookieHolder </item>
- <item> Copies </item>
- <item> CopiesSupported </item>
- <item> CRC32 </item>
- <item> CredentialExpiredException </item>
- <item> CRL </item>
- <item> CRLException </item>
- <item> CRLSelector </item>
- <item> CropImageFilter </item>
- <item> CSS </item>
- <item> CSS.Attribute </item>
- <item> CTX_RESTRICT_SCOPE </item>
- <item> CubicCurve2D </item>
- <item> CubicCurve2D.Double </item>
- <item> CubicCurve2D.Float </item>
- <item> Currency </item>
- <item> Current </item>
- <item> Current </item>
- <item> Current </item>
- <item> CurrentHelper </item>
- <item> CurrentHelper </item>
- <item> CurrentHelper </item>
- <item> CurrentHolder </item>
- <item> CurrentOperations </item>
- <item> CurrentOperations </item>
- <item> CurrentOperations </item>
- <item> Cursor </item>
- <item> Customizer </item>
- <item> CustomMarshal </item>
- <item> CustomValue </item>
- <item> DATA_CONVERSION </item>
- <item> DatabaseMetaData </item>
- <item> DataBuffer </item>
- <item> DataBufferByte </item>
- <item> DataBufferDouble </item>
- <item> DataBufferFloat </item>
- <item> DataBufferInt </item>
- <item> DataBufferShort </item>
- <item> DataBufferUShort </item>
- <item> DataFlavor </item>
- <item> DataFormatException </item>
- <item> DatagramChannel </item>
- <item> DatagramPacket </item>
- <item> DatagramSocket </item>
- <item> DatagramSocketImpl </item>
- <item> DatagramSocketImplFactory </item>
- <item> DataInput </item>
- <item> DataInputStream </item>
- <item> DataInputStream </item>
- <item> DataLine </item>
- <item> DataLine.Info </item>
- <item> DataOutput </item>
- <item> DataOutputStream </item>
- <item> DataOutputStream </item>
- <item> DataSource </item>
- <item> DataTruncation </item>
- <item> Date </item>
- <item> Date </item>
- <item> DateFormat </item>
- <item> DateFormat.Field </item>
- <item> DateFormatSymbols </item>
- <item> DateFormatter </item>
- <item> DateTimeAtCompleted </item>
- <item> DateTimeAtCreation </item>
- <item> DateTimeAtProcessing </item>
- <item> DateTimeSyntax </item>
- <item> DebugGraphics </item>
- <item> DecimalFormat </item>
- <item> DecimalFormatSymbols </item>
- <item> DeclHandler </item>
- <item> DefaultBoundedRangeModel </item>
- <item> DefaultButtonModel </item>
- <item> DefaultCaret </item>
- <item> DefaultCellEditor </item>
- <item> DefaultColorSelectionModel </item>
- <item> DefaultComboBoxModel </item>
- <item> DefaultDesktopManager </item>
- <item> DefaultEditorKit </item>
- <item> DefaultEditorKit.BeepAction </item>
- <item> DefaultEditorKit.CopyAction </item>
- <item> DefaultEditorKit.CutAction </item>
- <item> DefaultEditorKit.DefaultKeyTypedAction </item>
- <item> DefaultEditorKit.InsertBreakAction </item>
- <item> DefaultEditorKit.InsertContentAction </item>
- <item> DefaultEditorKit.InsertTabAction </item>
- <item> DefaultEditorKit.PasteAction </item>
- <item> DefaultFocusManager </item>
- <item> DefaultFocusTraversalPolicy </item>
- <item> DefaultFormatter </item>
- <item> DefaultFormatterFactory </item>
- <item> DefaultHandler </item>
- <item> DefaultHighlighter </item>
- <item> DefaultHighlighter.DefaultHighlightPainter </item>
- <item> DefaultKeyboardFocusManager </item>
- <item> DefaultListCellRenderer </item>
- <item> DefaultListCellRenderer.UIResource </item>
- <item> DefaultListModel </item>
- <item> DefaultListSelectionModel </item>
- <item> DefaultMenuLayout </item>
- <item> DefaultMetalTheme </item>
- <item> DefaultMutableTreeNode </item>
- <item> DefaultPersistenceDelegate </item>
- <item> DefaultSingleSelectionModel </item>
- <item> DefaultStyledDocument </item>
- <item> DefaultStyledDocument.AttributeUndoableEdit </item>
- <item> DefaultStyledDocument.ElementSpec </item>
- <item> DefaultTableCellRenderer </item>
- <item> DefaultTableCellRenderer.UIResource </item>
- <item> DefaultTableColumnModel </item>
- <item> DefaultTableModel </item>
- <item> DefaultTextUI </item>
- <item> DefaultTreeCellEditor </item>
- <item> DefaultTreeCellRenderer </item>
- <item> DefaultTreeModel </item>
- <item> DefaultTreeSelectionModel </item>
- <item> DefinitionKind </item>
- <item> DefinitionKindHelper </item>
- <item> Deflater </item>
- <item> DeflaterOutputStream </item>
- <item> Delegate </item>
- <item> Delegate </item>
- <item> Delegate </item>
- <item> DelegationPermission </item>
- <item> DESedeKeySpec </item>
- <item> DesignMode </item>
- <item> DESKeySpec </item>
- <item> DesktopIconUI </item>
- <item> DesktopManager </item>
- <item> DesktopPaneUI </item>
- <item> Destination </item>
- <item> Destroyable </item>
- <item> DestroyFailedException </item>
- <item> DGC </item>
- <item> DHGenParameterSpec </item>
- <item> DHKey </item>
- <item> DHParameterSpec </item>
- <item> DHPrivateKey </item>
- <item> DHPrivateKeySpec </item>
- <item> DHPublicKey </item>
- <item> DHPublicKeySpec </item>
- <item> Dialog </item>
- <item> Dictionary </item>
- <item> DigestException </item>
- <item> DigestInputStream </item>
- <item> DigestOutputStream </item>
- <item> Dimension </item>
- <item> Dimension2D </item>
- <item> DimensionUIResource </item>
- <item> DirContext </item>
- <item> DirectColorModel </item>
- <item> DirectoryManager </item>
- <item> DirObjectFactory </item>
- <item> DirStateFactory </item>
- <item> DirStateFactory.Result </item>
- <item> DisplayMode </item>
- <item> DnDConstants </item>
- <item> Doc </item>
- <item> DocAttribute </item>
- <item> DocAttributeSet </item>
- <item> DocFlavor </item>
- <item> DocFlavor.BYTE_ARRAY </item>
- <item> DocFlavor.CHAR_ARRAY </item>
- <item> DocFlavor.INPUT_STREAM </item>
- <item> DocFlavor.READER </item>
- <item> DocFlavor.SERVICE_FORMATTED </item>
- <item> DocFlavor.STRING </item>
- <item> DocFlavor.URL </item>
- <item> DocPrintJob </item>
- <item> Document </item>
- <item> Document </item>
- <item> DocumentBuilder </item>
- <item> DocumentBuilderFactory </item>
- <item> DocumentEvent </item>
- <item> DocumentEvent.ElementChange </item>
- <item> DocumentEvent.EventType </item>
- <item> DocumentFilter </item>
- <item> DocumentFilter.FilterBypass </item>
- <item> DocumentFragment </item>
- <item> DocumentHandler </item>
- <item> DocumentListener </item>
- <item> DocumentName </item>
- <item> DocumentParser </item>
- <item> DocumentType </item>
- <item> DomainCombiner </item>
- <item> DomainManager </item>
- <item> DomainManagerOperations </item>
- <item> DOMException </item>
- <item> DOMImplementation </item>
- <item> DOMLocator </item>
- <item> DOMResult </item>
- <item> DOMSource </item>
- <item> Double </item>
- <item> DoubleBuffer </item>
- <item> DoubleHolder </item>
- <item> DoubleSeqHelper </item>
- <item> DoubleSeqHolder </item>
- <item> DragGestureEvent </item>
- <item> DragGestureListener </item>
- <item> DragGestureRecognizer </item>
- <item> DragSource </item>
- <item> DragSourceAdapter </item>
- <item> DragSourceContext </item>
- <item> DragSourceDragEvent </item>
- <item> DragSourceDropEvent </item>
- <item> DragSourceEvent </item>
- <item> DragSourceListener </item>
- <item> DragSourceMotionListener </item>
- <item> Driver </item>
- <item> DriverManager </item>
- <item> DriverPropertyInfo </item>
- <item> DropTarget </item>
- <item> DropTarget.DropTargetAutoScroller </item>
- <item> DropTargetAdapter </item>
- <item> DropTargetContext </item>
- <item> DropTargetDragEvent </item>
- <item> DropTargetDropEvent </item>
- <item> DropTargetEvent </item>
- <item> DropTargetListener </item>
- <item> DSAKey </item>
- <item> DSAKeyPairGenerator </item>
- <item> DSAParameterSpec </item>
- <item> DSAParams </item>
- <item> DSAPrivateKey </item>
- <item> DSAPrivateKeySpec </item>
- <item> DSAPublicKey </item>
- <item> DSAPublicKeySpec </item>
- <item> DTD </item>
- <item> DTDConstants </item>
- <item> DTDHandler </item>
- <item> DuplicateName </item>
- <item> DuplicateNameHelper </item>
- <item> DynamicImplementation </item>
- <item> DynamicImplementation </item>
- <item> DynAny </item>
- <item> DynAny </item>
- <item> DynAnyFactory </item>
- <item> DynAnyFactoryHelper </item>
- <item> DynAnyFactoryOperations </item>
- <item> DynAnyHelper </item>
- <item> DynAnyOperations </item>
- <item> DynAnySeqHelper </item>
- <item> DynArray </item>
- <item> DynArray </item>
- <item> DynArrayHelper </item>
- <item> DynArrayOperations </item>
- <item> DynEnum </item>
- <item> DynEnum </item>
- <item> DynEnumHelper </item>
- <item> DynEnumOperations </item>
- <item> DynFixed </item>
- <item> DynFixed </item>
- <item> DynFixedHelper </item>
- <item> DynFixedOperations </item>
- <item> DynSequence </item>
- <item> DynSequence </item>
- <item> DynSequenceHelper </item>
- <item> DynSequenceOperations </item>
- <item> DynStruct </item>
- <item> DynStruct </item>
- <item> DynStructHelper </item>
- <item> DynStructOperations </item>
- <item> DynUnion </item>
- <item> DynUnion </item>
- <item> DynUnionHelper </item>
- <item> DynUnionOperations </item>
- <item> DynValue </item>
- <item> DynValue </item>
- <item> DynValueBox </item>
- <item> DynValueBoxOperations </item>
- <item> DynValueCommon </item>
- <item> DynValueCommonOperations </item>
- <item> DynValueHelper </item>
- <item> DynValueOperations </item>
- <item> EditorKit </item>
- <item> Element </item>
- <item> Element </item>
- <item> Element </item>
- <item> ElementIterator </item>
- <item> Ellipse2D </item>
- <item> Ellipse2D.Double </item>
- <item> Ellipse2D.Float </item>
- <item> EmptyBorder </item>
- <item> EmptyStackException </item>
- <item> EncodedKeySpec </item>
- <item> Encoder </item>
- <item> Encoding </item>
- <item> ENCODING_CDR_ENCAPS </item>
- <item> EncryptedPrivateKeyInfo </item>
- <item> Entity </item>
- <item> Entity </item>
- <item> EntityReference </item>
- <item> EntityResolver </item>
- <item> EnumControl </item>
- <item> EnumControl.Type </item>
- <item> Enumeration </item>
- <item> EnumSyntax </item>
- <item> Environment </item>
- <item> EOFException </item>
- <item> Error </item>
- <item> ErrorHandler </item>
- <item> ErrorListener </item>
- <item> ErrorManager </item>
- <item> EtchedBorder </item>
- <item> Event </item>
- <item> EventContext </item>
- <item> EventDirContext </item>
- <item> EventHandler </item>
- <item> EventListener </item>
- <item> EventListenerList </item>
- <item> EventListenerProxy </item>
- <item> EventObject </item>
- <item> EventQueue </item>
- <item> EventSetDescriptor </item>
- <item> Exception </item>
- <item> ExceptionInInitializerError </item>
- <item> ExceptionList </item>
- <item> ExceptionListener </item>
- <item> ExemptionMechanism </item>
- <item> ExemptionMechanismException </item>
- <item> ExemptionMechanismSpi </item>
- <item> ExpandVetoException </item>
- <item> ExportException </item>
- <item> Expression </item>
- <item> ExtendedRequest </item>
- <item> ExtendedResponse </item>
- <item> Externalizable </item>
- <item> FactoryConfigurationError </item>
- <item> FailedLoginException </item>
- <item> FeatureDescriptor </item>
- <item> Fidelity </item>
- <item> Field </item>
- <item> FieldNameHelper </item>
- <item> FieldNameHelper </item>
- <item> FieldPosition </item>
- <item> FieldView </item>
- <item> File </item>
- <item> FileCacheImageInputStream </item>
- <item> FileCacheImageOutputStream </item>
- <item> FileChannel </item>
- <item> FileChannel.MapMode </item>
- <item> FileChooserUI </item>
- <item> FileDescriptor </item>
- <item> FileDialog </item>
- <item> FileFilter </item>
- <item> FileFilter </item>
- <item> FileHandler </item>
- <item> FileImageInputStream </item>
- <item> FileImageOutputStream </item>
- <item> FileInputStream </item>
- <item> FileLock </item>
- <item> FileLockInterruptionException </item>
- <item> FilenameFilter </item>
- <item> FileNameMap </item>
- <item> FileNotFoundException </item>
- <item> FileOutputStream </item>
- <item> FilePermission </item>
- <item> FileReader </item>
- <item> FileSystemView </item>
- <item> FileView </item>
- <item> FileWriter </item>
- <item> Filter </item>
- <item> FilteredImageSource </item>
- <item> FilterInputStream </item>
- <item> FilterOutputStream </item>
- <item> FilterReader </item>
- <item> FilterWriter </item>
- <item> Finishings </item>
- <item> FixedHeightLayoutCache </item>
- <item> FixedHolder </item>
- <item> FlatteningPathIterator </item>
- <item> FlavorException </item>
- <item> FlavorMap </item>
- <item> FlavorTable </item>
- <item> Float </item>
- <item> FloatBuffer </item>
- <item> FloatControl </item>
- <item> FloatControl.Type </item>
- <item> FloatHolder </item>
- <item> FloatSeqHelper </item>
- <item> FloatSeqHolder </item>
- <item> FlowLayout </item>
- <item> FlowView </item>
- <item> FlowView.FlowStrategy </item>
- <item> FocusAdapter </item>
- <item> FocusEvent </item>
- <item> FocusListener </item>
- <item> FocusManager </item>
- <item> FocusTraversalPolicy </item>
- <item> Font </item>
- <item> FontFormatException </item>
- <item> FontMetrics </item>
- <item> FontRenderContext </item>
- <item> FontUIResource </item>
- <item> Format </item>
- <item> Format.Field </item>
- <item> FormatConversionProvider </item>
- <item> FormatMismatch </item>
- <item> FormatMismatchHelper </item>
- <item> Formatter </item>
- <item> FormView </item>
- <item> ForwardRequest </item>
- <item> ForwardRequest </item>
- <item> ForwardRequestHelper </item>
- <item> ForwardRequestHelper </item>
- <item> Frame </item>
- <item> FREE_MEM </item>
- <item> GapContent </item>
- <item> GatheringByteChannel </item>
- <item> GeneralPath </item>
- <item> GeneralSecurityException </item>
- <item> GlyphJustificationInfo </item>
- <item> GlyphMetrics </item>
- <item> GlyphVector </item>
- <item> GlyphView </item>
- <item> GlyphView.GlyphPainter </item>
- <item> GradientPaint </item>
- <item> GraphicAttribute </item>
- <item> Graphics </item>
- <item> Graphics2D </item>
- <item> GraphicsConfigTemplate </item>
- <item> GraphicsConfiguration </item>
- <item> GraphicsDevice </item>
- <item> GraphicsEnvironment </item>
- <item> GrayFilter </item>
- <item> GregorianCalendar </item>
- <item> GridBagConstraints </item>
- <item> GridBagLayout </item>
- <item> GridLayout </item>
- <item> Group </item>
- <item> GSSContext </item>
- <item> GSSCredential </item>
- <item> GSSException </item>
- <item> GSSManager </item>
- <item> GSSName </item>
- <item> Guard </item>
- <item> GuardedObject </item>
- <item> GZIPInputStream </item>
- <item> GZIPOutputStream </item>
- <item> Handler </item>
- <item> HandlerBase </item>
- <item> HandshakeCompletedEvent </item>
- <item> HandshakeCompletedListener </item>
- <item> HasControls </item>
- <item> HashAttributeSet </item>
- <item> HashDocAttributeSet </item>
- <item> HashMap </item>
- <item> HashPrintJobAttributeSet </item>
- <item> HashPrintRequestAttributeSet </item>
- <item> HashPrintServiceAttributeSet </item>
- <item> HashSet </item>
- <item> Hashtable </item>
- <item> HeadlessException </item>
- <item> HierarchyBoundsAdapter </item>
- <item> HierarchyBoundsListener </item>
- <item> HierarchyEvent </item>
- <item> HierarchyListener </item>
- <item> Highlighter </item>
- <item> Highlighter.Highlight </item>
- <item> Highlighter.HighlightPainter </item>
- <item> HostnameVerifier </item>
- <item> HTML </item>
- <item> HTML.Attribute </item>
- <item> HTML.Tag </item>
- <item> HTML.UnknownTag </item>
- <item> HTMLDocument </item>
- <item> HTMLDocument.Iterator </item>
- <item> HTMLEditorKit </item>
- <item> HTMLEditorKit.HTMLFactory </item>
- <item> HTMLEditorKit.HTMLTextAction </item>
- <item> HTMLEditorKit.InsertHTMLTextAction </item>
- <item> HTMLEditorKit.LinkController </item>
- <item> HTMLEditorKit.Parser </item>
- <item> HTMLEditorKit.ParserCallback </item>
- <item> HTMLFrameHyperlinkEvent </item>
- <item> HTMLWriter </item>
- <item> HttpsURLConnection </item>
- <item> HttpURLConnection </item>
- <item> HyperlinkEvent </item>
- <item> HyperlinkEvent.EventType </item>
- <item> HyperlinkListener </item>
- <item> ICC_ColorSpace </item>
- <item> ICC_Profile </item>
- <item> ICC_ProfileGray </item>
- <item> ICC_ProfileRGB </item>
- <item> Icon </item>
- <item> IconUIResource </item>
- <item> IconView </item>
- <item> ID_ASSIGNMENT_POLICY_ID </item>
- <item> ID_UNIQUENESS_POLICY_ID </item>
- <item> IdAssignmentPolicy </item>
- <item> IdAssignmentPolicyOperations </item>
- <item> IdAssignmentPolicyValue </item>
- <item> IdentifierHelper </item>
- <item> Identity </item>
- <item> IdentityHashMap </item>
- <item> IdentityScope </item>
- <item> IDLEntity </item>
- <item> IDLType </item>
- <item> IDLTypeHelper </item>
- <item> IDLTypeOperations </item>
- <item> IdUniquenessPolicy </item>
- <item> IdUniquenessPolicyOperations </item>
- <item> IdUniquenessPolicyValue </item>
- <item> IIOByteBuffer </item>
- <item> IIOException </item>
- <item> IIOImage </item>
- <item> IIOInvalidTreeException </item>
- <item> IIOMetadata </item>
- <item> IIOMetadataController </item>
- <item> IIOMetadataFormat </item>
- <item> IIOMetadataFormatImpl </item>
- <item> IIOMetadataNode </item>
- <item> IIOParam </item>
- <item> IIOParamController </item>
- <item> IIOReadProgressListener </item>
- <item> IIOReadUpdateListener </item>
- <item> IIOReadWarningListener </item>
- <item> IIORegistry </item>
- <item> IIOServiceProvider </item>
- <item> IIOWriteProgressListener </item>
- <item> IIOWriteWarningListener </item>
- <item> IllegalAccessError </item>
- <item> IllegalAccessException </item>
- <item> IllegalArgumentException </item>
- <item> IllegalBlockingModeException </item>
- <item> IllegalBlockSizeException </item>
- <item> IllegalCharsetNameException </item>
- <item> IllegalComponentStateException </item>
- <item> IllegalMonitorStateException </item>
- <item> IllegalPathStateException </item>
- <item> IllegalSelectorException </item>
- <item> IllegalStateException </item>
- <item> IllegalThreadStateException </item>
- <item> Image </item>
- <item> ImageCapabilities </item>
- <item> ImageConsumer </item>
- <item> ImageFilter </item>
- <item> ImageGraphicAttribute </item>
- <item> ImageIcon </item>
- <item> ImageInputStream </item>
- <item> ImageInputStreamImpl </item>
- <item> ImageInputStreamSpi </item>
- <item> ImageIO </item>
- <item> ImageObserver </item>
- <item> ImageOutputStream </item>
- <item> ImageOutputStreamImpl </item>
- <item> ImageOutputStreamSpi </item>
- <item> ImageProducer </item>
- <item> ImageReader </item>
- <item> ImageReaderSpi </item>
- <item> ImageReaderWriterSpi </item>
- <item> ImageReadParam </item>
- <item> ImageTranscoder </item>
- <item> ImageTranscoderSpi </item>
- <item> ImageTypeSpecifier </item>
- <item> ImageView </item>
- <item> ImageWriteParam </item>
- <item> ImageWriter </item>
- <item> ImageWriterSpi </item>
- <item> ImagingOpException </item>
- <item> IMP_LIMIT </item>
- <item> IMPLICIT_ACTIVATION_POLICY_ID </item>
- <item> ImplicitActivationPolicy </item>
- <item> ImplicitActivationPolicyOperations </item>
- <item> ImplicitActivationPolicyValue </item>
- <item> IncompatibleClassChangeError </item>
- <item> InconsistentTypeCode </item>
- <item> InconsistentTypeCode </item>
- <item> InconsistentTypeCodeHelper </item>
- <item> IndexColorModel </item>
- <item> IndexedPropertyDescriptor </item>
- <item> IndexOutOfBoundsException </item>
- <item> IndirectionException </item>
- <item> Inet4Address </item>
- <item> Inet6Address </item>
- <item> InetAddress </item>
- <item> InetSocketAddress </item>
- <item> Inflater </item>
- <item> InflaterInputStream </item>
- <item> InheritableThreadLocal </item>
- <item> InitialContext </item>
- <item> InitialContextFactory </item>
- <item> InitialContextFactoryBuilder </item>
- <item> InitialDirContext </item>
- <item> INITIALIZE </item>
- <item> InitialLdapContext </item>
- <item> InlineView </item>
- <item> InputContext </item>
- <item> InputEvent </item>
- <item> InputMap </item>
- <item> InputMapUIResource </item>
- <item> InputMethod </item>
- <item> InputMethodContext </item>
- <item> InputMethodDescriptor </item>
- <item> InputMethodEvent </item>
- <item> InputMethodHighlight </item>
- <item> InputMethodListener </item>
- <item> InputMethodRequests </item>
- <item> InputSource </item>
- <item> InputStream </item>
- <item> InputStream </item>
- <item> InputStream </item>
- <item> InputStreamReader </item>
- <item> InputSubset </item>
- <item> InputVerifier </item>
- <item> Insets </item>
- <item> InsetsUIResource </item>
- <item> InstantiationError </item>
- <item> InstantiationException </item>
- <item> Instrument </item>
- <item> InsufficientResourcesException </item>
- <item> IntBuffer </item>
- <item> Integer </item>
- <item> IntegerSyntax </item>
- <item> Interceptor </item>
- <item> InterceptorOperations </item>
- <item> INTERNAL </item>
- <item> InternalError </item>
- <item> InternalFrameAdapter </item>
- <item> InternalFrameEvent </item>
- <item> InternalFrameFocusTraversalPolicy </item>
- <item> InternalFrameListener </item>
- <item> InternalFrameUI </item>
- <item> InternationalFormatter </item>
- <item> InterruptedException </item>
- <item> InterruptedIOException </item>
- <item> InterruptedNamingException </item>
- <item> InterruptibleChannel </item>
- <item> INTF_REPOS </item>
- <item> IntHolder </item>
- <item> IntrospectionException </item>
- <item> Introspector </item>
- <item> INV_FLAG </item>
- <item> INV_IDENT </item>
- <item> INV_OBJREF </item>
- <item> INV_POLICY </item>
- <item> Invalid </item>
- <item> INVALID_TRANSACTION </item>
- <item> InvalidAddress </item>
- <item> InvalidAddressHelper </item>
- <item> InvalidAddressHolder </item>
- <item> InvalidAlgorithmParameterException </item>
- <item> InvalidAttributeIdentifierException </item>
- <item> InvalidAttributesException </item>
- <item> InvalidAttributeValueException </item>
- <item> InvalidClassException </item>
- <item> InvalidDnDOperationException </item>
- <item> InvalidKeyException </item>
- <item> InvalidKeySpecException </item>
- <item> InvalidMarkException </item>
- <item> InvalidMidiDataException </item>
- <item> InvalidName </item>
- <item> InvalidName </item>
- <item> InvalidName </item>
- <item> InvalidNameException </item>
- <item> InvalidNameHelper </item>
- <item> InvalidNameHelper </item>
- <item> InvalidNameHolder </item>
- <item> InvalidObjectException </item>
- <item> InvalidParameterException </item>
- <item> InvalidParameterSpecException </item>
- <item> InvalidPolicy </item>
- <item> InvalidPolicyHelper </item>
- <item> InvalidPreferencesFormatException </item>
- <item> InvalidSearchControlsException </item>
- <item> InvalidSearchFilterException </item>
- <item> InvalidSeq </item>
- <item> InvalidSlot </item>
- <item> InvalidSlotHelper </item>
- <item> InvalidTransactionException </item>
- <item> InvalidTypeForEncoding </item>
- <item> InvalidTypeForEncodingHelper </item>
- <item> InvalidValue </item>
- <item> InvalidValue </item>
- <item> InvalidValueHelper </item>
- <item> InvocationEvent </item>
- <item> InvocationHandler </item>
- <item> InvocationTargetException </item>
- <item> InvokeHandler </item>
- <item> IOException </item>
- <item> IOR </item>
- <item> IORHelper </item>
- <item> IORHolder </item>
- <item> IORInfo </item>
- <item> IORInfoOperations </item>
- <item> IORInterceptor </item>
- <item> IORInterceptorOperations </item>
- <item> IRObject </item>
- <item> IRObjectOperations </item>
- <item> IstringHelper </item>
- <item> ItemEvent </item>
- <item> ItemListener </item>
- <item> ItemSelectable </item>
- <item> Iterator </item>
- <item> IvParameterSpec </item>
- <item> JApplet </item>
- <item> JarEntry </item>
- <item> JarException </item>
- <item> JarFile </item>
- <item> JarInputStream </item>
- <item> JarOutputStream </item>
- <item> JarURLConnection </item>
- <item> JButton </item>
- <item> JCheckBox </item>
- <item> JCheckBoxMenuItem </item>
- <item> JColorChooser </item>
- <item> JComboBox </item>
- <item> JComboBox.KeySelectionManager </item>
- <item> JComponent </item>
- <item> JDesktopPane </item>
- <item> JDialog </item>
- <item> JEditorPane </item>
- <item> JFileChooser </item>
- <item> JFormattedTextField </item>
- <item> JFormattedTextField.AbstractFormatter </item>
- <item> JFormattedTextField.AbstractFormatterFactory </item>
- <item> JFrame </item>
- <item> JInternalFrame </item>
- <item> JInternalFrame.JDesktopIcon </item>
- <item> JLabel </item>
- <item> JLayeredPane </item>
- <item> JList </item>
- <item> JMenu </item>
- <item> JMenuBar </item>
- <item> JMenuItem </item>
- <item> JobAttributes </item>
- <item> JobAttributes.DefaultSelectionType </item>
- <item> JobAttributes.DestinationType </item>
- <item> JobAttributes.DialogType </item>
- <item> JobAttributes.MultipleDocumentHandlingType </item>
- <item> JobAttributes.SidesType </item>
- <item> JobHoldUntil </item>
- <item> JobImpressions </item>
- <item> JobImpressionsCompleted </item>
- <item> JobImpressionsSupported </item>
- <item> JobKOctets </item>
- <item> JobKOctetsProcessed </item>
- <item> JobKOctetsSupported </item>
- <item> JobMediaSheets </item>
- <item> JobMediaSheetsCompleted </item>
- <item> JobMediaSheetsSupported </item>
- <item> JobMessageFromOperator </item>
- <item> JobName </item>
- <item> JobOriginatingUserName </item>
- <item> JobPriority </item>
- <item> JobPrioritySupported </item>
- <item> JobSheets </item>
- <item> JobState </item>
- <item> JobStateReason </item>
- <item> JobStateReasons </item>
- <item> JOptionPane </item>
- <item> JPanel </item>
- <item> JPasswordField </item>
- <item> JPEGHuffmanTable </item>
- <item> JPEGImageReadParam </item>
- <item> JPEGImageWriteParam </item>
- <item> JPEGQTable </item>
- <item> JPopupMenu </item>
- <item> JPopupMenu.Separator </item>
- <item> JProgressBar </item>
- <item> JRadioButton </item>
- <item> JRadioButtonMenuItem </item>
- <item> JRootPane </item>
- <item> JScrollBar </item>
- <item> JScrollPane </item>
- <item> JSeparator </item>
- <item> JSlider </item>
- <item> JSpinner </item>
- <item> JSpinner.DateEditor </item>
- <item> JSpinner.DefaultEditor </item>
- <item> JSpinner.ListEditor </item>
- <item> JSpinner.NumberEditor </item>
- <item> JSplitPane </item>
- <item> JTabbedPane </item>
- <item> JTable </item>
- <item> JTableHeader </item>
- <item> JTextArea </item>
- <item> JTextComponent </item>
- <item> JTextComponent.KeyBinding </item>
- <item> JTextField </item>
- <item> JTextPane </item>
- <item> JToggleButton </item>
- <item> JToggleButton.ToggleButtonModel </item>
- <item> JToolBar </item>
- <item> JToolBar.Separator </item>
- <item> JToolTip </item>
- <item> JTree </item>
- <item> JTree.DynamicUtilTreeNode </item>
- <item> JTree.EmptySelectionModel </item>
- <item> JViewport </item>
- <item> JWindow </item>
- <item> KerberosKey </item>
- <item> KerberosPrincipal </item>
- <item> KerberosTicket </item>
- <item> Kernel </item>
- <item> Key </item>
- <item> KeyAdapter </item>
- <item> KeyAgreement </item>
- <item> KeyAgreementSpi </item>
- <item> KeyboardFocusManager </item>
- <item> KeyEvent </item>
- <item> KeyEventDispatcher </item>
- <item> KeyEventPostProcessor </item>
- <item> KeyException </item>
- <item> KeyFactory </item>
- <item> KeyFactorySpi </item>
- <item> KeyGenerator </item>
- <item> KeyGeneratorSpi </item>
- <item> KeyListener </item>
- <item> KeyManagementException </item>
- <item> KeyManager </item>
- <item> KeyManagerFactory </item>
- <item> KeyManagerFactorySpi </item>
- <item> Keymap </item>
- <item> KeyPair </item>
- <item> KeyPairGenerator </item>
- <item> KeyPairGeneratorSpi </item>
- <item> KeySpec </item>
- <item> KeyStore </item>
- <item> KeyStoreException </item>
- <item> KeyStoreSpi </item>
- <item> KeyStroke </item>
- <item> Label </item>
- <item> LabelUI </item>
- <item> LabelView </item>
- <item> LanguageCallback </item>
- <item> LastOwnerException </item>
- <item> LayeredHighlighter </item>
- <item> LayeredHighlighter.LayerPainter </item>
- <item> LayoutFocusTraversalPolicy </item>
- <item> LayoutManager </item>
- <item> LayoutManager2 </item>
- <item> LayoutQueue </item>
- <item> LDAPCertStoreParameters </item>
- <item> LdapContext </item>
- <item> LdapReferralException </item>
- <item> Lease </item>
- <item> Level </item>
- <item> LexicalHandler </item>
- <item> LIFESPAN_POLICY_ID </item>
- <item> LifespanPolicy </item>
- <item> LifespanPolicyOperations </item>
- <item> LifespanPolicyValue </item>
- <item> LimitExceededException </item>
- <item> Line </item>
- <item> Line.Info </item>
- <item> Line2D </item>
- <item> Line2D.Double </item>
- <item> Line2D.Float </item>
- <item> LineBorder </item>
- <item> LineBreakMeasurer </item>
- <item> LineEvent </item>
- <item> LineEvent.Type </item>
- <item> LineListener </item>
- <item> LineMetrics </item>
- <item> LineNumberInputStream </item>
- <item> LineNumberReader </item>
- <item> LineUnavailableException </item>
- <item> LinkageError </item>
- <item> LinkedHashMap </item>
- <item> LinkedHashSet </item>
- <item> LinkedList </item>
- <item> LinkException </item>
- <item> LinkLoopException </item>
- <item> LinkRef </item>
- <item> List </item>
- <item> List </item>
- <item> ListCellRenderer </item>
- <item> ListDataEvent </item>
- <item> ListDataListener </item>
- <item> ListIterator </item>
- <item> ListModel </item>
- <item> ListResourceBundle </item>
- <item> ListSelectionEvent </item>
- <item> ListSelectionListener </item>
- <item> ListSelectionModel </item>
- <item> ListUI </item>
- <item> ListView </item>
- <item> LoaderHandler </item>
- <item> Locale </item>
- <item> LocalObject </item>
- <item> LocateRegistry </item>
- <item> LOCATION_FORWARD </item>
- <item> Locator </item>
- <item> LocatorImpl </item>
- <item> Logger </item>
- <item> LoggingPermission </item>
- <item> LoginContext </item>
- <item> LoginException </item>
- <item> LoginModule </item>
- <item> LogManager </item>
- <item> LogRecord </item>
- <item> LogStream </item>
- <item> Long </item>
- <item> LongBuffer </item>
- <item> LongHolder </item>
- <item> LongLongSeqHelper </item>
- <item> LongLongSeqHolder </item>
- <item> LongSeqHelper </item>
- <item> LongSeqHolder </item>
- <item> LookAndFeel </item>
- <item> LookupOp </item>
- <item> LookupTable </item>
- <item> Mac </item>
- <item> MacSpi </item>
- <item> MalformedInputException </item>
- <item> MalformedLinkException </item>
- <item> MalformedURLException </item>
- <item> ManagerFactoryParameters </item>
- <item> Manifest </item>
- <item> Map </item>
- <item> Map.Entry </item>
- <item> MappedByteBuffer </item>
- <item> MARSHAL </item>
- <item> MarshalException </item>
- <item> MarshalledObject </item>
- <item> MaskFormatter </item>
- <item> Matcher </item>
- <item> Math </item>
- <item> MatteBorder </item>
- <item> Media </item>
- <item> MediaName </item>
- <item> MediaPrintableArea </item>
- <item> MediaSize </item>
- <item> MediaSize.Engineering </item>
- <item> MediaSize.ISO </item>
- <item> MediaSize.JIS </item>
- <item> MediaSize.NA </item>
- <item> MediaSize.Other </item>
- <item> MediaSizeName </item>
- <item> MediaTracker </item>
- <item> MediaTray </item>
- <item> Member </item>
- <item> MemoryCacheImageInputStream </item>
- <item> MemoryCacheImageOutputStream </item>
- <item> MemoryHandler </item>
- <item> MemoryImageSource </item>
- <item> Menu </item>
- <item> MenuBar </item>
- <item> MenuBarUI </item>
- <item> MenuComponent </item>
- <item> MenuContainer </item>
- <item> MenuDragMouseEvent </item>
- <item> MenuDragMouseListener </item>
- <item> MenuElement </item>
- <item> MenuEvent </item>
- <item> MenuItem </item>
- <item> MenuItemUI </item>
- <item> MenuKeyEvent </item>
- <item> MenuKeyListener </item>
- <item> MenuListener </item>
- <item> MenuSelectionManager </item>
- <item> MenuShortcut </item>
- <item> MessageDigest </item>
- <item> MessageDigestSpi </item>
- <item> MessageFormat </item>
- <item> MessageFormat.Field </item>
- <item> MessageProp </item>
- <item> MetaEventListener </item>
- <item> MetalBorders </item>
- <item> MetalBorders.ButtonBorder </item>
- <item> MetalBorders.Flush3DBorder </item>
- <item> MetalBorders.InternalFrameBorder </item>
- <item> MetalBorders.MenuBarBorder </item>
- <item> MetalBorders.MenuItemBorder </item>
- <item> MetalBorders.OptionDialogBorder </item>
- <item> MetalBorders.PaletteBorder </item>
- <item> MetalBorders.PopupMenuBorder </item>
- <item> MetalBorders.RolloverButtonBorder </item>
- <item> MetalBorders.ScrollPaneBorder </item>
- <item> MetalBorders.TableHeaderBorder </item>
- <item> MetalBorders.TextFieldBorder </item>
- <item> MetalBorders.ToggleButtonBorder </item>
- <item> MetalBorders.ToolBarBorder </item>
- <item> MetalButtonUI </item>
- <item> MetalCheckBoxIcon </item>
- <item> MetalCheckBoxUI </item>
- <item> MetalComboBoxButton </item>
- <item> MetalComboBoxEditor </item>
- <item> MetalComboBoxEditor.UIResource </item>
- <item> MetalComboBoxIcon </item>
- <item> MetalComboBoxUI </item>
- <item> MetalDesktopIconUI </item>
- <item> MetalFileChooserUI </item>
- <item> MetalIconFactory </item>
- <item> MetalIconFactory.FileIcon16 </item>
- <item> MetalIconFactory.FolderIcon16 </item>
- <item> MetalIconFactory.PaletteCloseIcon </item>
- <item> MetalIconFactory.TreeControlIcon </item>
- <item> MetalIconFactory.TreeFolderIcon </item>
- <item> MetalIconFactory.TreeLeafIcon </item>
- <item> MetalInternalFrameTitlePane </item>
- <item> MetalInternalFrameUI </item>
- <item> MetalLabelUI </item>
- <item> MetalLookAndFeel </item>
- <item> MetalPopupMenuSeparatorUI </item>
- <item> MetalProgressBarUI </item>
- <item> MetalRadioButtonUI </item>
- <item> MetalRootPaneUI </item>
- <item> MetalScrollBarUI </item>
- <item> MetalScrollButton </item>
- <item> MetalScrollPaneUI </item>
- <item> MetalSeparatorUI </item>
- <item> MetalSliderUI </item>
- <item> MetalSplitPaneUI </item>
- <item> MetalTabbedPaneUI </item>
- <item> MetalTextFieldUI </item>
- <item> MetalTheme </item>
- <item> MetalToggleButtonUI </item>
- <item> MetalToolBarUI </item>
- <item> MetalToolTipUI </item>
- <item> MetalTreeUI </item>
- <item> MetaMessage </item>
- <item> Method </item>
- <item> MethodDescriptor </item>
- <item> MidiChannel </item>
- <item> MidiDevice </item>
- <item> MidiDevice.Info </item>
- <item> MidiDeviceProvider </item>
- <item> MidiEvent </item>
- <item> MidiFileFormat </item>
- <item> MidiFileReader </item>
- <item> MidiFileWriter </item>
- <item> MidiMessage </item>
- <item> MidiSystem </item>
- <item> MidiUnavailableException </item>
- <item> MimeTypeParseException </item>
- <item> MinimalHTMLWriter </item>
- <item> MissingResourceException </item>
- <item> Mixer </item>
- <item> Mixer.Info </item>
- <item> MixerProvider </item>
- <item> ModificationItem </item>
- <item> Modifier </item>
- <item> MouseAdapter </item>
- <item> MouseDragGestureRecognizer </item>
- <item> MouseEvent </item>
- <item> MouseInputAdapter </item>
- <item> MouseInputListener </item>
- <item> MouseListener </item>
- <item> MouseMotionAdapter </item>
- <item> MouseMotionListener </item>
- <item> MouseWheelEvent </item>
- <item> MouseWheelListener </item>
- <item> MultiButtonUI </item>
- <item> MulticastSocket </item>
- <item> MultiColorChooserUI </item>
- <item> MultiComboBoxUI </item>
- <item> MultiDesktopIconUI </item>
- <item> MultiDesktopPaneUI </item>
- <item> MultiDoc </item>
- <item> MultiDocPrintJob </item>
- <item> MultiDocPrintService </item>
- <item> MultiFileChooserUI </item>
- <item> MultiInternalFrameUI </item>
- <item> MultiLabelUI </item>
- <item> MultiListUI </item>
- <item> MultiLookAndFeel </item>
- <item> MultiMenuBarUI </item>
- <item> MultiMenuItemUI </item>
- <item> MultiOptionPaneUI </item>
- <item> MultiPanelUI </item>
- <item> MultiPixelPackedSampleModel </item>
- <item> MultipleComponentProfileHelper </item>
- <item> MultipleComponentProfileHolder </item>
- <item> MultipleDocumentHandling </item>
- <item> MultipleMaster </item>
- <item> MultiPopupMenuUI </item>
- <item> MultiProgressBarUI </item>
- <item> MultiRootPaneUI </item>
- <item> MultiScrollBarUI </item>
- <item> MultiScrollPaneUI </item>
- <item> MultiSeparatorUI </item>
- <item> MultiSliderUI </item>
- <item> MultiSpinnerUI </item>
- <item> MultiSplitPaneUI </item>
- <item> MultiTabbedPaneUI </item>
- <item> MultiTableHeaderUI </item>
- <item> MultiTableUI </item>
- <item> MultiTextUI </item>
- <item> MultiToolBarUI </item>
- <item> MultiToolTipUI </item>
- <item> MultiTreeUI </item>
- <item> MultiViewportUI </item>
- <item> MutableAttributeSet </item>
- <item> MutableComboBoxModel </item>
- <item> MutableTreeNode </item>
- <item> Name </item>
- <item> NameAlreadyBoundException </item>
- <item> NameCallback </item>
- <item> NameClassPair </item>
- <item> NameComponent </item>
- <item> NameComponentHelper </item>
- <item> NameComponentHolder </item>
- <item> NamedNodeMap </item>
- <item> NamedValue </item>
- <item> NameDynAnyPair </item>
- <item> NameDynAnyPairHelper </item>
- <item> NameDynAnyPairSeqHelper </item>
- <item> NameHelper </item>
- <item> NameHolder </item>
- <item> NameNotFoundException </item>
- <item> NameParser </item>
- <item> NamespaceChangeListener </item>
- <item> NamespaceSupport </item>
- <item> NameValuePair </item>
- <item> NameValuePair </item>
- <item> NameValuePairHelper </item>
- <item> NameValuePairHelper </item>
- <item> NameValuePairSeqHelper </item>
- <item> Naming </item>
- <item> NamingContext </item>
- <item> NamingContextExt </item>
- <item> NamingContextExtHelper </item>
- <item> NamingContextExtHolder </item>
- <item> NamingContextExtOperations </item>
- <item> NamingContextExtPOA </item>
- <item> NamingContextHelper </item>
- <item> NamingContextHolder </item>
- <item> NamingContextOperations </item>
- <item> NamingContextPOA </item>
- <item> NamingEnumeration </item>
- <item> NamingEvent </item>
- <item> NamingException </item>
- <item> NamingExceptionEvent </item>
- <item> NamingListener </item>
- <item> NamingManager </item>
- <item> NamingSecurityException </item>
- <item> NavigationFilter </item>
- <item> NavigationFilter.FilterBypass </item>
- <item> NegativeArraySizeException </item>
- <item> NetPermission </item>
- <item> NetworkInterface </item>
- <item> NO_IMPLEMENT </item>
- <item> NO_MEMORY </item>
- <item> NO_PERMISSION </item>
- <item> NO_RESOURCES </item>
- <item> NO_RESPONSE </item>
- <item> NoClassDefFoundError </item>
- <item> NoConnectionPendingException </item>
- <item> NoContext </item>
- <item> NoContextHelper </item>
- <item> Node </item>
- <item> NodeChangeEvent </item>
- <item> NodeChangeListener </item>
- <item> NodeList </item>
- <item> NoInitialContextException </item>
- <item> NoninvertibleTransformException </item>
- <item> NonReadableChannelException </item>
- <item> NonWritableChannelException </item>
- <item> NoPermissionException </item>
- <item> NoRouteToHostException </item>
- <item> NoServant </item>
- <item> NoServantHelper </item>
- <item> NoSuchAlgorithmException </item>
- <item> NoSuchAttributeException </item>
- <item> NoSuchElementException </item>
- <item> NoSuchFieldError </item>
- <item> NoSuchFieldException </item>
- <item> NoSuchMethodError </item>
- <item> NoSuchMethodException </item>
- <item> NoSuchObjectException </item>
- <item> NoSuchPaddingException </item>
- <item> NoSuchProviderException </item>
- <item> NotActiveException </item>
- <item> Notation </item>
- <item> NotBoundException </item>
- <item> NotContextException </item>
- <item> NotEmpty </item>
- <item> NotEmptyHelper </item>
- <item> NotEmptyHolder </item>
- <item> NotFound </item>
- <item> NotFoundHelper </item>
- <item> NotFoundHolder </item>
- <item> NotFoundReason </item>
- <item> NotFoundReasonHelper </item>
- <item> NotFoundReasonHolder </item>
- <item> NotOwnerException </item>
- <item> NotSerializableException </item>
- <item> NotYetBoundException </item>
- <item> NotYetConnectedException </item>
- <item> NullCipher </item>
- <item> NullPointerException </item>
- <item> Number </item>
- <item> NumberFormat </item>
- <item> NumberFormat.Field </item>
- <item> NumberFormatException </item>
- <item> NumberFormatter </item>
- <item> NumberOfDocuments </item>
- <item> NumberOfInterveningJobs </item>
- <item> NumberUp </item>
- <item> NumberUpSupported </item>
- <item> NumericShaper </item>
- <item> NVList </item>
- <item> OBJ_ADAPTER </item>
- <item> Object </item>
- <item> Object </item>
- <item> OBJECT_NOT_EXIST </item>
- <item> ObjectAlreadyActive </item>
- <item> ObjectAlreadyActiveHelper </item>
- <item> ObjectChangeListener </item>
- <item> ObjectFactory </item>
- <item> ObjectFactoryBuilder </item>
- <item> ObjectHelper </item>
- <item> ObjectHolder </item>
- <item> ObjectIdHelper </item>
- <item> ObjectImpl </item>
- <item> ObjectImpl </item>
- <item> ObjectInput </item>
- <item> ObjectInputStream </item>
- <item> ObjectInputStream.GetField </item>
- <item> ObjectInputValidation </item>
- <item> ObjectNotActive </item>
- <item> ObjectNotActiveHelper </item>
- <item> ObjectOutput </item>
- <item> ObjectOutputStream </item>
- <item> ObjectOutputStream.PutField </item>
- <item> ObjectStreamClass </item>
- <item> ObjectStreamConstants </item>
- <item> ObjectStreamException </item>
- <item> ObjectStreamField </item>
- <item> ObjectView </item>
- <item> ObjID </item>
- <item> Observable </item>
- <item> Observer </item>
- <item> OctetSeqHelper </item>
- <item> OctetSeqHolder </item>
- <item> Oid </item>
- <item> OMGVMCID </item>
- <item> OpenType </item>
- <item> Operation </item>
- <item> OperationNotSupportedException </item>
- <item> Option </item>
- <item> OptionalDataException </item>
- <item> OptionPaneUI </item>
- <item> ORB </item>
- <item> ORB </item>
- <item> ORBInitializer </item>
- <item> ORBInitializerOperations </item>
- <item> ORBInitInfo </item>
- <item> ORBInitInfoOperations </item>
- <item> OrientationRequested </item>
- <item> OutOfMemoryError </item>
- <item> OutputDeviceAssigned </item>
- <item> OutputKeys </item>
- <item> OutputStream </item>
- <item> OutputStream </item>
- <item> OutputStream </item>
- <item> OutputStreamWriter </item>
- <item> OverlappingFileLockException </item>
- <item> OverlayLayout </item>
- <item> Owner </item>
- <item> Package </item>
- <item> PackedColorModel </item>
- <item> Pageable </item>
- <item> PageAttributes </item>
- <item> PageAttributes.ColorType </item>
- <item> PageAttributes.MediaType </item>
- <item> PageAttributes.OrientationRequestedType </item>
- <item> PageAttributes.OriginType </item>
- <item> PageAttributes.PrintQualityType </item>
- <item> PageFormat </item>
- <item> PageRanges </item>
- <item> PagesPerMinute </item>
- <item> PagesPerMinuteColor </item>
- <item> Paint </item>
- <item> PaintContext </item>
- <item> PaintEvent </item>
- <item> Panel </item>
- <item> PanelUI </item>
- <item> Paper </item>
- <item> ParagraphView </item>
- <item> ParagraphView </item>
- <item> Parameter </item>
- <item> ParameterBlock </item>
- <item> ParameterDescriptor </item>
- <item> ParameterMetaData </item>
- <item> ParameterMode </item>
- <item> ParameterModeHelper </item>
- <item> ParameterModeHolder </item>
- <item> ParseException </item>
- <item> ParsePosition </item>
- <item> Parser </item>
- <item> Parser </item>
- <item> ParserAdapter </item>
- <item> ParserConfigurationException </item>
- <item> ParserDelegator </item>
- <item> ParserFactory </item>
- <item> PartialResultException </item>
- <item> PasswordAuthentication </item>
- <item> PasswordCallback </item>
- <item> PasswordView </item>
- <item> Patch </item>
- <item> PathIterator </item>
- <item> Pattern </item>
- <item> PatternSyntaxException </item>
- <item> PBEKey </item>
- <item> PBEKeySpec </item>
- <item> PBEParameterSpec </item>
- <item> PDLOverrideSupported </item>
- <item> Permission </item>
- <item> Permission </item>
- <item> PermissionCollection </item>
- <item> Permissions </item>
- <item> PERSIST_STORE </item>
- <item> PersistenceDelegate </item>
- <item> PhantomReference </item>
- <item> Pipe </item>
- <item> Pipe.SinkChannel </item>
- <item> Pipe.SourceChannel </item>
- <item> PipedInputStream </item>
- <item> PipedOutputStream </item>
- <item> PipedReader </item>
- <item> PipedWriter </item>
- <item> PixelGrabber </item>
- <item> PixelInterleavedSampleModel </item>
- <item> PKCS8EncodedKeySpec </item>
- <item> PKIXBuilderParameters </item>
- <item> PKIXCertPathBuilderResult </item>
- <item> PKIXCertPathChecker </item>
- <item> PKIXCertPathValidatorResult </item>
- <item> PKIXParameters </item>
- <item> PlainDocument </item>
- <item> PlainView </item>
- <item> POA </item>
- <item> POAHelper </item>
- <item> POAManager </item>
- <item> POAManagerOperations </item>
- <item> POAOperations </item>
- <item> Point </item>
- <item> Point2D </item>
- <item> Point2D.Double </item>
- <item> Point2D.Float </item>
- <item> Policy </item>
- <item> Policy </item>
- <item> Policy </item>
- <item> PolicyError </item>
- <item> PolicyErrorCodeHelper </item>
- <item> PolicyErrorHelper </item>
- <item> PolicyErrorHolder </item>
- <item> PolicyFactory </item>
- <item> PolicyFactoryOperations </item>
- <item> PolicyHelper </item>
- <item> PolicyHolder </item>
- <item> PolicyListHelper </item>
- <item> PolicyListHolder </item>
- <item> PolicyNode </item>
- <item> PolicyOperations </item>
- <item> PolicyQualifierInfo </item>
- <item> PolicyTypeHelper </item>
- <item> Polygon </item>
- <item> PooledConnection </item>
- <item> Popup </item>
- <item> PopupFactory </item>
- <item> PopupMenu </item>
- <item> PopupMenuEvent </item>
- <item> PopupMenuListener </item>
- <item> PopupMenuUI </item>
- <item> Port </item>
- <item> Port.Info </item>
- <item> PortableRemoteObject </item>
- <item> PortableRemoteObjectDelegate </item>
- <item> PortUnreachableException </item>
- <item> Position </item>
- <item> Position.Bias </item>
- <item> PreferenceChangeEvent </item>
- <item> PreferenceChangeListener </item>
- <item> Preferences </item>
- <item> PreferencesFactory </item>
- <item> PreparedStatement </item>
- <item> PresentationDirection </item>
- <item> Principal </item>
- <item> Principal </item>
- <item> PrincipalHolder </item>
- <item> Printable </item>
- <item> PrinterAbortException </item>
- <item> PrinterException </item>
- <item> PrinterGraphics </item>
- <item> PrinterInfo </item>
- <item> PrinterIOException </item>
- <item> PrinterIsAcceptingJobs </item>
- <item> PrinterJob </item>
- <item> PrinterLocation </item>
- <item> PrinterMakeAndModel </item>
- <item> PrinterMessageFromOperator </item>
- <item> PrinterMoreInfo </item>
- <item> PrinterMoreInfoManufacturer </item>
- <item> PrinterName </item>
- <item> PrinterResolution </item>
- <item> PrinterState </item>
- <item> PrinterStateReason </item>
- <item> PrinterStateReasons </item>
- <item> PrinterURI </item>
- <item> PrintEvent </item>
- <item> PrintException </item>
- <item> PrintGraphics </item>
- <item> PrintJob </item>
- <item> PrintJobAdapter </item>
- <item> PrintJobAttribute </item>
- <item> PrintJobAttributeEvent </item>
- <item> PrintJobAttributeListener </item>
- <item> PrintJobAttributeSet </item>
- <item> PrintJobEvent </item>
- <item> PrintJobListener </item>
- <item> PrintQuality </item>
- <item> PrintRequestAttribute </item>
- <item> PrintRequestAttributeSet </item>
- <item> PrintService </item>
- <item> PrintServiceAttribute </item>
- <item> PrintServiceAttributeEvent </item>
- <item> PrintServiceAttributeListener </item>
- <item> PrintServiceAttributeSet </item>
- <item> PrintServiceLookup </item>
- <item> PrintStream </item>
- <item> PrintWriter </item>
- <item> PRIVATE_MEMBER </item>
- <item> PrivateCredentialPermission </item>
- <item> PrivateKey </item>
- <item> PrivilegedAction </item>
- <item> PrivilegedActionException </item>
- <item> PrivilegedExceptionAction </item>
- <item> Process </item>
- <item> ProcessingInstruction </item>
- <item> ProfileDataException </item>
- <item> ProfileIdHelper </item>
- <item> ProgressBarUI </item>
- <item> ProgressMonitor </item>
- <item> ProgressMonitorInputStream </item>
- <item> Properties </item>
- <item> PropertyChangeEvent </item>
- <item> PropertyChangeListener </item>
- <item> PropertyChangeListenerProxy </item>
- <item> PropertyChangeSupport </item>
- <item> PropertyDescriptor </item>
- <item> PropertyEditor </item>
- <item> PropertyEditorManager </item>
- <item> PropertyEditorSupport </item>
- <item> PropertyPermission </item>
- <item> PropertyResourceBundle </item>
- <item> PropertyVetoException </item>
- <item> ProtectionDomain </item>
- <item> ProtocolException </item>
- <item> Provider </item>
- <item> ProviderException </item>
- <item> Proxy </item>
- <item> PSSParameterSpec </item>
- <item> PUBLIC_MEMBER </item>
- <item> PublicKey </item>
- <item> PushbackInputStream </item>
- <item> PushbackReader </item>
- <item> QuadCurve2D </item>
- <item> QuadCurve2D.Double </item>
- <item> QuadCurve2D.Float </item>
- <item> QueuedJobCount </item>
- <item> Random </item>
- <item> RandomAccess </item>
- <item> RandomAccessFile </item>
- <item> Raster </item>
- <item> RasterFormatException </item>
- <item> RasterOp </item>
- <item> RC2ParameterSpec </item>
- <item> RC5ParameterSpec </item>
- <item> ReadableByteChannel </item>
- <item> Reader </item>
- <item> ReadOnlyBufferException </item>
- <item> Receiver </item>
- <item> Rectangle </item>
- <item> Rectangle2D </item>
- <item> Rectangle2D.Double </item>
- <item> Rectangle2D.Float </item>
- <item> RectangularShape </item>
- <item> Ref </item>
- <item> RefAddr </item>
- <item> Reference </item>
- <item> Reference </item>
- <item> Referenceable </item>
- <item> ReferenceQueue </item>
- <item> ReferenceUriSchemesSupported </item>
- <item> ReferralException </item>
- <item> ReflectPermission </item>
- <item> Refreshable </item>
- <item> RefreshFailedException </item>
- <item> RegisterableService </item>
- <item> Registry </item>
- <item> RegistryHandler </item>
- <item> RemarshalException </item>
- <item> Remote </item>
- <item> RemoteCall </item>
- <item> RemoteException </item>
- <item> RemoteObject </item>
- <item> RemoteRef </item>
- <item> RemoteServer </item>
- <item> RemoteStub </item>
- <item> RenderableImage </item>
- <item> RenderableImageOp </item>
- <item> RenderableImageProducer </item>
- <item> RenderContext </item>
- <item> RenderedImage </item>
- <item> RenderedImageFactory </item>
- <item> Renderer </item>
- <item> RenderingHints </item>
- <item> RenderingHints.Key </item>
- <item> RepaintManager </item>
- <item> ReplicateScaleFilter </item>
- <item> RepositoryIdHelper </item>
- <item> Request </item>
- <item> REQUEST_PROCESSING_POLICY_ID </item>
- <item> RequestInfo </item>
- <item> RequestInfoOperations </item>
- <item> RequestingUserName </item>
- <item> RequestProcessingPolicy </item>
- <item> RequestProcessingPolicyOperations </item>
- <item> RequestProcessingPolicyValue </item>
- <item> RescaleOp </item>
- <item> ResolutionSyntax </item>
- <item> Resolver </item>
- <item> ResolveResult </item>
- <item> ResourceBundle </item>
- <item> ResponseHandler </item>
- <item> Result </item>
- <item> ResultSet </item>
- <item> ResultSetMetaData </item>
- <item> ReverbType </item>
- <item> RGBImageFilter </item>
- <item> RMIClassLoader </item>
- <item> RMIClassLoaderSpi </item>
- <item> RMIClientSocketFactory </item>
- <item> RMIFailureHandler </item>
- <item> RMISecurityException </item>
- <item> RMISecurityManager </item>
- <item> RMIServerSocketFactory </item>
- <item> RMISocketFactory </item>
- <item> Robot </item>
- <item> RootPaneContainer </item>
- <item> RootPaneUI </item>
- <item> RoundRectangle2D </item>
- <item> RoundRectangle2D.Double </item>
- <item> RoundRectangle2D.Float </item>
- <item> RowMapper </item>
- <item> RowSet </item>
- <item> RowSetEvent </item>
- <item> RowSetInternal </item>
- <item> RowSetListener </item>
- <item> RowSetMetaData </item>
- <item> RowSetReader </item>
- <item> RowSetWriter </item>
- <item> RSAKey </item>
- <item> RSAKeyGenParameterSpec </item>
- <item> RSAMultiPrimePrivateCrtKey </item>
- <item> RSAMultiPrimePrivateCrtKeySpec </item>
- <item> RSAOtherPrimeInfo </item>
- <item> RSAPrivateCrtKey </item>
- <item> RSAPrivateCrtKeySpec </item>
- <item> RSAPrivateKey </item>
- <item> RSAPrivateKeySpec </item>
- <item> RSAPublicKey </item>
- <item> RSAPublicKeySpec </item>
- <item> RTFEditorKit </item>
- <item> RuleBasedCollator </item>
- <item> Runnable </item>
- <item> Runtime </item>
- <item> RunTime </item>
- <item> RuntimeException </item>
- <item> RunTimeOperations </item>
- <item> RuntimePermission </item>
- <item> SampleModel </item>
- <item> Savepoint </item>
- <item> SAXException </item>
- <item> SAXNotRecognizedException </item>
- <item> SAXNotSupportedException </item>
- <item> SAXParseException </item>
- <item> SAXParser </item>
- <item> SAXParserFactory </item>
- <item> SAXResult </item>
- <item> SAXSource </item>
- <item> SAXTransformerFactory </item>
- <item> ScatteringByteChannel </item>
- <item> SchemaViolationException </item>
- <item> Scrollable </item>
- <item> Scrollbar </item>
- <item> ScrollBarUI </item>
- <item> ScrollPane </item>
- <item> ScrollPaneAdjustable </item>
- <item> ScrollPaneConstants </item>
- <item> ScrollPaneLayout </item>
- <item> ScrollPaneLayout.UIResource </item>
- <item> ScrollPaneUI </item>
- <item> SealedObject </item>
- <item> SearchControls </item>
- <item> SearchResult </item>
- <item> SecretKey </item>
- <item> SecretKeyFactory </item>
- <item> SecretKeyFactorySpi </item>
- <item> SecretKeySpec </item>
- <item> SecureClassLoader </item>
- <item> SecureRandom </item>
- <item> SecureRandomSpi </item>
- <item> Security </item>
- <item> SecurityException </item>
- <item> SecurityManager </item>
- <item> SecurityPermission </item>
- <item> Segment </item>
- <item> SelectableChannel </item>
- <item> SelectionKey </item>
- <item> Selector </item>
- <item> SelectorProvider </item>
- <item> SeparatorUI </item>
- <item> Sequence </item>
- <item> SequenceInputStream </item>
- <item> Sequencer </item>
- <item> Sequencer.SyncMode </item>
- <item> Serializable </item>
- <item> SerializablePermission </item>
- <item> Servant </item>
- <item> SERVANT_RETENTION_POLICY_ID </item>
- <item> ServantActivator </item>
- <item> ServantActivatorHelper </item>
- <item> ServantActivatorOperations </item>
- <item> ServantActivatorPOA </item>
- <item> ServantAlreadyActive </item>
- <item> ServantAlreadyActiveHelper </item>
- <item> ServantLocator </item>
- <item> ServantLocatorHelper </item>
- <item> ServantLocatorOperations </item>
- <item> ServantLocatorPOA </item>
- <item> ServantManager </item>
- <item> ServantManagerOperations </item>
- <item> ServantNotActive </item>
- <item> ServantNotActiveHelper </item>
- <item> ServantObject </item>
- <item> ServantRetentionPolicy </item>
- <item> ServantRetentionPolicyOperations </item>
- <item> ServantRetentionPolicyValue </item>
- <item> ServerCloneException </item>
- <item> ServerError </item>
- <item> ServerException </item>
- <item> ServerNotActiveException </item>
- <item> ServerRef </item>
- <item> ServerRequest </item>
- <item> ServerRequestInfo </item>
- <item> ServerRequestInfoOperations </item>
- <item> ServerRequestInterceptor </item>
- <item> ServerRequestInterceptorOperations </item>
- <item> ServerRuntimeException </item>
- <item> ServerSocket </item>
- <item> ServerSocketChannel </item>
- <item> ServerSocketFactory </item>
- <item> ServiceContext </item>
- <item> ServiceContextHelper </item>
- <item> ServiceContextHolder </item>
- <item> ServiceContextListHelper </item>
- <item> ServiceContextListHolder </item>
- <item> ServiceDetail </item>
- <item> ServiceDetailHelper </item>
- <item> ServiceIdHelper </item>
- <item> ServiceInformation </item>
- <item> ServiceInformationHelper </item>
- <item> ServiceInformationHolder </item>
- <item> ServicePermission </item>
- <item> ServiceRegistry </item>
- <item> ServiceRegistry.Filter </item>
- <item> ServiceUI </item>
- <item> ServiceUIFactory </item>
- <item> ServiceUnavailableException </item>
- <item> Set </item>
- <item> SetOfIntegerSyntax </item>
- <item> SetOverrideType </item>
- <item> SetOverrideTypeHelper </item>
- <item> Severity </item>
- <item> Shape </item>
- <item> ShapeGraphicAttribute </item>
- <item> SheetCollate </item>
- <item> Short </item>
- <item> ShortBuffer </item>
- <item> ShortBufferException </item>
- <item> ShortHolder </item>
- <item> ShortLookupTable </item>
- <item> ShortMessage </item>
- <item> ShortSeqHelper </item>
- <item> ShortSeqHolder </item>
- <item> Sides </item>
- <item> Signature </item>
- <item> SignatureException </item>
- <item> SignatureSpi </item>
- <item> SignedObject </item>
- <item> Signer </item>
- <item> SimpleAttributeSet </item>
- <item> SimpleBeanInfo </item>
- <item> SimpleDateFormat </item>
- <item> SimpleDoc </item>
- <item> SimpleFormatter </item>
- <item> SimpleTimeZone </item>
- <item> SinglePixelPackedSampleModel </item>
- <item> SingleSelectionModel </item>
- <item> Size2DSyntax </item>
- <item> SizeLimitExceededException </item>
- <item> SizeRequirements </item>
- <item> SizeSequence </item>
- <item> Skeleton </item>
- <item> SkeletonMismatchException </item>
- <item> SkeletonNotFoundException </item>
- <item> SliderUI </item>
- <item> Socket </item>
- <item> SocketAddress </item>
- <item> SocketChannel </item>
- <item> SocketException </item>
- <item> SocketFactory </item>
- <item> SocketHandler </item>
- <item> SocketImpl </item>
- <item> SocketImplFactory </item>
- <item> SocketOptions </item>
- <item> SocketPermission </item>
- <item> SocketSecurityException </item>
- <item> SocketTimeoutException </item>
- <item> SoftBevelBorder </item>
- <item> SoftReference </item>
- <item> SortedMap </item>
- <item> SortedSet </item>
- <item> SortingFocusTraversalPolicy </item>
- <item> Soundbank </item>
- <item> SoundbankReader </item>
- <item> SoundbankResource </item>
- <item> Source </item>
- <item> SourceDataLine </item>
- <item> SourceLocator </item>
- <item> SpinnerDateModel </item>
- <item> SpinnerListModel </item>
- <item> SpinnerModel </item>
- <item> SpinnerNumberModel </item>
- <item> SpinnerUI </item>
- <item> SplitPaneUI </item>
- <item> Spring </item>
- <item> SpringLayout </item>
- <item> SpringLayout.Constraints </item>
- <item> SQLData </item>
- <item> SQLException </item>
- <item> SQLInput </item>
- <item> SQLOutput </item>
- <item> SQLPermission </item>
- <item> SQLWarning </item>
- <item> SSLContext </item>
- <item> SSLContextSpi </item>
- <item> SSLException </item>
- <item> SSLHandshakeException </item>
- <item> SSLKeyException </item>
- <item> SSLPeerUnverifiedException </item>
- <item> SSLPermission </item>
- <item> SSLProtocolException </item>
- <item> SSLServerSocket </item>
- <item> SSLServerSocketFactory </item>
- <item> SSLSession </item>
- <item> SSLSessionBindingEvent </item>
- <item> SSLSessionBindingListener </item>
- <item> SSLSessionContext </item>
- <item> SSLSocket </item>
- <item> SSLSocketFactory </item>
- <item> Stack </item>
- <item> StackOverflowError </item>
- <item> StackTraceElement </item>
- <item> StartTlsRequest </item>
- <item> StartTlsResponse </item>
- <item> State </item>
- <item> StateEdit </item>
- <item> StateEditable </item>
- <item> StateFactory </item>
- <item> Statement </item>
- <item> Statement </item>
- <item> Streamable </item>
- <item> StreamableValue </item>
- <item> StreamCorruptedException </item>
- <item> StreamHandler </item>
- <item> StreamPrintService </item>
- <item> StreamPrintServiceFactory </item>
- <item> StreamResult </item>
- <item> StreamSource </item>
- <item> StreamTokenizer </item>
- <item> StrictMath </item>
- <item> String </item>
- <item> StringBuffer </item>
- <item> StringBufferInputStream </item>
- <item> StringCharacterIterator </item>
- <item> StringContent </item>
- <item> StringHolder </item>
- <item> StringIndexOutOfBoundsException </item>
- <item> StringNameHelper </item>
- <item> StringReader </item>
- <item> StringRefAddr </item>
- <item> StringSelection </item>
- <item> StringSeqHelper </item>
- <item> StringSeqHolder </item>
- <item> StringTokenizer </item>
- <item> StringValueHelper </item>
- <item> StringWriter </item>
- <item> Stroke </item>
- <item> Struct </item>
- <item> StructMember </item>
- <item> StructMemberHelper </item>
- <item> Stub </item>
- <item> StubDelegate </item>
- <item> StubNotFoundException </item>
- <item> Style </item>
- <item> StyleConstants </item>
- <item> StyleConstants.CharacterConstants </item>
- <item> StyleConstants.ColorConstants </item>
- <item> StyleConstants.FontConstants </item>
- <item> StyleConstants.ParagraphConstants </item>
- <item> StyleContext </item>
- <item> StyledDocument </item>
- <item> StyledEditorKit </item>
- <item> StyledEditorKit.AlignmentAction </item>
- <item> StyledEditorKit.BoldAction </item>
- <item> StyledEditorKit.FontFamilyAction </item>
- <item> StyledEditorKit.FontSizeAction </item>
- <item> StyledEditorKit.ForegroundAction </item>
- <item> StyledEditorKit.ItalicAction </item>
- <item> StyledEditorKit.StyledTextAction </item>
- <item> StyledEditorKit.UnderlineAction </item>
- <item> StyleSheet </item>
- <item> StyleSheet.BoxPainter </item>
- <item> StyleSheet.ListPainter </item>
- <item> Subject </item>
- <item> SubjectDomainCombiner </item>
- <item> SUCCESSFUL </item>
- <item> SupportedValuesAttribute </item>
- <item> SwingConstants </item>
- <item> SwingPropertyChangeSupport </item>
- <item> SwingUtilities </item>
- <item> SYNC_WITH_TRANSPORT </item>
- <item> SyncFailedException </item>
- <item> SyncScopeHelper </item>
- <item> Synthesizer </item>
- <item> SysexMessage </item>
- <item> System </item>
- <item> SYSTEM_EXCEPTION </item>
- <item> SystemColor </item>
- <item> SystemException </item>
- <item> SystemFlavorMap </item>
- <item> TabableView </item>
- <item> TabbedPaneUI </item>
- <item> TabExpander </item>
- <item> TableCellEditor </item>
- <item> TableCellRenderer </item>
- <item> TableColumn </item>
- <item> TableColumnModel </item>
- <item> TableColumnModelEvent </item>
- <item> TableColumnModelListener </item>
- <item> TableHeaderUI </item>
- <item> TableModel </item>
- <item> TableModelEvent </item>
- <item> TableModelListener </item>
- <item> TableUI </item>
- <item> TableView </item>
- <item> TabSet </item>
- <item> TabStop </item>
- <item> TAG_ALTERNATE_IIOP_ADDRESS </item>
- <item> TAG_CODE_SETS </item>
- <item> TAG_INTERNET_IOP </item>
- <item> TAG_JAVA_CODEBASE </item>
- <item> TAG_MULTIPLE_COMPONENTS </item>
- <item> TAG_ORB_TYPE </item>
- <item> TAG_POLICIES </item>
- <item> TagElement </item>
- <item> TaggedComponent </item>
- <item> TaggedComponentHelper </item>
- <item> TaggedComponentHolder </item>
- <item> TaggedProfile </item>
- <item> TaggedProfileHelper </item>
- <item> TaggedProfileHolder </item>
- <item> TargetDataLine </item>
- <item> TCKind </item>
- <item> Templates </item>
- <item> TemplatesHandler </item>
- <item> Text </item>
- <item> TextAction </item>
- <item> TextArea </item>
- <item> TextAttribute </item>
- <item> TextComponent </item>
- <item> TextEvent </item>
- <item> TextField </item>
- <item> TextHitInfo </item>
- <item> TextInputCallback </item>
- <item> TextLayout </item>
- <item> TextLayout.CaretPolicy </item>
- <item> TextListener </item>
- <item> TextMeasurer </item>
- <item> TextOutputCallback </item>
- <item> TextSyntax </item>
- <item> TextUI </item>
- <item> TexturePaint </item>
- <item> Thread </item>
- <item> THREAD_POLICY_ID </item>
- <item> ThreadDeath </item>
- <item> ThreadGroup </item>
- <item> ThreadLocal </item>
- <item> ThreadPolicy </item>
- <item> ThreadPolicyOperations </item>
- <item> ThreadPolicyValue </item>
- <item> Throwable </item>
- <item> Tie </item>
- <item> TileObserver </item>
- <item> Time </item>
- <item> TimeLimitExceededException </item>
- <item> Timer </item>
- <item> Timer </item>
- <item> TimerTask </item>
- <item> Timestamp </item>
- <item> TimeZone </item>
- <item> TitledBorder </item>
- <item> ToolBarUI </item>
- <item> Toolkit </item>
- <item> ToolTipManager </item>
- <item> ToolTipUI </item>
- <item> TooManyListenersException </item>
- <item> Track </item>
- <item> TRANSACTION_REQUIRED </item>
- <item> TRANSACTION_ROLLEDBACK </item>
- <item> TransactionRequiredException </item>
- <item> TransactionRolledbackException </item>
- <item> TransactionService </item>
- <item> Transferable </item>
- <item> TransferHandler </item>
- <item> TransformAttribute </item>
- <item> Transformer </item>
- <item> TransformerConfigurationException </item>
- <item> TransformerException </item>
- <item> TransformerFactory </item>
- <item> TransformerFactoryConfigurationError </item>
- <item> TransformerHandler </item>
- <item> TRANSIENT </item>
- <item> Transmitter </item>
- <item> Transparency </item>
- <item> TRANSPORT_RETRY </item>
- <item> TreeCellEditor </item>
- <item> TreeCellRenderer </item>
- <item> TreeExpansionEvent </item>
- <item> TreeExpansionListener </item>
- <item> TreeMap </item>
- <item> TreeModel </item>
- <item> TreeModelEvent </item>
- <item> TreeModelListener </item>
- <item> TreeNode </item>
- <item> TreePath </item>
- <item> TreeSelectionEvent </item>
- <item> TreeSelectionListener </item>
- <item> TreeSelectionModel </item>
- <item> TreeSet </item>
- <item> TreeUI </item>
- <item> TreeWillExpandListener </item>
- <item> TrustAnchor </item>
- <item> TrustManager </item>
- <item> TrustManagerFactory </item>
- <item> TrustManagerFactorySpi </item>
- <item> TypeCode </item>
- <item> TypeCodeHolder </item>
- <item> TypeMismatch </item>
- <item> TypeMismatch </item>
- <item> TypeMismatch </item>
- <item> TypeMismatchHelper </item>
- <item> TypeMismatchHelper </item>
- <item> Types </item>
- <item> UID </item>
- <item> UIDefaults </item>
- <item> UIDefaults.ActiveValue </item>
- <item> UIDefaults.LazyInputMap </item>
- <item> UIDefaults.LazyValue </item>
- <item> UIDefaults.ProxyLazyValue </item>
- <item> UIManager </item>
- <item> UIManager.LookAndFeelInfo </item>
- <item> UIResource </item>
- <item> ULongLongSeqHelper </item>
- <item> ULongLongSeqHolder </item>
- <item> ULongSeqHelper </item>
- <item> ULongSeqHolder </item>
- <item> UndeclaredThrowableException </item>
- <item> UndoableEdit </item>
- <item> UndoableEditEvent </item>
- <item> UndoableEditListener </item>
- <item> UndoableEditSupport </item>
- <item> UndoManager </item>
- <item> UnexpectedException </item>
- <item> UnicastRemoteObject </item>
- <item> UnionMember </item>
- <item> UnionMemberHelper </item>
- <item> UNKNOWN </item>
- <item> UnknownEncoding </item>
- <item> UnknownEncodingHelper </item>
- <item> UnknownError </item>
- <item> UnknownException </item>
- <item> UnknownGroupException </item>
- <item> UnknownHostException </item>
- <item> UnknownHostException </item>
- <item> UnknownObjectException </item>
- <item> UnknownServiceException </item>
- <item> UnknownUserException </item>
- <item> UnknownUserExceptionHelper </item>
- <item> UnknownUserExceptionHolder </item>
- <item> UnmappableCharacterException </item>
- <item> UnmarshalException </item>
- <item> UnmodifiableSetException </item>
- <item> UnrecoverableKeyException </item>
- <item> Unreferenced </item>
- <item> UnresolvedAddressException </item>
- <item> UnresolvedPermission </item>
- <item> UnsatisfiedLinkError </item>
- <item> UnsolicitedNotification </item>
- <item> UnsolicitedNotificationEvent </item>
- <item> UnsolicitedNotificationListener </item>
- <item> UNSUPPORTED_POLICY </item>
- <item> UNSUPPORTED_POLICY_VALUE </item>
- <item> UnsupportedAddressTypeException </item>
- <item> UnsupportedAudioFileException </item>
- <item> UnsupportedCallbackException </item>
- <item> UnsupportedCharsetException </item>
- <item> UnsupportedClassVersionError </item>
- <item> UnsupportedEncodingException </item>
- <item> UnsupportedFlavorException </item>
- <item> UnsupportedLookAndFeelException </item>
- <item> UnsupportedOperationException </item>
- <item> URI </item>
- <item> URIException </item>
- <item> URIResolver </item>
- <item> URISyntax </item>
- <item> URISyntaxException </item>
- <item> URL </item>
- <item> URLClassLoader </item>
- <item> URLConnection </item>
- <item> URLDecoder </item>
- <item> URLEncoder </item>
- <item> URLStreamHandler </item>
- <item> URLStreamHandlerFactory </item>
- <item> URLStringHelper </item>
- <item> USER_EXCEPTION </item>
- <item> UserException </item>
- <item> UShortSeqHelper </item>
- <item> UShortSeqHolder </item>
- <item> UTFDataFormatException </item>
- <item> Util </item>
- <item> UtilDelegate </item>
- <item> Utilities </item>
- <item> ValueBase </item>
- <item> ValueBaseHelper </item>
- <item> ValueBaseHolder </item>
- <item> ValueFactory </item>
- <item> ValueHandler </item>
- <item> ValueMember </item>
- <item> ValueMemberHelper </item>
- <item> VariableHeightLayoutCache </item>
- <item> Vector </item>
- <item> VerifyError </item>
- <item> VersionSpecHelper </item>
- <item> VetoableChangeListener </item>
- <item> VetoableChangeListenerProxy </item>
- <item> VetoableChangeSupport </item>
- <item> View </item>
- <item> ViewFactory </item>
- <item> ViewportLayout </item>
- <item> ViewportUI </item>
- <item> VirtualMachineError </item>
- <item> Visibility </item>
- <item> VisibilityHelper </item>
- <item> VM_ABSTRACT </item>
- <item> VM_CUSTOM </item>
- <item> VM_NONE </item>
- <item> VM_TRUNCATABLE </item>
- <item> VMID </item>
- <item> VoiceStatus </item>
- <item> Void </item>
- <item> VolatileImage </item>
- <item> WCharSeqHelper </item>
- <item> WCharSeqHolder </item>
- <item> WeakHashMap </item>
- <item> WeakReference </item>
- <item> Window </item>
- <item> WindowAdapter </item>
- <item> WindowConstants </item>
- <item> WindowEvent </item>
- <item> WindowFocusListener </item>
- <item> WindowListener </item>
- <item> WindowStateListener </item>
- <item> WrappedPlainView </item>
- <item> WritableByteChannel </item>
- <item> WritableRaster </item>
- <item> WritableRenderedImage </item>
- <item> WriteAbortedException </item>
- <item> Writer </item>
- <item> WrongAdapter </item>
- <item> WrongAdapterHelper </item>
- <item> WrongPolicy </item>
- <item> WrongPolicyHelper </item>
- <item> WrongTransaction </item>
- <item> WrongTransactionHelper </item>
- <item> WrongTransactionHolder </item>
- <item> WStringSeqHelper </item>
- <item> WStringSeqHolder </item>
- <item> WStringValueHelper </item>
- <item> X500Principal </item>
- <item> X500PrivateCredential </item>
- <item> X509Certificate </item>
- <item> X509Certificate </item>
- <item> X509CertSelector </item>
- <item> X509CRL </item>
- <item> X509CRLEntry </item>
- <item> X509CRLSelector </item>
- <item> X509EncodedKeySpec </item>
- <item> X509Extension </item>
- <item> X509KeyManager </item>
- <item> X509TrustManager </item>
- <item> XAConnection </item>
- <item> XADataSource </item>
- <item> XAException </item>
- <item> XAResource </item>
- <item> Xid </item>
- <item> XMLDecoder </item>
- <item> XMLEncoder </item>
- <item> XMLFilter </item>
- <item> XMLFilterImpl </item>
- <item> XMLFormatter </item>
- <item> XMLReader </item>
- <item> XMLReaderAdapter </item>
- <item> XMLReaderFactory </item>
- <item> ZipEntry </item>
- <item> ZipException </item>
- <item> ZipFile </item>
- <item> ZipInputStream </item>
- <item> ZipOutputStream </item>
- <item> ZoneView </item>
- <item> _BindingIteratorImplBase </item>
- <item> _BindingIteratorStub </item>
- <item> _DynAnyFactoryStub </item>
- <item> _DynAnyStub </item>
- <item> _DynArrayStub </item>
- <item> _DynEnumStub </item>
- <item> _DynFixedStub </item>
- <item> _DynSequenceStub </item>
- <item> _DynStructStub </item>
- <item> _DynUnionStub </item>
- <item> _DynValueStub </item>
- <item> _IDLTypeStub </item>
- <item> _NamingContextExtStub </item>
- <item> _NamingContextImplBase </item>
- <item> _NamingContextStub </item>
- <item> _PolicyStub </item>
- <item> _Remote_Stub </item>
- <item> _ServantActivatorStub </item>
- <item> _ServantLocatorStub </item>
- </list>
- <list name="keywords">
- <item> abstract </item>
- <item> break </item>
- <item> case </item>
- <item> catch </item>
- <item> class </item>
- <item> continue </item>
- <item> default </item>
- <item> do </item>
- <item> else </item>
- <item> extends </item>
- <item> false </item>
- <item> finally </item>
- <item> for </item>
- <item> goto </item>
- <item> if </item>
- <item> implements </item>
- <item> instanceof </item>
- <item> interface </item>
- <item> native </item>
- <item> new </item>
- <item> null </item>
- <item> private </item>
- <item> protected </item>
- <item> public </item>
- <item> return </item>
- <item> super </item>
- <item> strictfp </item>
- <item> switch </item>
- <item> synchronized </item>
- <item> this </item>
- <item> throws </item>
- <item> throw </item>
- <item> transient </item>
- <item> true </item>
- <item> try </item>
- <item> volatile </item>
- <item> while </item>
- </list>
- <list name="types">
- <item> boolean </item>
- <item> byte </item>
- <item> char </item>
- <item> const </item>
- <item> double </item>
- <item> final </item>
- <item> float </item>
- <item> int </item>
- <item> long </item>
- <item> short </item>
- <item> static </item>
- <item> void </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <keyword attribute="Java14" context="#stay" String="java14"/>
- <Float attribute="Float" context="#stay">
- <AnyChar String="fF" attribute="Float" context="#stay"/>
- </Float>
- <HlCOct attribute="Octal" context="#stay"/>
- <HlCHex attribute="Hex" context="#stay"/>
- <Int attribute="Decimal" context="#stay">
- <StringDetect attribute="Decimal" context="#stay" String="ULL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LUL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LLU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="UL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="U" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="L" insensitive="TRUE"/>
- </Int>
- <HlCChar attribute="Char" context="#stay"/>
- <RegExpr attribute="Decimal" context="#stay" String="//\s*BEGIN.*$" beginRegion="Region1"/>
- <RegExpr attribute="Decimal" context="#stay" String="//\s*END.*$" endRegion="Region1"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*" beginRegion="Comment"/>
- <DetectChar attribute="Symbol" context="#stay" char="{" beginRegion="Brace1"/>
- <DetectChar attribute="Symbol" context="#stay" char="}" endRegion="Brace1"/>
- <RegExpr attribute="Keyword" context="Imports" String="^\s*(package|import)" />
- <RegExpr attribute="Function" context="#stay" String="\b[_\w][_\w\d]*(?=[\s]*[(])" />
- <RegExpr attribute="Symbol" context="Member" String="[.]{1,1}" />
- <AnyChar attribute="Symbol" context="#stay" String=":!%&amp;()+,-/.*&lt;=&gt;?[]|~^&#59;"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Member">
- <RegExpr attribute="Function" context="#pop" String="\b[_\w][_\w\d]*(?=[\s]*)" />
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Imports">
- <RegExpr attribute="Imports" context="#pop" String="\s*.*$" />
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Commentar 1"/>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar 2">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Function" defStyleNum="dsKeyword" color="#000080" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Imports" defStyleNum="dsKeyword" color="#808000" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Java14" defStyleNum="dsNormal" color="#0095FF" selColor="#FFFFFF" bold="1" italic="0"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//"/>
- <comment name="multiLine" start="/*" end="*/"/>
- </comments>
- <keywords casesensitive="1"/>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!-- Author: Anders Lund <anders@alweb.dk> //-->
-<!-- Minor changes: Joseph Wenninger <jowenn@kde.org> //-->
-<!-- Full JavaScript 1.0 support by Whitehawk Stormchaser //-->
-<language name="JavaScript" version="1.07" kateversion="2.1" section="Scripts"
- extensions="*.js" mimetype="text/x-javascript"
- author="Anders Lund (anders@alweb.dk), Joseph Wenninger (jowenn@kde.org), Whitehawk Stormchaser" license="">
- <highlighting>
- <list name="keywords">
- <item> if </item>
- <item> else </item>
- <item> for </item>
- <item> in </item>
- <item> while </item>
- <item> do </item>
- <item> continue </item>
- <item> break </item>
- <item> with </item>
- <item> try </item>
- <item> catch </item>
- <item> switch </item>
- <item> case </item>
- <item> new </item>
- <item> var </item>
- <item> function </item>
- <item> return </item>
- <item> delete </item>
- <item> true </item>
- <item> false </item>
- <item> void </item>
- <item> throw </item>
- <item> typeof </item>
- <item> const </item>
- <item> default </item>
- </list>
- <list name="functions">
- <item> escape </item>
- <item> isFinite </item>
- <item> isNaN </item>
- <item> Number </item>
- <item> parseFloat </item>
- <item> parseInt </item>
- <item> reload </item>
- <item> taint </item>
- <item> unescape </item>
- <item> untaint </item>
- <item> write </item>
- </list>
- <list name="objects">
- <item>Anchor</item>
- <item>Applet</item>
- <item>Area</item>
- <item>Array</item>
- <item>Boolean</item>
- <item>Button</item>
- <item>Checkbox</item>
- <item>Date</item>
- <item>document</item>
- <item>window</item>
- <item>Image</item>
- <item>FileUpload</item>
- <item>Form</item>
- <item>Frame</item>
- <item>Function</item>
- <item>Hidden</item>
- <item>Link</item>
- <item>MimeType</item>
- <item>Math</item>
- <item>Max</item>
- <item>Min</item>
- <item>Layer</item>
- <item>navigator</item>
- <item>Object</item>
- <item>Password</item>
- <item>Plugin</item>
- <item>Radio</item>
- <item>RegExp</item>
- <item>Reset</item>
- <item>Screen</item>
- <item>Select</item>
- <item>String</item>
- <item>Text</item>
- <item>Textarea</item>
- <item>this</item>
- <item>Window</item>
- </list>
- <list name="math">
- <item> abs </item>
- <item> acos </item>
- <item> asin </item>
- <item> atan </item>
- <item> atan2 </item>
- <item> ceil </item>
- <item> cos </item>
- <item> ctg </item>
- <item> E </item>
- <item> exp </item>
- <item> floor </item>
- <item> LN2 </item>
- <item> LN10 </item>
- <item> log </item>
- <item> LOG2E </item>
- <item> LOG10E </item>
- <item> PI </item>
- <item> pow </item>
- <item> round </item>
- <item> sin </item>
- <item> sqrt </item>
- <item> SQRT1_2 </item>
- <item> SQRT2 </item>
- <item> tan </item>
- </list>
- <list name="events">
- <item>onAbort</item>
- <item>onBlur</item>
- <item>onChange</item>
- <item>onClick</item>
- <item>onError</item>
- <item>onFocus</item>
- <item>onLoad</item>
- <item>onMouseOut</item>
- <item>onMouseOver</item>
- <item>onReset</item>
- <item>onSelect</item>
- <item>onSubmit</item>
- <item>onUnload</item>
- </list>
- <list name="methods">
- <item>above</item>
- <item>action</item>
- <item>alinkColor</item>
- <item>alert</item>
- <item>anchor</item>
- <item>anchors</item>
- <item>appCodeName</item>
- <item>applets</item>
- <item>apply</item>
- <item>appName</item>
- <item>appVersion</item>
- <item>argument</item>
- <item>arguments</item>
- <item>arity</item>
- <item>availHeight</item>
- <item>availWidth</item>
- <item>back</item>
- <item>background</item>
- <item>below</item>
- <item>bgColor</item>
- <item>border</item>
- <item>big</item>
- <item>blink</item>
- <item>blur</item>
- <item>bold</item>
- <item>border</item>
- <item>call</item>
- <item>caller</item>
- <item>charAt</item>
- <item>charCodeAt</item>
- <item>checked</item>
- <item>clearInterval</item>
- <item>clearTimeout</item>
- <item>click</item>
- <item>clip</item>
- <item>close</item>
- <item>closed</item>
- <item>colorDepth</item>
- <item>complete</item>
- <item>compile</item>
- <item>constructor</item>
- <item>confirm</item>
- <item>cookie</item>
- <item>current</item>
- <item>cursor</item>
- <item>data</item>
- <item>defaultChecked</item>
- <item>defaultSelected</item>
- <item>defaultStatus</item>
- <item>defaultValue</item>
- <item>description</item>
- <item>disableExternalCapture</item>
- <item>domain</item>
- <item>elements</item>
- <item>embeds</item>
- <item>enabledPlugin</item>
- <item>enableExternalCapture</item>
- <item>encoding</item>
- <item>eval</item>
- <item>exec</item>
- <item>fgColor</item>
- <item>filename</item>
- <item>find</item>
- <item>fixed</item>
- <item>focus</item>
- <item>fontcolor</item>
- <item>fontsize</item>
- <item>form</item>
- <item>forms</item>
- <item>formName</item>
- <item>forward</item>
- <item>frames</item>
- <item>fromCharCode</item>
- <item>getDate</item>
- <item>getDay</item>
- <item>getHours</item>
- <item>getMiliseconds</item>
- <item>getMinutes</item>
- <item>getMonth</item>
- <item>getSeconds</item>
- <item>getSelection</item>
- <item>getTime</item>
- <item>getTimezoneOffset</item>
- <item>getUTCDate</item>
- <item>getUTCDay</item>
- <item>getUTCFullYear</item>
- <item>getUTCHours</item>
- <item>getUTCMilliseconds</item>
- <item>getUTCMinutes</item>
- <item>getUTCMonth</item>
- <item>getUTCSeconds</item>
- <item>getYear</item>
- <item>global</item>
- <item>go</item>
- <item>hash</item>
- <item>height</item>
- <item>history</item>
- <item>home</item>
- <item>host</item>
- <item>hostname</item>
- <item>href</item>
- <item>hspace</item>
- <item>ignoreCase</item>
- <item>images</item>
- <item>index</item>
- <item>indexOf</item>
- <item>innerHeight</item>
- <item>innerWidth</item>
- <item>input</item>
- <item>italics</item>
- <item>javaEnabled</item>
- <item>join</item>
- <item>language</item>
- <item>lastIndex</item>
- <item>lastIndexOf</item>
- <item>lastModified</item>
- <item>lastParen</item>
- <item>layers</item>
- <item>layerX</item>
- <item>layerY</item>
- <item>left</item>
- <item>leftContext</item>
- <item>length</item>
- <item>link</item>
- <item>linkColor</item>
- <item>links</item>
- <item>location</item>
- <item>locationbar</item>
- <item>load</item>
- <item>lowsrc</item>
- <item>match</item>
- <item>MAX_VALUE</item>
- <item>menubar</item>
- <item>method</item>
- <item>mimeTypes</item>
- <item>MIN_VALUE</item>
- <item>modifiers</item>
- <item>moveAbove</item>
- <item>moveBelow</item>
- <item>moveBy</item>
- <item>moveTo</item>
- <item>moveToAbsolute</item>
- <item>multiline</item>
- <item>name</item>
- <item>NaN</item>
- <item>NEGATIVE_INFINITY</item>
- <item>negative_infinity</item>
- <item>next</item>
- <item>open</item>
- <item>opener</item>
- <item>options</item>
- <item>outerHeight</item>
- <item>outerWidth</item>
- <item>pageX</item>
- <item>pageY</item>
- <item>pageXoffset</item>
- <item>pageYoffset</item>
- <item>parent</item>
- <item>parse</item>
- <item>pathname</item>
- <item>personalbar</item>
- <item>pixelDepth</item>
- <item>platform</item>
- <item>plugins</item>
- <item>pop</item>
- <item>port</item>
- <item>POSITIVE_INFINITY</item>
- <item>positive_infinity</item>
- <item>preference</item>
- <item>previous</item>
- <item>print</item>
- <item>prompt</item>
- <item>protocol</item>
- <item>prototype</item>
- <item>push</item>
- <item>referrer</item>
- <item>refresh</item>
- <item>releaseEvents</item>
- <item>reload</item>
- <item>replace</item>
- <item>reset</item>
- <item>resizeBy</item>
- <item>resizeTo</item>
- <item>reverse</item>
- <item>rightContext</item>
- <item>screenX</item>
- <item>screenY</item>
- <item>scroll</item>
- <item>scrollbar</item>
- <item>scrollBy</item>
- <item>scrollTo</item>
- <item>search</item>
- <item>select</item>
- <item>selected</item>
- <item>selectedIndex</item>
- <item>self</item>
- <item>setDate</item>
- <item>setHours</item>
- <item>setMinutes</item>
- <item>setMonth</item>
- <item>setSeconds</item>
- <item>setTime</item>
- <item>setTimeout</item>
- <item>setUTCDate</item>
- <item>setUTCDay</item>
- <item>setUTCFullYear</item>
- <item>setUTCHours</item>
- <item>setUTCMilliseconds</item>
- <item>setUTCMinutes</item>
- <item>setUTCMonth</item>
- <item>setUTCSeconds</item>
- <item>setYear</item>
- <item>shift</item>
- <item>siblingAbove</item>
- <item>siblingBelow</item>
- <item>small</item>
- <item>sort</item>
- <item>source</item>
- <item>splice</item>
- <item>split</item>
- <item>src</item>
- <item>status</item>
- <item>statusbar</item>
- <item>strike</item>
- <item>sub</item>
- <item>submit</item>
- <item>substr</item>
- <item>substring</item>
- <item>suffixes</item>
- <item>sup</item>
- <item>taintEnabled</item>
- <item>target</item>
- <item>test</item>
- <item>text</item>
- <item>title</item>
- <item>toGMTString</item>
- <item>toLocaleString</item>
- <item>toLowerCase</item>
- <item>toolbar</item>
- <item>toSource</item>
- <item>toString</item>
- <item>top</item>
- <item>toUpperCase</item>
- <item>toUTCString</item>
- <item>type</item>
- <item>URL</item>
- <item>unshift</item>
- <item>unwatch</item>
- <item>userAgent</item>
- <item>UTC</item>
- <item>value</item>
- <item>valueOf</item>
- <item>visibility</item>
- <item>vlinkColor</item>
- <item>vspace</item>
- <item>width</item>
- <item>watch</item>
- <item>which</item>
- <item>width</item>
- <item>write</item>
- <item>writeln</item>
- <item>x</item>
- <item>y</item>
- <item>zIndex</item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <RegExpr attribute="Decimal" context="#stay" String="//\s*BEGIN.*$" beginRegion="Region1"/>
- <RegExpr attribute="Decimal" context="#stay" String="//\s*END.*$" endRegion="Region1"/>
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Function" context="#stay" String="functions" />
- <keyword attribute="Objects" context="#stay" String="objects" />
- <keyword attribute="Math" context="#stay" String="math" />
- <keyword attribute="Events" context="#stay" String="events" />
- <keyword attribute="Data Type" context="#stay" String="methods" />
- <Float attribute="Float" context="#stay" />
- <Int attribute="Decimal" context="#stay" />
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <DetectChar attribute="String" context="String 1" char="'"/>
- <Detect2Chars attribute="Comment" context="Comment" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Multi/inline Comment" char="/" char1="*" beginRegion="Comment"/>
- <RegExpr attribute="Normal Text" context="(Internal regex catch)" String="\s*[=?:]\s*" />
- <RegExpr attribute="Normal Text" context="(Internal regex catch)" String="\(\s*" />
- <DetectChar attribute="Symbol" context="#stay" char="{" beginRegion="Brace1" />
- <DetectChar attribute="Symbol" context="#stay" char="}" endRegion="Brace1" />
- <AnyChar attribute="Symbol" context="#stay" String=":!%&amp;()+,-/.*&lt;=&gt;?[]|~^&#59;"/>
- </context>
-
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="String Char" lineEndContext="#pop" name="String 1">
- <LineContinue attribute="String" context="#stay"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <DetectChar attribute="String Char" context="#pop" char="'"/>
- </context>
-
- <context attribute="Comment" lineEndContext="#pop" name="Comment">
- <RegExpr attribute="Decimal" context="#stay" String="(FIXME|TODO)" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Multi/inline Comment">
- <RegExpr attribute="Decimal" context="#stay" String="(FIXME|TODO)" />
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- </context>
-
- <context attribute="Regular Expression" lineEndContext="#stay" name="Regular Expression">
- <RegExpr attribute="Regular Expression" context="#pop#pop#pop" String="/[ig]{0,2}" />
- <RegExpr attribute="Pattern Internal Operator" context="#stay" String="\{[\d, ]+\}" />
- <RegExpr attribute="Pattern Internal Operator" context="#stay" String="\\[bB]" />
- <RegExpr attribute="Pattern Character Class" context="#stay" String="\\[nrtvfDdSsWw]" />
- <DetectChar attribute="Pattern Character Class" context="(charclass caret first check)" char="[" />
- <RegExpr attribute="Pattern Internal Operator" context="#stay" String="\\." />
- <RegExpr attribute="Pattern Internal Operator" context="#stay" String="\$(?=/)" />
- <AnyChar attribute="Pattern Internal Operator" context="#stay" String="?+*()|" />
- </context>
- <context attribute="Normal Text" lineEndContext="#stay" name="(Internal regex catch)" fallthrough="true" fallthroughContext="#pop">
- <RegExpr attribute="Normal Text" context="#stay" String="\s*" />
- <RegExpr attribute="Regular Expression" context="#pop" String="//(?=;)" />
- <Detect2Chars attribute="Comment" context="Comment" char="/" char1="/" />
- <Detect2Chars attribute="Comment" context="Multi/inline Comment" char="/" char1="*" />
- <DetectChar attribute="Regular Expression" context="(regex caret first check)" char="/" />
- </context>
- <context attribute="Pattern Character Class" lineEndContext="#stay" name="Regular Expression Character Class">
- <RegExpr attribute="Pattern Character Class" context="#stay" String="\\[\[\]]" />
- <DetectChar attribute="Pattern Character Class" context="#pop#pop" char="]" />
- </context>
- <context attribute="Pattern Internal Operator" lineEndContext="#pop" name="(regex caret first check)" fallthrough="true" fallthroughContext="Regular Expression">
- <DetectChar attribute="Pattern Internal Operator" context="Regular Expression" char="^" />
- </context>
- <context attribute="Pattern Internal Operator" lineEndContext="#pop" name="(charclass caret first check)" fallthrough="true" fallthroughContext="Regular Expression Character Class">
- <DetectChar attribute="Pattern Internal Operator" context="Regular Expression Character Class" char="^" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Function" defStyleNum="dsKeyword" color="#0000FF" selColor="#00ffff" bold="0" italic="0"/>
- <itemData name="Objects" defStyleNum="dsKeyword" color="#008000" selColor="#00ffff" bold="0" italic="0"/>
- <itemData name="Math" defStyleNum="dsKeyword" color="#DBA716" selColor="#00ffff" bold="0" italic="0"/>
- <itemData name="Events" defStyleNum="dsKeyword" color="#F766D5" selColor="#00ffff" bold="0" italic="0"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Regular Expression" defStyleNum="dsOthers" />
- <itemData name="Pattern Internal Operator" defStyleNum="dsFloat" />
- <itemData name="Pattern Character Class" defStyleNum="dsBaseN" />
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="KBasic" version="1.02" kateversion="2.1" section="Sources" extensions="*.kbasic" mimetype="text/x-kbasic-src">
- <highlighting>
- <list name="keywords">
- <item> For </item>
- <item> Next</item>
- <item> Do </item>
- <item> Loop </item>
- <item> While </item>
- <item> Wend </item>
- <item> Until </item>
- <item> If </item>
- <item> Else </item>
- <item> End </item>
- <item> Function </item>
- <item> Goto </item>
- <item> Sub </item>
- <item> Implements </item>
- <item> In </item>
- <item> Sub </item>
- <item> Private </item>
- <item> Public </item>
- <item> Global </item>
- <item> As </item>
- <item> Dim </item>
- <item> Set </item>
- <item> Let </item>
- <item> Get </item>
- <item> To </item>
- <item> Property </item>
- <item> True </item>
- <item> False </item>
- <item> Or </item>
- <item> Not </item>
- <item> Xor </item>
- <item> And </item>
- <item> Then </item>
- <item> Exit </item>
- <item> Put </item>
- <item> Open </item>
- <item> Close </item>
- <item> Seek </item>
- <item> Print </item>
- <item> Input</item>
- <item> Output </item>
- <item> Repeat </item>
- <item> Load </item>
- <item> Unload </item>
- <item> Declare </item>
- <item> Option </item>
- <item> Explicit </item>
- </list>
- <list name="types">
- <item>Integer </item>
- <item>Long </item>
- <item>Byte </item>
- <item>Boolean </item>
- <item>Variant </item>
- <item>Single </item>
- <item>Double </item>
- <item>Currency </item>
- <item>String </item>
- <item>Object </item>
- <item>Control </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Identifier" context="#stay" String="types"/>
- <Float attribute="String" context="#stay"/>
- <Int attribute="Types" context="#stay"/>
- <DetectChar attribute="String" context="String" char="quot;"/>
- <DetectChar attribute="Comment" context="Comment" char="'"/>
- </context>
- <context name="Comment" attribute="Comment" lineEndContext="#pop"/>
- <context name="String" attribute="String" lineEndContext="#pop">
- <DetectChar attribute="String" context="#pop" char="'"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Identifier" defStyleNum="dsOthers"/>
- <itemData name="Types" defStyleNum="dsDataType"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="LaTeX" version="1.06" kateversion="2.1" section="Markup" extensions="*.tex;*.TEX;*.bib;*.BIB;*.ltx;*.LTX;*.sty;*.STY;*.cls;*.CLS" mimetype="text/x-tex" casesensitive="1">
- <highlighting>
- <list name="keywords">
- <item>mu</item>
- <item>multline</item>
- <item>nu</item>
- <item>psi</item>
- <item>phi</item>
- <item>varphi</item>
- <item>pi</item>
- <item>epsilon</item>
- <item>sigma</item>
- <item>eta</item>
- <item>left</item>
- <item>right</item>
- <item>partial</item>
- <item>ldots</item>
- <item>abovedisplayskip</item>
- <item>abovedisplayshortskip</item>
- <item>abstract</item>
- <item>acute</item>
- <item>addcontentsline</item>
- <item>address</item>
- <item>addtocontents</item>
- <item>addtocounter</item>
- <item>addtolength</item>
- <item>addvspace</item>
- <item>Alph</item>
- <item>alph</item>
- <item>alpha</item>
- <item>and</item>
- <item>appendix</item>
- <item>arabic</item>
- <item>array</item>
- <item>arraycolsep</item>
- <item>arrayrulewidth</item>
- <item>arraystretch</item>
- <item>author</item>
- <item>bar</item>
- <item>baselineskip</item>
- <item>baselinestretch</item>
- <item>begin</item>
- <item>belowdisplayskip</item>
- <item>belowdisplayshortskip</item>
- <item>bf</item>
- <item>bibitem</item>
- <item>bibliography</item>
- <item>bibliographystyle</item>
- <item>bigskip</item>
- <item>bigskipamount</item>
- <item>boldmath</item>
- <item>bottomfraction</item>
- <item>bottomnumber</item>
- <item>breve</item>
- <item>cal</item>
- <item>caption</item>
- <item>cc</item>
- <item>cdot</item>
- <item>center</item>
- <item>centering</item>
- <item>centerline</item>
- <item>chapter</item>
- <item>check</item>
- <item>circle</item>
- <item>cite</item>
- <item>cleardoublepage</item>
- <item>clearpage</item>
- <item>cline</item>
- <item>closing</item>
- <item>columnsep</item>
- <item>columnseprule</item>
- <item>dashbox</item>
- <item>date</item>
- <item>dblfloatpagefraction</item>
- <item>dblfloatsep</item>
- <item>dbltextfloatsep</item>
- <item>dbltopfraction</item>
- <item>dbltopnumber</item>
- <item>ddot</item>
- <item>description</item>
- <item>discretionary</item>
- <item>displaymath</item>
- <item>displaystyle</item>
- <item>document</item>
- <item>documentclass</item>
- <item>documentstyle</item>
- <item>dot</item>
- <item>dotfill</item>
- <item>doublerulesep</item>
- <item>em</item>
- <item>emph</item>
- <item>encl</item>
- <item>end</item>
- <item>enumerate</item>
- <item>eqnarray</item>
- <item>equation</item>
- <item>evensidemargin</item>
- <item>extracolsep</item>
- <item>fbox</item>
- <item>fboxrule</item>
- <item>fboxsep</item>
- <item>figure</item>
- <item>fill</item>
- <item>floatpagefraction</item>
- <item>floatsep</item>
- <item>flushbottom</item>
- <item>flushleft</item>
- <item>flushright</item>
- <item>fnsymbol</item>
- <item>footheight</item>
- <item>footnote</item>
- <item>footnotemark</item>
- <item>footnotesep</item>
- <item>footnotesize</item>
- <item>footnotetext</item>
- <item>footskip</item>
- <item>frac</item>
- <item>frame</item>
- <item>framebox</item>
- <item>frenchspacing</item>
- <item>fussy</item>
- <item>fussypar</item>
- <item>grave</item>
- <item>hat</item>
- <item>headheight</item>
- <item>headsep</item>
- <item>hfill</item>
- <item>hline</item>
- <item>hoffset</item>
- <item>hrulefill</item>
- <item>hspace</item>
- <item>Huge</item>
- <item>huge</item>
- <item>imath</item>
- <item>include</item>
- <item>includeonly</item>
- <item>indent</item>
- <item>input</item>
- <item>intextsep</item>
- <item>int</item>
- <item>it</item>
- <item>item</item>
- <item>itemize</item>
- <item>itemsep</item>
- <item>jmath</item>
- <item>jot</item>
- <item>kill</item>
- <item>label</item>
- <item>LARGE</item>
- <item>Large</item>
- <item>large</item>
- <item>LaTeX</item>
- <item>LaTeXe</item>
- <item>letter</item>
- <item>line</item>
- <item>linebreak</item>
- <item>linethickness</item>
- <item>listoffigures</item>
- <item>listoftables</item>
- <item>makebox</item>
- <item>maketitle</item>
- <item>marginpar</item>
- <item>marginparpush</item>
- <item>marginparsep</item>
- <item>marginparwidth</item>
- <item>markboth</item>
- <item>markright</item>
- <item>math</item>
- <item>mathindent</item>
- <item>mbox</item>
- <item>medskip</item>
- <item>medskipamount</item>
- <item>minipage</item>
- <item>multicolumn</item>
- <item>multiput</item>
- <item>name</item>
- <item>newcommand</item>
- <item>newcounter</item>
- <item>newenvironment</item>
- <item>newfont</item>
- <item>newlength</item>
- <item>newline</item>
- <item>newpage</item>
- <item>newsavebox</item>
- <item>newtheorem</item>
- <item>noindent</item>
- <item>nolinebreak</item>
- <item>nonfrenchspacing</item>
- <item>nonumber</item>
- <item>nopagebreak</item>
- <item>normalmarginpar</item>
- <item>normalsize</item>
- <item>numberline</item>
- <item>oddsidemargin</item>
- <item>onecolumn</item>
- <item>opening</item>
- <item>oval</item>
- <item>overbrace</item>
- <item>overline</item>
- <item>pagebreak</item>
- <item>pagenumbering</item>
- <item>pageref</item>
- <item>pagestyle</item>
- <item>par</item>
- <item>paragraph</item>
- <item>parbox</item>
- <item>parindent</item>
- <item>parsep</item>
- <item>parskip</item>
- <item>part</item>
- <item>picture</item>
- <item>poptabs</item>
- <item>protect</item>
- <item>ps</item>
- <item>pushtabs</item>
- <item>put</item>
- <item>quotation</item>
- <item>quote</item>
- <item>raggedbottom</item>
- <item>raggedleft</item>
- <item>raggedright</item>
- <item>raisebox</item>
- <item>ref</item>
- <item>refstepcounter</item>
- <item>renewcommand</item>
- <item>renewenvironment</item>
- <item>reversemarginpar</item>
- <item>rm</item>
- <item>Roman</item>
- <item>roman</item>
- <item>rule</item>
- <item>samepage</item>
- <item>savebox</item>
- <item>sbox</item>
- <item>sc</item>
- <item>scriptscriptstyle</item>
- <item>scriptsize</item>
- <item>scriptstyle</item>
- <item>section</item>
- <item>setcounter</item>
- <item>setlanguage</item>
- <item>setlength</item>
- <item>settowidth</item>
- <item>sf</item>
- <item>shortstack</item>
- <item>signature</item>
- <item>sl</item>
- <item>sloppy</item>
- <item>sloppypar</item>
- <item>small</item>
- <item>smallskip</item>
- <item>smallskipamount</item>
- <item>sqrt</item>
- <item>stackrel</item>
- <item>stepcounter</item>
- <item>subparagraph</item>
- <item>subsection</item>
- <item>subsubsection</item>
- <item>symbol</item>
- <item>tabbing</item>
- <item>tabbingsep</item>
- <item>tabcolsep</item>
- <item>table</item>
- <item>tableofcontents</item>
- <item>tabular</item>
- <item>TeX</item>
- <item>textbf</item>
- <item>textit</item>
- <item>textfraction</item>
- <item>textfloatsep</item>
- <item>textheight</item>
- <item>textmd</item>
- <item>textrm</item>
- <item>textsc</item>
- <item>textsf</item>
- <item>textsl</item>
- <item>textstyle</item>
- <item>texttt</item>
- <item>textup</item>
- <item>textwidth</item>
- <item>thanks</item>
- <item>thebibliography</item>
- <item>thicklines</item>
- <item>thinlines</item>
- <item>thispagestyle</item>
- <item>tilde</item>
- <item>tiny</item>
- <item>title</item>
- <item>titlepage</item>
- <item>today</item>
- <item>topfraction</item>
- <item>topmargin</item>
- <item>topnumber</item>
- <item>topsep</item>
- <item>topskip</item>
- <item>totalnumber</item>
- <item>tt</item>
- <item>twocolumn</item>
- <item>typein</item>
- <item>typeout</item>
- <item>unboldmath</item>
- <item>underbrace</item>
- <item>underline</item>
- <item>unitlength</item>
- <item>usebox</item>
- <item>usepackage</item>
- <item>value</item>
- <item>vec</item>
- <item>vector</item>
- <item>verb</item>
- <item>verbatim</item>
- <item>verse</item>
- <item>vfill</item>
- <item>vline</item>
- <item>voffset</item>
- <item>vspace</item>
- <item>widehat</item>
- <item>widetilde</item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <StringDetect String="\begin{" attribute="Begin End" context="Paren" insensitive="FALSE"/>
- <StringDetect String="\end{" attribute="Begin End" context="Paren" insensitive="FALSE"/>
- <StringDetect String="\section{" attribute="Begin End" context="Paren" insensitive="FALSE"/>
- <StringDetect String="\subsection{" attribute="Begin End" context="Paren" insensitive="FALSE"/>
- <StringDetect String="\subsubsection{" attribute="Begin End" context="Paren" insensitive="FALSE"/>
- <StringDetect String="\title{" attribute="Begin End" context="Paren" insensitive="FALSE"/>
- <StringDetect String="\author{" attribute="Begin End" context="Paren" insensitive="FALSE"/>
- <StringDetect String="\usepackage{" attribute="Begin End" context="Paren" insensitive="FALSE"/>
- <StringDetect String="\usepackage[" attribute="Begin End" context="Paren" insensitive="FALSE"/>
- <StringDetect String="\(" attribute="Math" context="Keyword 2"/>
- <DetectChar char="\" attribute="Keyword" context="Keyword 1" />
- <RegExpr String="%.*$" attribute="Comment" context="#stay"/>
- </context>
- <context attribute="Environment" lineEndContext="#stay" name="Paren">
- <DetectChar char="}" attribute="Begin End" context="#pop"/>
- <DetectChar char="]" attribute="Begin End" context="#pop"/>
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Keyword 1">
- <keyword String="keywords" attribute="Keyword" context="#pop" />
- </context>
- <context attribute="Math" lineEndContext="#stay" name="Keyword 2">
- <keyword String="keywords" attribute="Keyword" context="#stay"/>
- <StringDetect String="\)" attribute="Math" context="#pop"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsNormal" color="#0000A0" selColor="#ff0000"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Begin End" defStyleNum="dsNormal" color="#000000" selColor="#ffffff" bold="1" italic="1"/>
- <itemData name="Math" defStyleNum="dsNormal" color="#FF8080" selColor="#008080" bold="0" italic="0"/>
- <itemData name="Environment" defStyleNum="dsNormal" color="#900000" selColor="#000080" bold="1" italic="0"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="%" />
- </comments>
- </general>
-</language>
-
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="LDIF" version="1.01" kateversion="2.1" section="Other"
- extensions="*.ldif" mimetype="application/directory"
- author="Andreas Hochsteger (e9625392@student.tuwien.ac.at)" license="">
- <highlighting>
- <list name="attributetypes">
- <item>IPPhone</item>
- <item>URL</item>
- <item>aRecord</item>
- <item>aliasedEntryName</item>
- <item>aliasedObjectName</item>
- <item>associatedDomain</item>
- <item>associatedName</item>
- <item>audio</item>
- <item>authorityRevocationList</item>
- <item>bootFile</item>
- <item>bootParameter</item>
- <item>buildingName</item>
- <item>businessCategory</item>
- <item>c</item>
- <item>cACertificate</item>
- <item>cNAMERecord</item>
- <item>certificateRevocationList</item>
- <item>cn</item>
- <item>comment</item>
- <item>commonName</item>
- <item>conferenceInformation</item>
- <item>corbaContainer</item>
- <item>corbaRepositoryId</item>
- <item>countryName</item>
- <item>crossCertificatePair</item>
- <item>custom1</item>
- <item>custom2</item>
- <item>custom3</item>
- <item>custom4</item>
- <item>dITRedirect</item>
- <item>dSAQuality</item>
- <item>dc</item>
- <item>deltaRevocationList</item>
- <item>description</item>
- <item>destinationIndicator</item>
- <item>distinguishedName</item>
- <item>dmdName</item>
- <item>dnQualifier</item>
- <item>documentAuthor</item>
- <item>documentIdentifier</item>
- <item>documentLocation</item>
- <item>documentPublisher</item>
- <item>documentTitle</item>
- <item>documentVersion</item>
- <item>domainComponent</item>
- <item>enhancedSearchGuide</item>
- <item>facsimileTelephoneNumber</item>
- <item>fax</item>
- <item>gecos</item>
- <item>generationQualifier</item>
- <item>gidNumber</item>
- <item>givenName</item>
- <item>gn</item>
- <item>homeDirectory</item>
- <item>homePostalAddress</item>
- <item>homeUrl</item>
- <item>host</item>
- <item>houseIdentifier</item>
- <item>info</item>
- <item>initials</item>
- <item>internationaliSDNNumber</item>
- <item>ipHostNumber</item>
- <item>ipNetmaskNumber</item>
- <item>ipNetworkNumber</item>
- <item>ipProtocolNumber</item>
- <item>ipServicePort</item>
- <item>ipServiceProtocol</item>
- <item>janetMailbox</item>
- <item>javaClassNames</item>
- <item>javaCodebase</item>
- <item>javaContainer</item>
- <item>javaDoc</item>
- <item>javaFactory</item>
- <item>javaReferenceAddress</item>
- <item>javaSerializedData</item>
- <item>knowledgeInformation</item>
- <item>l</item>
- <item>labeledURI</item>
- <item>lastModifiedBy</item>
- <item>lastModifiedTime</item>
- <item>lmpassword</item>
- <item>localityName</item>
- <item>loginShell</item>
- <item>mDRecord</item>
- <item>mXRecord</item>
- <item>macAddress</item>
- <item>mail</item>
- <item>manager</item>
- <item>member</item>
- <item>memberNisNetgroup</item>
- <item>memberUid</item>
- <item>mozillaHomeCountryName</item>
- <item>mozillaHomeFriendlyCountryName</item>
- <item>mozillaHomeLocalityName</item>
- <item>mozillaHomePostalAddress2</item>
- <item>mozillaHomePostalCode</item>
- <item>mozillaHomeState</item>
- <item>mozillaPostalAddress2</item>
- <item>mozillaSecondemail</item>
- <item>nSRecord</item>
- <item>name</item>
- <item>nisMapEntry</item>
- <item>nisMapName</item>
- <item>nisNetgroupTriple</item>
- <item>ntpasswd</item>
- <item>o</item>
- <item>objectClass</item>
- <item>oncRpcNumber</item>
- <item>organizationName</item>
- <item>organizationalStatus</item>
- <item>organizationalUnitName</item>
- <item>otherFacsimiletelephoneNumber</item>
- <item>otherMailbox</item>
- <item>ou</item>
- <item>owner</item>
- <item>personalSignature</item>
- <item>personalTitle</item>
- <item>photo</item>
- <item>physicalDeliveryOfficeName</item>
- <item>postOfficeBox</item>
- <item>postalAddress</item>
- <item>postalCode</item>
- <item>preferredDeliveryMethod</item>
- <item>presentationAddress</item>
- <item>protocolInformation</item>
- <item>rdn</item>
- <item>registeredAddress</item>
- <item>reports</item>
- <item>rfc822Mailbox</item>
- <item>roleOccupant</item>
- <item>roomNumber</item>
- <item>sOARecord</item>
- <item>searchGuide</item>
- <item>secretary</item>
- <item>seeAlso</item>
- <item>serialNumber</item>
- <item>shadowExpire</item>
- <item>shadowFlag</item>
- <item>shadowInactive</item>
- <item>shadowLastChange</item>
- <item>shadowMax</item>
- <item>shadowMin</item>
- <item>shadowWarning</item>
- <item>singleLevelQuality</item>
- <item>sn</item>
- <item>st</item>
- <item>stateOrProvinceName</item>
- <item>street</item>
- <item>streetAddress</item>
- <item>subtreeMaximumQuality</item>
- <item>subtreeMinimumQuality</item>
- <item>supportedAlgorithms</item>
- <item>supportedApplicationContext</item>
- <item>surname</item>
- <item>telephoneNumber</item>
- <item>teletexTerminalIdentifier</item>
- <item>telexNumber</item>
- <item>textEncodedORAddress</item>
- <item>title</item>
- <item>uid</item>
- <item>uidNumber</item>
- <item>uniqueIdentifier</item>
- <item>uniqueMember</item>
- <item>userCertificate</item>
- <item>userClass</item>
- <item>userPassword</item>
- <item>userid</item>
- <item>workUrl</item>
- <item>x121Address</item>
- <item>x500UniqueIdentifier</item>
- <item>xmozillaNickname</item>
- <item>xmozillaUseHtmlMail</item>
- <item>xmozillanickname</item>
- <item>xmozillausehtmlmail</item>
- </list>
- <list name="objectclasses">
- <item>RFC822localPart</item>
- <item>SUP</item>
- <item>account</item>
- <item>alias</item>
- <item>applicationEntity</item>
- <item>applicationProcess</item>
- <item>bootableDevice</item>
- <item>cRLDistributionPoint</item>
- <item>certificationAuthority</item>
- <item>certificationAuthority-V2</item>
- <item>corbaObject</item>
- <item>corbaObjectReference</item>
- <item>country</item>
- <item>dNSDomain</item>
- <item>dSA</item>
- <item>dcObject</item>
- <item>deltaCRL</item>
- <item>device</item>
- <item>dmd</item>
- <item>document</item>
- <item>documentSeries</item>
- <item>domain</item>
- <item>domainRelatedObject</item>
- <item>friendlyCountry</item>
- <item>groupOfNames</item>
- <item>groupOfUniqueNames</item>
- <item>ieee802Device</item>
- <item>inetOrgPerson</item>
- <item>ipHost</item>
- <item>ipNetwork</item>
- <item>ipProtocol</item>
- <item>ipService</item>
- <item>javaClassName</item>
- <item>javaMarshalledObject</item>
- <item>javaNamingReference</item>
- <item>javaObject</item>
- <item>javaSerializedObject</item>
- <item>labeledURIObject</item>
- <item>locality</item>
- <item>mozillaAbPersonObsolete</item>
- <item>nisMap</item>
- <item>nisNetgroup</item>
- <item>nisObject</item>
- <item>officePerson</item>
- <item>oncRpc</item>
- <item>organization</item>
- <item>organizationalPerson</item>
- <item>organizationalRole</item>
- <item>organizationalUnit</item>
- <item>pager</item>
- <item>pagerTelephoneNumber</item>
- <item>person</item>
- <item>pilotDSA</item>
- <item>pilotObject</item>
- <item>pilotOrganization</item>
- <item>pkiCA</item>
- <item>pkiUser</item>
- <item>posixAccount</item>
- <item>posixGroup</item>
- <item>qualityLabelledData</item>
- <item>residentialPerson</item>
- <item>rid</item>
- <item>room</item>
- <item>sambaAccount</item>
- <item>shadowAccount</item>
- <item>simpleSecurityObject</item>
- <item>strongAuthenticationUser</item>
- <item>telephoneNumber</item>
- <item>top</item>
- <item>uid</item>
- <item>uidNumber</item>
- <item>uidObject</item>
- <item>userSecurityInformation</item>
- <item>userid</item>
- <item>xmozillaanyphone</item>
- <item>zillaPerson</item>
- </list>
- <contexts>
- <context name="ctxStart" attribute="Value (Standard)" lineEndContext="#stay">
- <RegExpr String="#.*$" attribute="Comment" context="#stay"/>
- <RegExpr String=":" attribute="Description Keyword" context="ctxEncoded"/>
- <RegExpr String="&lt;" attribute="Description Keyword" context="ctxURL"/>
- <RegExpr String="[^:&lt;]" attribute="Value (Standard)" context="ctxStandard"/>
- <RegExpr String="^[\w\-]+((;[\w\-]+)+)?:" attribute="Description Keyword" context="#stay"/>
- </context>
- <context name="ctxEncoded" attribute="Value (Encoded)" lineEndContext="#stay">
- <RegExpr String="#.*$" attribute="Comment" context="#stay"/>
- <RegExpr String="[\s].*$" attribute="Value (Encoded)" context="#stay"/>
- <RegExpr String="^[\w\-]+((;[\w\-]+)+)?:" attribute="Description Keyword" context="#pop"/>
- </context>
- <context name="ctxURL" attribute="Value (URL)" lineEndContext="#stay">
- <RegExpr String="#.*$" attribute="Comment" context="#stay"/>
- <RegExpr String="[\s]+[\w]+://[\w/.]+" attribute="Value (URL)" context="#stay"/>
- <RegExpr String="[\s].*$" attribute="Value (URL)" context="#stay"/>
- <RegExpr String="^[\w\-]+((;[\w\-]+)+)?:" attribute="Description Keyword" context="#pop"/>
- </context>
- <context name="ctxStandard" attribute="Value (Standard)" lineEndContext="#stay">
- <RegExpr String="#.*$" attribute="Comment" context="#stay"/>
- <RegExpr String="\{\w+\}.*$" attribute="Value (Encrypted)" context="ctxEncrypted"/>
- <keyword String="attributetypes" attribute="AttributeType" context="#stay"/>
- <keyword String="objectclasses" attribute="ObjectClass" context="#stay"/>
- <RegExpr String="^[\w\-]+((;[\w\-]+)+)?:" attribute="Description Keyword" context="#pop"/>
- <RegExpr String="[a-zA-Z0-9\-]+=" attribute="Value (Keyword)" context="#stay"/>
- </context>
- <context name="ctxEncrypted" attribute="Value (Encrypted)" lineEndContext="#stay">
- <RegExpr String="#.*$" attribute="Comment" context="#stay"/>
- <RegExpr String="[\s].*$" attribute="Value (Encrypted)" context="#stay"/>
- <RegExpr String="^[\w\-]+((;[\w\-]+)+)?:" attribute="Description Keyword" context="#pop#pop"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" color="#000000" selColor="#FFFFFF" bold="0" italic="0"/>
- <itemData name="Comment" defStyleNum="dsComment" color="#808080" selColor="#808080" bold="0" italic="0"/>
- <itemData name="AttributeType" defStyleNum="dsKeyword" color="#404040" selColor="#FFFFFF" bold="1" italic="0"/>
- <itemData name="ObjectClass" defStyleNum="dsKeyword" color="#800080" selColor="#FFFFFF" bold="1" italic="0"/>
- <itemData name="Description Keyword" defStyleNum="dsKeyword" color="#000000" selColor="#FFFFFF" bold="1" italic="0"/>
- <itemData name="Value (Standard)" defStyleNum="dsString" color="#008000" selColor="#008000" bold="0" italic="0"/>
- <itemData name="Value (Encoded)" defStyleNum="dsString" color="#FF8000" selColor="#0080FF" bold="0" italic="0"/>
- <itemData name="Value (Encrypted)" defStyleNum="dsString" color="#FF0000" selColor="#00FFFF" bold="0" italic="0"/>
- <itemData name="Value (Keyword)" defStyleNum="dsString" color="#008000" selColor="#800080" bold="1" italic="0"/>
- <itemData name="Value (URL)" defStyleNum="dsString" color="#0000FF" selColor="#FFFF00" bold="0" italic="0"/>
- </itemDatas>
- </highlighting>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Literate Haskell" version="1.02" kateversion="2.1" section="Sources"
- extensions="*.lhs"
- author="Marcel Martin (mmar@freenet.de)" license="">
- <highlighting>
- <list name="keywords">
- <item> case </item>
- <item> class </item>
- <item> data </item>
- <item> deriving </item>
- <item> do </item>
- <item> else </item>
- <item> if </item>
- <item> in </item>
- <item> infixl </item>
- <item> infixr </item>
- <item> instance </item>
- <item> let </item>
- <item> module </item>
- <item> of </item>
- <item> primitive </item>
- <item> then </item>
- <item> type </item>
- <item> where </item>
- </list>
- <list name="infix operators">
- <item> quot </item>
- <item> rem </item>
- <item> div </item>
- <item> mod </item>
- <item> elem </item>
- <item> notElem </item>
- <item> seq </item>
- </list>
- <list name="functions">
- <!--
- These operators are not handled yet.
- <item> !! </item>
- <item> % </item>
- <item> && </item>
- <item> $! </item>
- <item> $ </item>
- <item> * </item>
- <item> ** </item>
- <item> - </item>
- <item> . </item>
- <item> /= </item>
- <item> < </item>
- <item> <= </item>
- <item> =<< </item>
- <item> == </item>
- <item> > </item>
- <item> >= </item>
- <item> >> </item>
- <item> >>= </item>
- <item> ^ </item>
- <item> ^^ </item>
- <item> ++ </item>
- <item> || </item>
- //-->
-
- <item> FilePath </item>
- <item> IOError </item>
- <item> abs </item>
- <item> acos </item>
- <item> acosh </item>
- <item> all </item>
- <item> and </item>
- <item> any </item>
- <item> appendFile </item>
- <item> approxRational </item>
- <item> asTypeOf </item>
- <item> asin </item>
- <item> asinh </item>
- <item> atan </item>
- <item> atan2 </item>
- <item> atanh </item>
- <item> basicIORun </item>
- <item> break </item>
- <item> catch </item>
- <item> ceiling </item>
- <item> chr </item>
- <item> compare </item>
- <item> concat </item>
- <item> concatMap </item>
- <item> const </item>
- <item> cos </item>
- <item> cosh </item>
- <item> curry </item>
- <item> cycle </item>
- <item> decodeFloat </item>
- <item> denominator </item>
- <item> digitToInt </item>
- <item> div </item>
- <item> divMod </item>
- <item> drop </item>
- <item> dropWhile </item>
- <item> either </item>
- <item> elem </item>
- <item> encodeFloat </item>
- <item> enumFrom </item>
- <item> enumFromThen </item>
- <item> enumFromThenTo </item>
- <item> enumFromTo </item>
- <item> error </item>
- <item> even </item>
- <item> exp </item>
- <item> exponent </item>
- <item> fail </item>
- <item> filter </item>
- <item> flip </item>
- <item> floatDigits </item>
- <item> floatRadix </item>
- <item> floatRange </item>
- <item> floor </item>
- <item> fmap </item>
- <item> foldl </item>
- <item> foldl1 </item>
- <item> foldr </item>
- <item> foldr1 </item>
- <item> fromDouble </item>
- <item> fromEnum </item>
- <item> fromInt </item>
- <item> fromInteger </item>
- <item> fromIntegral </item>
- <item> fromRational </item>
- <item> fst </item>
- <item> gcd </item>
- <item> getChar </item>
- <item> getContents </item>
- <item> getLine </item>
- <item> head </item>
- <item> id </item>
- <item> inRange </item>
- <item> index </item>
- <item> init </item>
- <item> intToDigit </item>
- <item> interact </item>
- <item> ioError </item>
- <item> isAlpha </item>
- <item> isAlphaNum </item>
- <item> isAscii </item>
- <item> isControl </item>
- <item> isDenormalized </item>
- <item> isDigit </item>
- <item> isHexDigit </item>
- <item> isIEEE </item>
- <item> isInfinite </item>
- <item> isLower </item>
- <item> isNaN </item>
- <item> isNegativeZero </item>
- <item> isOctDigit </item>
- <item> isPrint </item>
- <item> isSpace </item>
- <item> isUpper </item>
- <item> iterate </item>
- <item> last </item>
- <item> lcm </item>
- <item> length </item>
- <item> lex </item>
- <item> lexDigits </item>
- <item> lexLitChar </item>
- <item> lines </item>
- <item> log </item>
- <item> logBase </item>
- <item> lookup </item>
- <item> map </item>
- <item> mapM </item>
- <item> mapM_ </item>
- <item> max </item>
- <item> maxBound </item>
- <item> maximum </item>
- <item> maybe </item>
- <item> min </item>
- <item> minBound </item>
- <item> minimum </item>
- <item> mod </item>
- <item> negate </item>
- <item> not </item>
- <item> notElem </item>
- <item> null </item>
- <item> numerator </item>
- <item> odd </item>
- <item> or </item>
- <item> ord </item>
- <item> otherwise </item>
- <item> pi </item>
- <item> pred </item>
- <item> primExitWith </item>
- <item> print </item>
- <item> product </item>
- <item> properFraction </item>
- <item> putChar </item>
- <item> putStr </item>
- <item> putStrLn </item>
- <item> quot </item>
- <item> quotRem </item>
- <item> range </item>
- <item> rangeSize </item>
- <item> read </item>
- <item> readDec </item>
- <item> readFile </item>
- <item> readFloat </item>
- <item> readHex </item>
- <item> readIO </item>
- <item> readInt </item>
- <item> readList </item>
- <item> readLitChar </item>
- <item> readLn </item>
- <item> readOct </item>
- <item> readParen </item>
- <item> readSigned </item>
- <item> reads </item>
- <item> readsPrec </item>
- <item> realToFrac </item>
- <item> recip </item>
- <item> rem </item>
- <item> repeat </item>
- <item> replicate </item>
- <item> return </item>
- <item> reverse </item>
- <item> round </item>
- <item> scaleFloat </item>
- <item> scanl </item>
- <item> scanl1 </item>
- <item> scanr </item>
- <item> scanr1 </item>
- <item> seq </item>
- <item> sequence </item>
- <item> sequence_ </item>
- <item> show </item>
- <item> showChar </item>
- <item> showInt </item>
- <item> showList </item>
- <item> showLitChar </item>
- <item> showParen </item>
- <item> showSigned </item>
- <item> showString </item>
- <item> shows </item>
- <item> showsPrec </item>
- <item> significand </item>
- <item> signum </item>
- <item> sin </item>
- <item> sinh </item>
- <item> snd </item>
- <item> span </item>
- <item> splitAt </item>
- <item> sqrt </item>
- <item> subtract </item>
- <item> succ </item>
- <item> sum </item>
- <item> tail </item>
- <item> take </item>
- <item> takeWhile </item>
- <item> tan </item>
- <item> tanh </item>
- <item> threadToIOResult </item>
- <item> toEnum </item>
- <item> toInt </item>
- <item> toInteger </item>
- <item> toLower </item>
- <item> toRational </item>
- <item> toUpper </item>
- <item> truncate </item>
- <item> uncurry </item>
- <item> undefined </item>
- <item> unlines </item>
- <item> until </item>
- <item> unwords </item>
- <item> unzip </item>
- <item> unzip3 </item>
- <item> userError </item>
- <item> words </item>
- <item> writeFile </item>
- <item> zip </item>
- <item> zip3 </item>
- <item> zipWith </item>
- <item> zipWith3 </item>
- </list>
- <list name="type constructors">
- <item> Bool </item>
- <item> Char </item>
- <item> Double </item>
- <item> Either </item>
- <item> Float </item>
- <item> IO </item>
- <item> Integer </item>
- <item> Int </item>
- <item> Maybe </item>
- <item> Ordering </item>
- <item> Rational </item>
- <item> Ratio </item>
- <item> ReadS </item>
- <item> ShowS </item>
- <item> String </item>
-
- </list>
- <list name="classes">
- <item> Bounded </item>
- <item> Enum </item>
- <item> Eq </item>
- <item> Floating </item>
- <item> Fractional </item>
- <item> Functor </item>
- <item> Integral </item>
- <item> Ix </item>
- <item> Monad </item>
- <item> Num </item>
- <item> Ord </item>
- <item> Read </item>
- <item> RealFloat </item>
- <item> RealFrac </item>
- <item> Real </item>
- <item> Show </item>
- </list>
- <list name="data constructors">
- <item> EQ </item>
- <item> False </item>
- <item> GT </item>
- <item> Just </item>
- <item> LT </item>
- <item> Left </item>
- <item> Nothing </item>
- <item> Right </item>
- <item> True </item>
- </list>
- <contexts>
- <context attribute="Comment" lineEndContext="#stay" name="literate-normal">
- <RegExpr attribute="Special" context="normal" String="^&gt;\s*" />
- </context>
- <context attribute="Normal Text" lineEndContext="literate-normal" name="normal">
- <Detect2Chars attribute="Comment" context="comment_multi_line" char="{" char1="-" />
- <Detect2Chars attribute="Comment" context="comment_single_line" char="-" char1="-" />
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Class" context="#stay" String="classes" />
- <keyword attribute="Type Constructor" context="#stay" String="type constructors" />
- <keyword attribute="Function" context="#stay" String="functions" />
- <keyword attribute="Data Constructor" context="#stay" String="data constructors" />
- <DetectChar attribute="String" context="string" char="&quot;" />
- <DetectChar attribute="Infix Operator" context="infix" char="`"/>
- <RegExpr attribute="Normal Text" context="#stay" String="[A-Za-z0-9_][']+" />
- <DetectChar attribute="Char" context="single_char" char="'" />
- <RegExpr attribute="Function Definition" context="#stay" String="\s*[a-z_]+[A-Za-z_0-9]*'*\s*::" />
- <Float attribute="Float" context="#stay" />
- <Int attribute="Decimal" context="#stay" />
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="comment_single_line" />
- <context attribute="Comment" lineEndContext="#stay" name="comment_multi_line">
- <Detect2Chars attribute="Comment" context="#pop" char="-" char1="}" />
- </context>
- <context attribute="String" lineEndContext="#stay" name="string">
- <RegExpr attribute="String" context="#stay" String="\\." />
- <DetectChar attribute="String" context="#pop" char="&quot;" />
- </context>
- <context attribute="Infix Operator" lineEndContext="#stay" name="infix">
- <DetectChar attribute="Infix Operator" context="#pop" char="`"/>
- </context>
- <context attribute="Char" lineEndContext="#pop" name="single_char">
- <RegExpr attribute="Char" context="#stay" String="\\." />
- <DetectChar attribute="Char" context="#pop" char="'" />
- </context>
- <context attribute="Function Definition" lineEndContext="#pop" name="function_definition">
- <DetectChar attribute="Function Definition" context="#pop" char=";" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Function" defStyleNum="dsOthers"/>
- <itemData name="Function Definition" defStyleNum="dsOthers"/>
- <itemData name="Class" defStyleNum="dsKeyword"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Constructor" defStyleNum="dsOthers"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Data Constructor" defStyleNum="dsKeyword"/>
- <itemData name="Type Constructor" defStyleNum="dsDataType"/>
- <itemData name="Infix Operator" defStyleNum="dsOthers"/>
- <itemData name="Special" defStyleNum="dsChar"/>
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="LPC" version="0.12" kateversion="2.1" section="Sources" extensions="*.c;*.h;*.o">
- <highlighting>
- <list name="l_mod">
- <item> private </item>
- <item> protected </item>
- <item> static </item>
- <item> public </item>
- <item> nomask </item>
- <item> varargs </item>
- <item> nosave </item>
- <item> virtual </item>
- </list>
- <list name="l_typ">
- <item> void </item>
- <item> int </item>
- <item> status </item>
- <item> string </item>
- <item> object </item>
- <item> array </item>
- <item> mapping </item>
- <item> closure </item>
- <item> symbol </item>
- <item> float </item>
- <item> mixed </item>
- </list>
- <list name="l_key">
- <item> break </item>
- <item> continue </item>
- <item> return </item>
- <item> if </item>
- <item> else </item>
- <item> for </item>
- <item> foreach </item>
- <item> do </item>
- <item> while </item>
- <item> switch </item>
- <item> case </item>
- <item> inherit </item>
- <item> default </item>
- <item> variables </item>
- <item> functions </item>
- </list>
- <list name="l_predef">
- <item> LPC3 </item>
- <item> __LDMUD__ </item>
- <item> __EUIDS__ </item>
- <item> COMPAT_FLAG </item>
- <item> __COMPAT_MODE__ </item>
- <item> __STRICT_EUIDS__ </item>
- <item> __MASTER_OBJECT__ </item>
- <item> __FILE__ </item>
- <item> __LINE__ </item>
- <item> __DIR__ </item>
- <item> __PATH__ </item>
- <item> __VERSION__ </item>
- <item> __VERSION_MAJOR__ </item>
- <item> __VERSION_MINOR__ </item>
- <item> __VERSION_MICRO__ </item>
- <item> __VERSION_PATCH__ </item>
- <item> __DOMAIN_NAME__ </item>
- <item> __HOST_IP_NUMBER__ </item>
- <item> __HOST_NAME__ </item>
- <item> __MAX_RECURSION__ </item>
- <item> __MAX_EVAL_COST__ </item>
- <item> __CATCH_EVAL_COST__ </item>
- <item> __MASTER_EVAL_COST__ </item>
- <item> __RESET_TIME__ </item>
- <item> __CLEANUP_TIME__ </item>
- <item> __EFUN_DEFINED__ </item>
- <item> __DRIVER_LOG__ </item>
- <item> __WIZLIST__ </item>
- <item> __INT_MAX__ </item>
- <item> __INT_MIN__ </item>
- <item> __FLOAT_MAX__ </item>
- <item> __FLOAT_MIN__ </item>
- <item> __ERQ_MAX_SEND__ </item>
- <item> __ERQ_MAX_REPLY__ </item>
- <item> __IPV6__ </item>
- <item> __MYSQL__ </item>
- <item> __LPC_NOSAVE__ </item>
- <item> __DEPRECATED__ </item>
- </list>
- <list name="l_efun">
- <item> abs </item>
- <item> acos </item>
- <item> add_action </item>
- <item> add_verb </item>
- <item> add_xverb </item>
- <item> all_environment </item>
- <item> all_inventory </item>
- <item> allocate </item>
- <item> allocate_mapping </item>
- <item> and_bits </item>
- <item> apply </item>
- <item> asin </item>
- <item> assoc </item>
- <item> atan </item>
- <item> atan2 </item>
- <item> attach_erq_demon </item>
- <item> binary_message </item>
- <item> bind_lambda </item>
- <item> blueprint </item>
- <item> break_point </item>
- <item> call_other </item>
- <item> call_out </item>
- <item> call_out_info </item>
- <item> call_resolved </item>
- <item> caller_stack </item>
- <item> caller_stack_depth </item>
- <item> capitalize </item>
- <item> cat </item>
- <item> catch </item>
- <item> ceil </item>
- <item> clear_bit </item>
- <item> clone_object </item>
- <item> clonep </item>
- <item> clones </item>
- <item> closurep </item>
- <item> command </item>
- <item> command_stack </item>
- <item> command_stack_depth </item>
- <item> copy </item>
- <item> copy_bits </item>
- <item> copy_file </item>
- <item> copy_mapping </item>
- <item> cos </item>
- <item> count_bits </item>
- <item> creator </item>
- <item> crypt </item>
- <item> ctime </item>
- <item> db_affected_rows </item>
- <item> db_close </item>
- <item> db_coldefs </item>
- <item> db_connect </item>
- <item> db_conv_string </item>
- <item> db_error </item>
- <item> db_exec </item>
- <item> db_fetch </item>
- <item> db_handles </item>
- <item> db_insert_id </item>
- <item> debug_info </item>
- <item> debug_message </item>
- <item> deep_copy </item>
- <item> deep_inventory </item>
- <item> destruct </item>
- <item> disable_commands </item>
- <item> ed </item>
- <item> efun </item>
- <item> efun308 </item>
- <item> enable_commands </item>
- <item> environment </item>
- <item> exec </item>
- <item> execute_command </item>
- <item> exp </item>
- <item> expand_define </item>
- <item> explode </item>
- <item> export_uid </item>
- <item> extern_call </item>
- <item> extract </item>
- <item> file_name </item>
- <item> file_size </item>
- <item> filter </item>
- <item> filter_array </item>
- <item> filter_indices </item>
- <item> filter_mapping </item>
- <item> filter_objects </item>
- <item> find_call_out </item>
- <item> find_input_to </item>
- <item> find_object </item>
- <item> first_inventory </item>
- <item> floatp </item>
- <item> floor </item>
- <item> funcall </item>
- <item> function_exists </item>
- <item> functionlist </item>
- <item> garbage_collection </item>
- <item> get_dir </item>
- <item> get_error_file </item>
- <item> get_eval_cost </item>
- <item> get_extra_wizinfo </item>
- <item> get_type_info </item>
- <item> geteuid </item>
- <item> getuid </item>
- <item> gmtime </item>
- <item> heart_beat_info </item>
- <item> implode </item>
- <item> include_list </item>
- <item> inherit_list </item>
- <item> input_to </item>
- <item> input_to_info </item>
- <item> insert_alist </item>
- <item> interactive </item>
- <item> intersect_alist </item>
- <item> intp </item>
- <item> invert_bits </item>
- <item> lambda </item>
- <item> last_bit </item>
- <item> last_instructions </item>
- <item> limited </item>
- <item> living </item>
- <item> load_name </item>
- <item> load_object </item>
- <item> localtime </item>
- <item> log </item>
- <item> lower_case </item>
- <item> m_add </item>
- <item> m_allocate </item>
- <item> m_contains </item>
- <item> m_delete </item>
- <item> m_indices </item>
- <item> m_reallocate </item>
- <item> m_sizeof </item>
- <item> m_values </item>
- <item> make_shared_string </item>
- <item> map </item>
- <item> map_array </item>
- <item> map_indices </item>
- <item> map_mapping </item>
- <item> map_objects </item>
- <item> mapping_contains </item>
- <item> mappingp </item>
- <item> max </item>
- <item> md5 </item>
- <item> member </item>
- <item> member_array </item>
- <item> min </item>
- <item> mkdir </item>
- <item> mkmapping </item>
- <item> move_object </item>
- <item> negate </item>
- <item> next_bit </item>
- <item> next_inventory </item>
- <item> notify_fail </item>
- <item> object_info </item>
- <item> object_name </item>
- <item> object_time </item>
- <item> objectp </item>
- <item> or_bits </item>
- <item> order_alist </item>
- <item> parse_command </item>
- <item> pointerp </item>
- <item> pow </item>
- <item> present </item>
- <item> present_clone </item>
- <item> previous_object </item>
- <item> printf </item>
- <item> process_string </item>
- <item> program_name </item>
- <item> program_time </item>
- <item> query_actions </item>
- <item> query_command </item>
- <item> query_editing </item>
- <item> query_idle </item>
- <item> query_imp_port </item>
- <item> query_input_pending </item>
- <item> query_ip_name </item>
- <item> query_ip_number </item>
- <item> query_limits </item>
- <item> query_load_average </item>
- <item> query_mud_port </item>
- <item> query_notify_fail </item>
- <item> query_once_interactive </item>
- <item> query_shadowing </item>
- <item> query_snoop </item>
- <item> query_udp_port </item>
- <item> query_verb </item>
- <item> quote </item>
- <item> raise_error </item>
- <item> random </item>
- <item> read_bytes </item>
- <item> read_file </item>
- <item> referencep </item>
- <item> regexp </item>
- <item> regexplode </item>
- <item> regreplace </item>
- <item> remove_action </item>
- <item> remove_call_out </item>
- <item> remove_input_to </item>
- <item> remove_interactive </item>
- <item> rename </item>
- <item> rename_object </item>
- <item> replace_program </item>
- <item> restore_object </item>
- <item> restore_value </item>
- <item> rm </item>
- <item> rmdir </item>
- <item> rusage </item>
- <item> save_object </item>
- <item> save_value </item>
- <item> say </item>
- <item> send_erq </item>
- <item> send_imp </item>
- <item> send_udp </item>
- <item> set_auto_include_string </item>
- <item> set_bit </item>
- <item> set_buffer_size </item>
- <item> set_combine_charset </item>
- <item> set_connection_charset </item>
- <item> set_driver_hook </item>
- <item> set_environment </item>
- <item> set_extra_wizinfo </item>
- <item> set_extra_wizinfo_size </item>
- <item> set_heart_beat </item>
- <item> set_is_wizard </item>
- <item> set_light </item>
- <item> set_limits </item>
- <item> set_modify_command </item>
- <item> set_next_reset </item>
- <item> set_prompt </item>
- <item> set_this_object </item>
- <item> set_this_player </item>
- <item> seteuid </item>
- <item> sgn </item>
- <item> shadow </item>
- <item> shutdown </item>
- <item> sin </item>
- <item> sizeof </item>
- <item> slice_array </item>
- <item> snoop </item>
- <item> sort_array </item>
- <item> sprintf </item>
- <item> sqrt </item>
- <item> sscanf </item>
- <item> stringp </item>
- <item> strlen </item>
- <item> strstr </item>
- <item> swap </item>
- <item> symbol_function </item>
- <item> symbol_variable </item>
- <item> symbolp </item>
- <item> tail </item>
- <item> tan </item>
- <item> tell_object </item>
- <item> tell_room </item>
- <item> terminal_colour </item>
- <item> test_bit </item>
- <item> this_interactive </item>
- <item> this_object </item>
- <item> this_player </item>
- <item> throw </item>
- <item> time </item>
- <item> to_array </item>
- <item> to_float </item>
- <item> to_int </item>
- <item> to_object </item>
- <item> to_string </item>
- <item> trace </item>
- <item> traceprefix </item>
- <item> transfer </item>
- <item> transpose_array </item>
- <item> trim </item>
- <item> typeof </item>
- <item> unbound_lambda </item>
- <item> unique_array </item>
- <item> unmkmapping </item>
- <item> unquote </item>
- <item> unshadow </item>
- <item> upper_case </item>
- <item> users </item>
- <item> utime </item>
- <item> walk_mapping </item>
- <item> widthof </item>
- <item> wizlist_info </item>
- <item> write </item>
- <item> write_bytes </item>
- <item> write_file </item>
- <item> xor_bits </item>
- </list>
- <contexts>
- <context attribute="iNormal" name="0" lineEndContext="0" >
- <DetectChar attribute="iString" context="18" char="&quot;" />
- <Detect2Chars attribute="iSingle Comment" context="12" char="/" char1="/" />
- <Detect2Chars attribute="iMulti Comment" context="13" char="/" char1="*" beginRegion="multiLine" />
- <keyword attribute="iModifiers" String="l_mod" context="0" />
- <keyword attribute="iData Types" String="l_typ" context="0" />
- <keyword attribute="iKeywords" String="l_key" context="0" />
- <keyword attribute="iPredefined" String="l_predef" context="0" />
- <keyword attribute="iEFuns" String="l_efun" context="0" />
- <Float attribute="iFloat" context="0" />
- <RegExpr attribute="iOctal" String="0o[0-9]+" context="0" />
- <RegExpr attribute="iHex" String="0x[0-9A-Fa-f]+" context="0" />
- <RegExpr attribute="iInt" String="[0-9]+" context="0" />
- <RegExpr attribute="iChar" String="'(\\.|.)'" context="0" />
- <RegExpr attribute="iClosure" context="0" String="#'[-_A-Za-z0-9]*" />
- <Detect2Chars attribute="iSingle Comment" context="12" char="/" char1="/" />
- <DetectChar attribute="iRound Brace" char="(" beginRegion="rRoundBrace" context="0"/>
- <DetectChar attribute="iRound Brace" char=")" endRegion="rRoundBrace" context="0" />
- <DetectChar attribute="iBlock Brace" char="{" beginRegion="rBlockBrace" context="0" />
- <DetectChar attribute="iBlock Brace" char="}" endRegion="rBlockBrace" context="0" />
- <DetectChar attribute="iIndex Brace" char="[" beginRegion="rIndexBrace" context="0" />
- <DetectChar attribute="iIndex Brace" char="]" endRegion="rIndexBrace" context="0" />
- <RegExpr attribute="iPreprocessor" String="^#" context="17" />
- </context>
- <context name="1" attribute="iModifiers" lineEndContext="0" />
- <context name="2" attribute="iData Types" lineEndContext="0" />
- <context name="3" attribute="iKeywords" lineEndContext="0" />
- <context name="4" attribute="iPredefined" lineEndContext="0" />
- <context name="5" attribute="iEFuns" lineEndContext="0" />
- <context name="6" attribute="iOctal" lineEndContext="0" />
- <context name="7" attribute="iHex" lineEndContext="0" />
- <context name="8" attribute="iInt" lineEndContext="0" />
- <context name="9" attribute="iFloat" lineEndContext="0" />
- <context name="10" attribute="iChar" lineEndContext="0" />
- <context name="11" attribute="iClosure" lineEndContext="0" />
- <context name="12" attribute="iSingle Comment" lineEndContext="0">
- <RegExpr attribute="iComment Highlight" String="([A-Z][A-Za-z]*( by)*:+|EOF|End of file[.]+)" context="12"/>
- </context>
- <context name="13" attribute="iMulti Comment" lineEndContext="13">
- <RegExpr attribute="iComment Highlight" String="([A-Z][A-Za-z]*( by)*:+|EOF|End of file[.]+)" context="13"/>
- <Detect2Chars attribute="iMulti COmment" char="*" char1="/" context="0" endRegion="multiLine" />
- </context>
- <context name="14" attribute="iPreprocessor" lineEndContext="0" />
- <context name="15" attribute="iString" lineEndContext="0" />
- <context name="16" attribute="iComment Highlight" lineEndContext="0" />
- <context name="17" attribute="iPreprocessor" lineEndContext="0">
- <DetectChar attribute="iPreString" char="&quot;" context="22" />
- <DetectChar attribute="iPreString" char="&lt;" context="23" />
- <Detect2Chars attribute="iSingle Comment" context="12" char="/" char1="/" />
- <RegExpr attribute="iPreprocessor directives" context="17" String="(defined|include|define|ifdef|ifndef|if|else|elif|endif|undef|line|echo|pragma)" />
- <RegExpr attribute="iPragmas" context="17" String="(combine_strings|no_combine_string|no_clone|no_inherit|no_shadow|weak_types|strict_types|save_types|no_local_scopes|pedantic|sloppy|warn_deprecated|no_warn_deprecated|set_code_window|show_code_window)" />
- <LineContinue attribute="iPreprocessor" context="17" />
- </context>
- <context name="18" attribute="iString" lineEndContext="18">
- <LineContinue attribute="iString" context="#stay"/>
- <HlCStringChar attribute="iPreString" context="18"/>
- <DetectChar attribute="iString" char="&quot;" context="0" />
- </context>
- <context name="19" attribute="iComment Highlight" lineEndContext="0" />
- <context name="20" attribute="iPreprocessor directives" lineEndContext="0" />
- <context name="21" attribute="iPragmas" lineEndContext="0" />
- <context name="22" attribute="iPreString" lineEndContext="22">
- <DetectChar attribute="iPreString" char="&quot;" context="17" />
- </context>
- <context name="23" attribute="iPreString" lineEndContext="23">
- <DetectChar attribute="iPreString" char="&gt;" context="17" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="iNormal Text" defStyleNum="dsNormal" />
- <itemData name="iModifiers" defStyleNum="dsKeyword" />
- <itemData name="iData Types" defStyleNum="dsDataType" />
- <itemData name="iKeywords" defStyleNum="dsKeyword" />
- <itemData name="iPredefined" defStyleNum="dsOthers" />
- <itemData name="iEFuns" defStyleNum="dsKeyword" />
- <itemData name="iOctal" defStyleNum="dsBaseN" />
- <itemData name="iHex" defStyleNum="dsBaseN" />
- <itemData name="iInt" defStyleNum="dsDecVal" />
- <itemData name="iFloat" defStyleNum="dsFloat" />
- <itemData name="iChar" defStyleNum="dsChar" />
- <itemData name="iClosure" defStyleNum="dsOthers" />
- <itemData name="iSingle Comment" defStyleNum="dsComment" />
- <itemData name="iMulti Comment" defStyleNum="dsComment" />
- <itemData name="iRound Brace" defStyleNum="dsNormal" />
- <itemData name="iBlock Brace" defStyleNum="dsNormal" />
- <itemData name="iIndex Brace" defStyleNum="dsNormal" />
- <itemData name="iPreprocessor" defStyleNum="dsOthers" />
- <itemData name="iString" defStyleNum="dsString" />
- <itemData name="iComment Highlight" defStyleNum="dsComment" />
- <itemData name="iPreprocessor directives" defStyleNum="dsOthers" />
- <itemData name="iPragmas" defStyleNum="dsOthers" />
- <itemData name="iPreString" defStyleNum="dsOthers" />
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="MAB-DB" version="1.01" kateversion="2.1"
- extensions="*.mab;*.MAB;*.Mab" section="Markup" mimetype="text/x-mab" casesensitive="0">
- <highlighting>
- <contexts>
- <context attribute="Normal Text" name="Section" lineEndContext="#stay" >
- <RegExpr String="^\*I [a-zA-Z01-9]* " attribute="Mab I Field" context="#stay"/>
- <RegExpr String="^\*\*\*\**E.*" attribute="Header Piece" context="#stay"/>
- <RegExpr String="^\*\*\*\**M.*" attribute="Header Medium" context="#stay"/>
- <RegExpr String="^\*\*\*\* BIBLIOTHECA.*" attribute="Database Header" context="#stay" />
- <RegExpr String="^\*M [a-zA-Z01-9]* " attribute="Mab M Field" context="#stay"/>
- <RegExpr String="^\*X TYP .*" attribute="Mab Comment Description" context="#stay" />
- <RegExpr String="^\*X DESC .*" attribute="Mab Comment Type" context="#stay" />
- <RegExpr String="^\*X .*" attribute="Comment" context="#stay" />
- </context>
- </contexts>
-
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" color="#FF0022" selColor="#ffffff" italic="0" bold="1" />
- <itemData name="Header Piece" defStyleNum="dsKeyword" color="#993322" selColor="#ffffff" italic="0" bold="1" />
- <itemData name="Header Medium" defStyleNum="dsKeyword" color="#339922" selColor="#ffffff" italic="0" bold="1" />
- <itemData name="Database Header" defStyleNum="dsKeyword" color="#FF3322" selColor="#ffffff" italic="0" bold="1" />
- <itemData name="Mab M Field" defStyleNum="dsKeyword" color="#003366" selColor="#ffffff" italic="0" bold="1" />
- <itemData name="Mab I Field" defStyleNum="dsKeyword" color="#330066" selColor="#ffffff" italic="0" bold="1" />
- <itemData name="Mab Comment Description" defStyleNum="dsKeyword" color="#3333FF" selColor="#ffffff" italic="1" bold="1" />
- <itemData name="Mab Comment Type" defStyleNum="dsKeyword" color="#BB3333" selColor="#ffffff" italic="1" bold="1" />
- <itemData name="Comment" defStyleNum="dsKeyword" color="#999999" selColor="#ffffff" italic="1" bold="1" />
- </itemDatas>
- </highlighting>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!-- Makefile syntaxfile v0.9 by Per Wigren <wigren@home.se> -->
-<!-- Modified by Joseph Wenninger <jowenn@kde.org> -->
-<language name="Makefile" version="1.03" kateversion="2.1" section="Other"
- extensions="" mimetype="text/x-makefile"
- author="Per Wigren (wigren@home.se)" license="">
- <highlighting>
- <list name = "keywords">
- <item> include </item>
- <item> define </item>
- <item> else </item>
- <item> endef </item>
- <item> endif </item>
- <item> ifdef </item>
- <item> ifeq </item>
- <item> ifndef </item>
- <item> ifneq </item>
- </list>
-
- <contexts>
- <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <RegExpr attribute="Variable" context="Value" String="[_\w\d]*\s*(?=:=|=)"/>
- <RegExpr attribute="Target" context="#stay" String="^\s*[_\w\d-]*\s*:"/>
- <RegExpr attribute="Section" context="#stay" String="^[.].*:"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <RegExpr attribute="Operator" context="VarFromNormal" String="[$][\({]"/>
- <AnyChar attribute="Operator" context="#stay" String="+*=%$():\\&#059;" />
- <RegExpr attribute="Operator" context="Commands" String="^\s*[@-]"/>
- <RegExpr attribute="Comment" context="#stay" String="#.*$"/>
- </context>
-
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
-
- <context name="Value" attribute="String" lineEndContext="#stay">
- <RegExpr attribute="Operator" String="\\$" context="#stay"/>
- <RegExpr attribute="String" String="[^\\]?$" context="#pop"/>
- <RegExpr attribute="Operator" String="[$][\({]" context="VarFromValue"/>
- <RegExpr attribute="Special" context="#pop" String="@[-_\d\w]*@" />
- <DetectChar attribute="Operator" char="&#059;" context="#pop"/>
- </context>
-
- <context name="VarFromValue" attribute="Variable" lineEndContext="#stay">
- <RegExpr attribute="Operator" String="[\)}](?=/)" context="#pop"/>
- <RegExpr attribute="Operator" String="[\)}][^$]" context="#pop"/>
- <RegExpr attribute="Operator" String="[\)}]$" context="#pop#pop"/>
- </context>
-
- <context name="VarFromNormal" attribute="Variable" lineEndContext="#stay">
- <RegExpr attribute="Operator" String="[\)}]" context="#pop"/>
- </context>
-
- <context name="Commands" attribute="Normal Text" lineEndContext="#pop">
- <RegExpr attribute="Operator" context="VarFromNormal" String="[$][\({]"/>
- <RegExpr attribute="Commands" context="#pop" String="[_\w-]*\b"/>
- </context>
-
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Variable" defStyleNum="dsDataType"/>
- <itemData name="Target" defStyleNum="dsDecVal"/>
- <itemData name="Section" defStyleNum="dsOthers"/>
- <itemData name="Operator" defStyleNum="dsChar"/>
- <itemData name="Commands" defStyleNum="dsBaseN"/>
- <itemData name="Special" defStyleNum="dsFloat"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name = "singleLine" start = "#"/>
- </comments>
- <keywords casesensitive = "1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language version="1.04" kateversion="2.1" name="Mason" section="Scripts" extensions="*.html;" mimetype="">
-<highlighting>
- <list name="keywords">
- <item> sub </item>
- <item> bless </item>
- <item> caller </item>
- <item> cmp </item>
- <item> print </item>
- <item> echo </item>
- <item> die </item>
- <item> import </item>
- <item> lt </item>
- <item> le </item>
- <item> local </item>
- <item> last </item>
- <item> ! </item>
- <item> || </item>
- <item> eq </item>
- <item> ne </item>
- <item> use </item>
- <item> elsif </item>
- <item> my </item>
- <item> foreach </item>
- <item> wantarray </item>
- <item> push </item>
- <item> pop </item>
- <item> dbmclose </item>
- <item> dbmopen </item>
- <item> dump </item>
- <item> each </item>
- <item> ge </item>
- <item> gt </item>
- <item> split </item>
- <item> open </item>
- <item> close </item>
- <item> eval </item>
- <item> chomp </item>
- <item> chop </item>
- <item> unless </item>
- <item> undef </item>
- <item> next </item>
- <item> unlink </item>
- <item> new </item>
- <item> and </item>
- <item> not </item>
- <item> no </item>
- <item> ref </item>
- <item> redo </item>
- <item> require </item>
- <item> tied </item>
- <item> tie </item>
- <item> untie </item>
- <item> or </item>
- <item> xor </item>
- <item> continue </item>
- <item> do </item>
- <item> else </item>
- <item> for </item>
- <item> goto </item>
- <item> if </item>
- <item> return </item>
- <item> switch </item>
- <item> while </item>
- </list>
-
- <contexts>
- <context attribute="HTML" lineEndContext="#stay" name="HTML">
- <RegExpr attribute="Mason Tag" context="EmbeddedPerl" String="&lt;\%method[^&gt;]*&gt;" />
- <StringDetect attribute="Mason Tag" context="EmbeddedPerl" String="&lt;%method&gt;" insensitive="FALSE" />
- <StringDetect attribute="Comment" context="Documentation" String="&lt;%doc&gt;" insensitive="FALSE" />
-
- <StringDetect attribute="Mason Tag" context="EmbeddedPerl" String="&lt;%perl&gt;" insensitive="FALSE" />
- <Detect2Chars attribute="Mason Tag" context="EmbeddedPerl" char="&lt;" char1="%" />
- <Detect2Chars attribute="Mason Method" context="MethodCall" char="&lt;" char1="&amp;" />
- <RegExpr attribute="Mason Tag" context="PerlOneLiner" String="^%" />
- </context>
-
- <context attribute="normal" lineEndContext="#stay" name="EmbeddedPerl">
- <Detect2Chars attribute="Mason Tag" context="#pop" char="%" char1="&gt;" />
- <StringDetect attribute="Mason Tag" context="#pop" String="&lt;/%perl&gt;" insensitive="FALSE" />
- <StringDetect attribute="Mason Tag" context="#pop" String="&lt;/%method&gt;" insensitive="FALSE" />
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <HlCOct attribute="Octal" context="#stay"/>
- <HlCHex attribute="Hex" context="#stay"/>
- <Int attribute="Decimal" context="#stay" />
- <HlCChar attribute="Char" context="#stay"/>
- <RegExpr attribute="Keyword" context="#stay" String="^#!.*" />
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <DetectChar attribute="String" context="String2" char="'"/>
- <DetectChar attribute="String Char" context="String" char="`"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*"/>
- <Detect2Chars attribute="Pattern" context="Pattern2" char="s" char1="/" />
- <DetectChar attribute="Pattern" context="Pattern" char="/" />
- <AnyChar attribute="Symbol" context="#stay" String="!%&amp;()+,-&lt;=&gt;?[]^{|}~"/>
- <RegExpr attribute="Decimal" context="#stay" String="\$[0-9]+" />
- <RegExpr attribute="Data Type" context="#stay" String="\$\#?[a-zA-Z_]+[a-zA-Z0-9_]*" />
- <RegExpr attribute="Pattern" context="#stay" String="\s+\:" />
- <DetectChar attribute="Comment" context="Commentar 1" char="#" />
- </context>
-
- <context attribute="String" lineEndContext="#stay" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- <RegExpr attribute="Decimal" context="#stay" String="\$[0-9]+" />
- <RegExpr attribute="Data Type" context="#stay" String="\$[a-zA-Z_]*[a-zA-Z0-9_]*" />
- </context>
-
- <context attribute="Comment" lineEndContext="#pop" name="Commentar 1"/>
-
- <context attribute="Comment" lineEndContext="#stay" name="Commentar 2">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/"/>
- </context>
-
- <context attribute="Pattern" lineEndContext="#stay" name="Pattern">
- <RegExpr attribute="String Char" context="#stay" String="\\[\/\[\]dDwWsSnrtfb0\$@]?" />
- <RegExpr attribute="String Char" context="#stay" String="\^[\/\[\]]?" />
- <DetectChar attribute="Pattern" context="#pop" char="/" />
- </context>
-
- <context attribute="Pattern" lineEndContext="#stay" name="Pattern2">
- <RegExpr attribute="String Char" context="#stay" String="\\[\/\[\]dDwWsSnrtfb0\$@]?" />
- <RegExpr attribute="String Char" context="#stay" String="\^[\/\[\]]?" />
- <RegExpr attribute="Pattern" context="Pattern3" String="\/" />
- </context>
-
- <context attribute="Pattern" lineEndContext="#stay" name="Pattern3">
- <RegExpr attribute="String Char" context="#stay" String="\\[\/\[\]dDwWsSnrtfb0\$@]?" />
- <RegExpr attribute="String Char" context="#stay" String="\^[\/\[\]]?" />
- <RegExpr attribute="Pattern" context="#pop#pop" String="\/g?" />
- </context>
-
- <context attribute="String Char" lineEndContext="#stay" name="Something">
- <DetectChar attribute="String Char" context="#pop" char="`"/>
- </context>
-
- <context attribute="String" lineEndContext="#stay" name="String2">
- <LineContinue attribute="String" context="#stay"/>
- <Detect2Chars attribute="String Char" context="#stay" char="\" char1="'"/>
- <DetectChar attribute="String" context="#pop" char="'"/>
- </context>
-
- <context attribute="String" lineEndContext="#pop" name="PerlOneLiner">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <HlCOct attribute="Octal" context="#stay"/>
- <HlCHex attribute="Hex" context="#stay"/>
- <Int attribute="Decimal" context="#stay" />
- <HlCChar attribute="Char" context="#stay"/>
- <RegExpr attribute="Keyword" context="#stay" String="^#!.*" />
- <RegExpr attribute="String" context="#stay" String="&quot;[^&quot;]*&quot;"/>
- <RegExpr attribute="String" context="#stay" String="'[^']*'"/>
- <DetectChar attribute="String Char" context="Something" char="`"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*"/>
- <Detect2Chars attribute="Pattern" context="Pattern2" char="s" char1="/" />
- <AnyChar attribute="Symbol" context="#stay" String="!%&amp;()+,-&lt;=&gt;?[]^{|}~"/>
- <RegExpr attribute="Decimal" context="#stay" String="\$[0-9]+" />
- <RegExpr attribute="Data Type" context="#stay" String="\$\#?[a-zA-Z_]+[a-zA-Z0-9_]*" />
- <RegExpr attribute="Pattern" context="#stay" String="\s+\:" />
- <RegExpr attribute="Comment" context="#stay" String="\#.*" />
- </context>
-
- <context attribute="Comment" lineEndContext="#stay" name="Documentation">
- <StringDetect attribute="Comment" context="#pop" String="&lt;/%doc&gt;" insensitive="FALSE" />
- </context>
-
- <context attribute="Mason Method" lineEndContext="#stay" name="MethodCall">
- <Detect2Chars attribute="Mason Method" context="#pop" char="&amp;" char1="&gt;" />
- </context>
- </contexts>
-
- <itemDatas>
- <itemData name="normal" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Pattern" defStyleNum="dsOthers"/>
- <itemData name="Mason Tag" defStyleNum="dsKeyword"/>
- <itemData name="Mason Method" defStyleNum="dsKeyword"/>
- <itemData name="HTML" defStyleNum="dsString"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="#" />
- <comment name="multiLine" start="&lt;%doc&gt;" end="&lt;%doc&gt;"/>
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Matlab M-File" version="1.06" kateversion="2.1" section="Sources" extensions="*.m;*.M" mimetype="text/mfile">
- <highlighting>
- <list name="keywords">
- <item> break </item>
- <item> end </item>
- <item> case </item>
- <item> continue </item>
- <item> do </item>
- <item> else </item>
- <item> elseif </item>
- <item> for </item>
- <item> goto </item>
- <item> if </item>
- <item> return </item>
- <item> struct </item>
- <item> switch </item>
- <item> while </item>
- <item> function </item>
- <item> otherwise </item>
- <item> try </item>
- <item> catch </item>
- </list>
- <list name="types">
- <item> global </item>
- <item> persistent </item>
- <item> double </item>
- </list>
- <list name="commands">
- <item> abs </item>
- <item> acos </item>
- <item> acot </item>
- <item> acsc </item>
- <item> angle </item>
- <item> asec </item>
- <item> asin </item>
- <item> atan </item>
- <item> bar </item>
- <item> ceil </item>
- <item> close </item>
- <item> cond </item>
- <item> condeig </item>
- <item> complex </item>
- <item> conj </item>
- <item> cos </item>
- <item> cot </item>
- <item> csc </item>
- <item> det </item>
- <item> disp </item>
- <item> display </item>
- <item> exp </item>
- <item> figure </item>
- <item> filter </item>
- <item> fix </item>
- <item> fft </item>
- <item> floor </item>
- <item> fprintf </item>
- <item> freqz </item>
- <item> get </item>
- <item> gcd </item>
- <item> grid </item>
- <item> imag </item>
- <item> impz </item>
- <item> isempty </item>
- <item> isequal </item>
- <item> islogical </item>
- <item> isnumeric </item>
- <item> isprime </item>
- <item> isreal </item>
- <item> issparse </item>
- <item> lcm </item>
- <item> length </item>
- <item> linspace </item>
- <item> load </item>
- <item> log </item>
- <item> log2 </item>
- <item> log10 </item>
- <item> logspace </item>
- <item> mesh </item>
- <item> mod </item>
- <item> ndims </item>
- <item> nextpow2 </item>
- <item> norm </item>
- <item> normest </item>
- <item> null </item>
- <item> numel </item>
- <item> open </item>
- <item> orth </item>
- <item> perms </item>
- <item> primes </item>
- <item> poly </item>
- <item> pow2 </item>
- <item> plot </item>
- <item> rank </item>
- <item> rcond </item>
- <item> real </item>
- <item> reallog </item>
- <item> realpow </item>
- <item> realsqrt </item>
- <item> rem </item>
- <item> roots </item>
- <item> rref </item>
- <item> save </item>
- <item> scatter </item>
- <item> sec </item>
- <item> semilogx </item>
- <item> semilogy </item>
- <item> set </item>
- <item> sin </item>
- <item> sign </item>
- <item> size </item>
- <item> sprintf </item>
- <item> sqrt </item>
- <item> stairs </item>
- <item> stem </item>
- <item> subplot </item>
- <item> subspace </item>
- <item> tan </item>
- <item> title </item>
- <item> trace </item>
- <item> waitforbuttonpress </item>
- <item> zoom </item>
- <item> zplane </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal Text">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <keyword attribute="Command" context="#stay" String="commands"/>
- <Float attribute="Float" context="#stay"/>
- <HlCOct attribute="Float" context="#stay"/>
- <HlCHex attribute="Float" context="#stay"/>
- <Int attribute="Decimal" context="#stay" />
- <RegExpr String="(\b([\w][\d\w]*)*[\s]*|[.])(?=([([{].*[])}])?['])" minimal="1" attribute="Transpose" context="Transpose"/>
- <RegExpr String="[([{](?=[^'([{]*[])}]['])" minimal="1" attribute="Normal Text" context="Transpose"/>
- <RegExpr String= "%.*$" attribute="Comment" context="#stay"/>
- <DetectChar attribute="String" context="String" char="&apos;"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&apos;"/>
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Transpose">
- <Float attribute="Float" context="#stay"/>
- <HlCOct attribute="Float" context="#stay"/>
- <HlCHex attribute="Float" context="#stay"/>
- <Int attribute="Decimal" context="#stay" />
- <RegExpr attribute="String" context="#stay" minimal="1" String="['][^']*['](?=[])}]['])"/>
- <DetectChar attribute="Normal Text" context="#pop" char="&apos;"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword" color="#1414e4" selColor="#ffd60b"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Transpose" defStyleNum="dsNormal" color="#800080"/>
- <itemData name="String" defStyleNum="dsString" color="#ff0000" selColor="#ff0000"/>
- <itemData name="Comment" defStyleNum="dsComment" color="#2b7805" selColor="#945ca4"/>
- <itemData name="Command" defStyleNum="dsCommand" color="#000000" selColor="#ffffff" bold="1"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="% " />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Modula-2" version="1.02" kateversion="2.1" section="Sources" extensions="*.mod;*.def;*.mi;*.md" mimetype="text/x-modula-2">
- <highlighting>
- <list name="directives">
- <item> ASSEMBLER </item>
- <item> ALLOCATE </item>
- <item> DEALLOCATE </item>
- <item> SIZE </item>
- <item> Write </item>
- <item> WriteString </item>
- <item> WriteCard </item>
- <item> WriteLn </item>
- <item> WriteBf </item>
- <item> WriteInt </item>
- <item> WriteReal </item>
- <item> WriteLongReal </item>
- <item> Read </item>
- <item> ReadString </item>
- <item> ReadCard </item>
- <item> ReadInt </item>
- <item> ReadReal </item>
- <item> ReadLongReal </item>
- <item> Open </item>
- <item> Close </item>
- <item> OpenInput </item>
- <item> OpenOutput </item>
- <item> Accessible </item>
- <item> Erase </item>
- <item> EOF </item>
- <item> Done </item>
- <item> EmptyString </item>
- <item> Assign </item>
- <item> Append </item>
- <item> Length </item>
- <item> StrEq </item>
- <item> Copy </item>
- <item> Concat </item>
- <item> pos </item>
- <item> Delete </item>
- <item> Insert </item>
- <item> compare </item>
- <item> CAPS </item>
- <item> PutBf </item>
- <item> GetArgs </item>
- <item> GetEnv </item>
- <item> ResetClock </item>
- <item> UserTime </item>
- <item> SystemTime </item>
- <item> GetChar </item>
- <item> GetInt </item>
- <item> GetCard </item>
- <item> GetString </item>
- <item> GetReal </item>
- <item> GetLongReal </item>
- <item> PutChar </item>
- <item> PutInt </item>
- <item> PutCard </item>
- <item> PutString </item>
- <item> PutReal </item>
- <item> PutLongReal </item>
- <item> PutLn </item>
- </list>
- <list name="keywords">
- <item> AND </item>
- <item> ARRAY </item>
- <item> ASM </item>
- <item> BEGIN </item>
- <item> CASE </item>
- <item> CONST </item>
- <item> DIV </item>
- <item> DO </item>
- <item> ELSE </item>
- <item> ELSIF </item>
- <item> END </item>
- <item> FOR </item>
- <item> IF </item>
- <item> IMPLEMENTATION </item>
- <item> IN </item>
- <item> SET </item>
- <item> INCL </item>
- <item> EXCL </item>
- <item> ABS </item>
- <item> BITSET </item>
- <item> CAP </item>
- <item> CHR </item>
- <item> DEC </item>
- <item> HALT </item>
- <item> HIGH </item>
- <item> INC </item>
- <item> MAX </item>
- <item> MIN </item>
- <item> ODD </item>
- <item> ORD </item>
- <item> PROC </item>
- <item> TRUNC </item>
- <item> VAL </item>
- <item> MOD </item>
- <item> NIL </item>
- <item> NOT </item>
- <item> OF </item>
- <item> OR </item>
- <item> PROCEDURE </item>
- <item> MODULE </item>
- <item> DEFINITION </item>
- <item> RECORD </item>
- <item> REPEAT </item>
- <item> THEN </item>
- <item> TO </item>
- <item> TYPE </item>
- <item> UNTIL </item>
- <item> LOOP </item>
- <item> VAR </item>
- <item> WHILE </item>
- <item> WITH </item>
- <item> EXIT </item>
- <item> FALSE </item>
- <item> TRUE </item>
- <item> BY </item>
- <item> FROM </item>
- <item> IMPORT </item>
- <item> EXPORT </item>
- <item> QUALIFIED </item>
- <item> RETURN </item>
- <item> NEWPROCESS </item>
- <item> TRANSFER </item>
- <item> IOTRANSFER </item>
- <item> FOREIGN </item>
- </list>
- <list name="types">
- <item> INTEGER </item>
- <item> CARDINAL </item>
- <item> SHORTINT </item>
- <item> SHORTCARD </item>
- <item> LONGINT </item>
- <item> LONGREAL </item>
- <item> CHAR </item>
- <item> BOOLEAN </item>
- <item> POINTER </item>
- <item> ADDRESS </item>
- <item> ADR </item>
- <item> REAL </item>
- <item> File </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Directive" context="#stay" String="directives"/>
- <keyword attribute="Type" context="#stay" String="types"/>
- <Float attribute="Number" context="#stay"/>
- <Int attribute="Number" context="#stay"/>
- <DetectChar attribute="String" context="String1" char="&quot;" />
- <DetectChar attribute="String" context="String2" char="'" />
- <StringDetect attribute="Directive" context="Prep1" String="(*$"/>
- <Detect2Chars attribute="Comment" context="Comment2" char="(" char1="*"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String1">
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String2">
- <DetectChar attribute="String" context="#pop" char="'" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Comment2">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1=")"/>
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Comment3" />
- <context attribute="Directive" lineEndContext="#stay" name="Prep1">
- <StringDetect attribute="Directive" context="Prep1" String="$*)"/>
- </context>
-
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="Type" defStyleNum="dsDataType"/>
- <itemData name="Number" defStyleNum="dsDecVal" />
- <itemData name="String" defStyleNum="dsString" />
- <itemData name="Directive" defStyleNum="dsOthers" />
- <itemData name="Comment" defStyleNum="dsComment" />
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="1" />
- <comments>
- <comment name="multiLine" start="(*" end="*)" />
- </comments>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Objective-C" version="1.03" kateversion="2.1" section="Sources" extensions="*.m;*.h" mimetype="text/x-objc-src;text/x-c-hdr">
- <highlighting>
- <list name="keywords">
- <item> break </item>
- <item> case </item>
- <item> continue </item>
- <item> default </item>
- <item> do </item>
- <item> else </item>
- <item> enum </item>
- <item> extern </item>
- <item> for </item>
- <item> goto </item>
- <item> if </item>
- <item> return </item>
- <item> sizeof </item>
- <item> struct </item>
- <item> switch </item>
- <item> typedef </item>
- <item> union </item>
- <item> while </item>
- <item> @class </item>
- <item> @defs </item>
- <item> @encode </item>
- <item> @end </item>
- <item> @implementation </item>
- <item> @interface </item>
- <item> @private </item>
- <item> @protected </item>
- <item> @protocol </item>
- <item> @public </item>
- <item> @selector </item>
- <item> self </item>
- <item> super </item>
- </list>
- <list name="types">
- <item> auto </item>
- <item> char </item>
- <item> const </item>
- <item> double </item>
- <item> float </item>
- <item> int </item>
- <item> long </item>
- <item> register </item>
- <item> short </item>
- <item> signed </item>
- <item> static </item>
- <item> unsigned </item>
- <item> void </item>
- <item> volatile </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Default">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <Float attribute="Float" context="#stay">
- <AnyChar String="fF" attribute="Float" context="#stay"/>
- </Float>
- <HlCOct attribute="Octal" context="#stay"/>
- <HlCHex attribute="Hex" context="#stay"/>
- <Int attribute="Decimal" context="#stay" >
- <StringDetect attribute="Decimal" context="#stay" String="ULL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LUL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LLU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="UL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="U" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="L" insensitive="TRUE"/>
- </Int>
- <HlCChar attribute="Char" context="#stay"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="SingleLineComment" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="MultiLineComment" char="/" char1="*"/>
- <AnyChar attribute="Symbol" context="#stay" String=":!%&amp;()+,-/.*&lt;=&gt;?[]|~^&#59;"/>
- <RegExpr attribute="Preprocessor" context="Preprocessor" String="^#"/>
- <Detect2Chars attribute="String" context="String" char="@" char1="&quot;" />
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="SingleLineComment"/>
- <context attribute="Comment" lineEndContext="#stay" name="MultiLineComment">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/"/>
- </context>
- <context attribute="Preprocessor" lineEndContext="Default" name="Preprocessor">
- <LineContinue attribute="Preprocessor" context="#stay"/>
- <RangeDetect attribute="Prep. Lib" context="#stay" char="&quot;" char1="&quot;"/>
- <RangeDetect attribute="Prep. Lib" context="#stay" char="&lt;" char1="&gt;"/>
- <Detect2Chars attribute="Comment" context="SingleLineComment" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="MultiLineCommentPrep" char="/" char1="*"/>
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="MultiLineCommentPrep">
- <Detect2Chars attribute="Comment" context="#pop#pop" char="*" char1="/"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- <itemData name="Prep. Lib" defStyleNum="dsOthers"/> <!--,Qt::darkYellow,Qt::yellow,false,false)); -->
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Pascal" version="1.08" kateversion="2.1" section="Sources" extensions="*.pp;*.pas;*.p" mimetype="text/x-pascal">
- <highlighting>
- <list name="keywords">
- <item> and </item>
- <item> array </item>
- <item> asm </item>
- <item> case </item>
- <item> const </item>
- <item> div </item>
- <item> do </item>
- <item> downto </item>
- <item> else </item>
- <item> file </item>
- <item> for </item>
- <item> function </item>
- <item> goto </item>
- <item> if </item>
- <item> in </item>
- <item> label </item>
- <item> mod </item>
- <item> nil </item>
- <item> not </item>
- <item> of </item>
- <item> operator </item>
- <item> or </item>
- <item> packed </item>
- <item> procedure </item>
- <item> program </item>
- <item> record </item>
- <item> repeat </item>
- <item> set </item>
- <item> then </item>
- <item> to </item>
- <item> type </item>
- <item> unit </item>
- <item> until </item>
- <item> uses </item>
- <item> var </item>
- <item> while </item>
- <item> with </item>
- <item> xor </item>
-
-
- <item> at </item>
- <item> automated </item>
- <item> break </item>
- <item> continue </item>
- <item> dispinterface </item>
- <item> dispose </item>
- <item> exit </item>
- <item> false </item>
- <item> finalization </item>
- <item> initialization </item>
- <item> library </item>
- <item> new </item>
- <item> published </item>
- <item> resourcestring </item>
- <item> self </item>
- <item> true </item>
- </list>
- <list name="ISO/Delphi Extended">
- <item> as </item>
- <item> bindable </item>
- <item> constructor </item>
- <item> destructor </item>
- <item> except </item>
- <item> export </item>
- <item> finally </item>
- <item> import </item>
- <item> implementation </item>
- <item> inherited </item>
- <item> inline </item>
- <item> interface </item>
- <item> is </item>
- <item> module </item>
- <item> on </item>
- <item> only </item>
- <item> otherwise </item>
- <item> private </item>
- <item> property </item>
- <item> protected </item>
- <item> public </item>
- <item> qualified </item>
- <item> raise </item>
- <item> restricted </item>
- <item> shl </item>
- <item> shr </item>
- <item> threadvar </item>
- <item> try </item>
- </list>
- <list name="types">
- <item> Integer </item>
- <item> Cardinal </item>
- <item> ShortInt </item>
- <item> SmallInt </item>
- <item> LongInt </item>
- <item> Int64 </item>
- <item> Byte </item>
- <item> Word </item>
- <item> LongWord </item>
- <item> Char </item>
- <item> AnsiChar </item>
- <item> WideChar </item>
- <item> Boolean </item>
- <item> ByteBool </item>
- <item> WordBool </item>
- <item> LongBool </item>
- <item> Single </item>
- <item> Double </item>
- <item> Extended </item>
- <item> Comp </item>
- <item> Currency </item>
- <item> Real </item>
- <item> Real48 </item>
- <item> String </item>
- <item> ShortString </item>
- <item> AnsiString </item>
- <item> WideString </item>
- <item> Pointer </item>
- <item> Variant</item>
- <item> File </item>
- <item> Text </item>
- </list>
- <list name="attention">
- <item> FIXME </item>
- <item> TODO </item>
- <item> ### </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <RegExpr attribute="Keyword" context="#stay" String="\b(begin|case|record)([\s]|$)" insensitive="true" beginRegion="Region1"/>
- <RegExpr attribute="ISO/Delphi Extended" context="#stay" String="\b(try|class|object)([\s]|$)" insensitive="true" beginRegion="Region1"/>
- <RegExpr attribute="Keyword" context="#stay" String="\bend([.;\s]|$)" insensitive="true" endRegion="Region1"/>
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="ISO/Delphi Extended" context="#stay" String="ISO/Delphi Extended"/>
- <keyword attribute="Type" context="#stay" String="types"/>
- <Float attribute="Number" context="#stay"/>
- <Int attribute="Number" context="#stay"/>
- <DetectChar attribute="String" context="String" char="&apos;" />
- <StringDetect attribute="Directive" context="Prep1" String="(*$"/>
- <Detect2Chars attribute="Directive" context="Prep2" char="{" char1="$"/>
- <DetectChar attribute="Comment" context="Comment1" char="{"/>
- <Detect2Chars attribute="Comment" context="Comment2" char="(" char1="*"/>
- <Detect2Chars attribute="Comment" context="Comment3" char="/" char1="/"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <DetectChar attribute="String" context="#pop" char="&apos;"/>
- </context>
- <context attribute="Directive" lineEndContext="#pop" name="Prep1">
- <Detect2Chars attribute="Directive" context="#pop" char="*" char1=")"/>
- </context>
- <context attribute="Directive" lineEndContext="#pop" name="Prep2">
- <DetectChar attribute="Directive" context="#pop" char="}"/>
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Comment1">
- <keyword attribute="Number" context="#stay" String="attention" />
- <DetectChar attribute="Comment" context="#pop" char="}"/>
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Comment2">
- <keyword attribute="Number" context="#stay" String="attention" />
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1=")"/>
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Comment3">
- <keyword attribute="Number" context="#stay" String="attention" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="ISO/Delphi Extended" defStyleNum="dsKeyword" color="#000080" />
- <itemData name="Type" defStyleNum="dsDataType"/>
- <itemData name="Number" defStyleNum="dsDecVal" />
- <itemData name="String" defStyleNum="dsString" />
- <itemData name="Directive" defStyleNum="dsOthers" />
- <itemData name="Comment" defStyleNum="dsComment" />
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="0" />
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="{" end="}" />
- </comments>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!--
- This file is part of the KDE project
- Copyright (C) 2001, 2002, 2003 Anders Lund <anders@alweb.dk>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License version 2 as published by the Free Software Foundation.
-
- This 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- *** NOTICE ***
- This file is maintained by Anders Lund <anders@alweb.dk>
- Please do not commit changes without checking with me.
-
- *** TODO ***
- s/// - Either make a special case, or better, enable saving data in contexts,
- so any delimiter can be handled correctly!
-
- The variable detection is not entirely left if there is a variable in a key.
- Samples:
- $hask{ $key }{ value }; ## comments are not detected
-
- HERE document delimiters - requires support for saving data in contexts.
--->
-<language name="Perl" version="1.10" kateversion="2.2" section="Scripts"
- extensions="*.pl;*.pm" mimetype="application/x-perl;text/x-perl"
- author="Anders Lund (anders@alweb.dk)" license="LGPL">
- <highlighting>
- <list name="keywords">
- <item> if </item>
- <item> unless </item>
- <item> else </item>
- <item> elsif </item>
- <item> while </item>
- <item> until </item>
- <item> for </item>
- <item> each </item>
- <item> foreach </item>
- <item> next </item>
- <item> last </item>
- <item> break </item>
- <item> continue </item>
- <item> return </item>
- <item> use </item>
- <item> no </item>
- <item> require </item>
- <item> my </item>
- <item> our </item>
- <item> local </item>
- <item> BEGIN </item>
- <item> END </item>
- <item>require</item>
- <item> package </item>
- <item> sub </item>
- <item> do </item>
- <item> __END__ </item>
- <item> __DATA__ </item>
- <item> __FILE__ </item>
- <item> __LINE__ </item>
- <item> __PACKAGE__ </item>
- </list>
- <list name="operators">
- <item> = </item>
- <item> != </item>
- <item> ~= </item>
- <item> += </item>
- <item> -= </item>
- <item> *= </item>
- <item> /= </item>
- <item> **= </item>
- <item> |= </item>
- <item> ||= </item>
- <item> &amp;= </item>
- <item> &amp;&amp;= </item>
- <item> ?= </item>
- <item> + </item>
- <item> - </item>
- <item> * </item>
- <!-- <item> / </item>//-->
- <item> % </item>
- <item> || </item>
- <item> &amp;&amp; </item>
- <item> | </item>
- <item> &amp; </item>
- <item> &lt; </item>
- <item> &lt;&lt; </item>
- <item> &gt; </item>
- <item> &gt;&gt; </item>
- <item> ^ </item>
- <item> -&gt; </item>
- <item> =&gt; </item>
- <item> . </item>
- <item> , </item>
- <item> ; </item>
- <item> :: </item>
- <item> \ </item>
- <item> and </item>
- <item> or </item>
- <item> not </item>
- <item> eq </item>
- <item> ne </item>
- </list>
- <list name="functions">
- <item>abs</item>
- <item>accept</item>
- <item>alarm</item>
- <item>atan2</item>
- <item>bind</item>
- <item>binmode</item>
- <item>bless</item>
- <item>caller</item>
- <item>chdir</item>
- <item>chmod</item>
- <item>chomp</item>
- <item>chop</item>
- <item>chown</item>
- <item>chr</item>
- <item>chroot</item>
- <item>close</item>
- <item>closedir</item>
- <item>connect</item>
- <item>cos</item>
- <item>crypt</item>
- <item>dbmclose</item>
- <item>dbmopen</item>
- <item>defined</item>
- <item>delete</item>
- <item>die</item>
- <item>dump</item>
- <item>endgrent</item>
- <item>endhostent</item>
- <item>endnetent</item>
- <item>endprotoent</item>
- <item>endpwent</item>
- <item>endservent</item>
- <item>eof</item>
- <item>eval</item>
- <item>exec</item>
- <item>exists</item>
- <item>exit</item>
- <item>exp</item>
- <item>fcntl</item>
- <item>fileno</item>
- <item>flock</item>
- <item>fork</item>
- <item>format</item>
- <item>formline</item>
- <item>getc</item>
- <item>getgrent</item>
- <item>getgrgid</item>
- <item>getgrnam</item>
- <item>gethostbyaddr</item>
- <item>gethostbyname</item>
- <item>gethostent</item>
- <item>getlogin</item>
- <item>getnetbyaddr</item>
- <item>getnetbyname</item>
- <item>getnetent</item>
- <item>getpeername</item>
- <item>getpgrp</item>
- <item>getppid</item>
- <item>getpriority</item>
- <item>getprotobyname</item>
- <item>getprotobynumber</item>
- <item>getprotoent</item>
- <item>getpwent</item>
- <item>getpwnam</item>
- <item>getpwuid</item>
- <item>getservbyname</item>
- <item>getservbyport</item>
- <item>getservent</item>
- <item>getsockname</item>
- <item>getsockopt</item>
- <item>glob</item>
- <item>gmtime</item>
- <item>goto</item>
- <item>grep</item>
- <item>hex</item>
- <item>import</item>
- <item>index</item>
- <item>int</item>
- <item>ioctl</item>
- <item>join</item>
- <item>keys</item>
- <item>kill</item>
- <item>last</item>
- <item>lc</item>
- <item>lcfirst</item>
- <item>length</item>
- <item>link</item>
- <item>listen</item>
- <item>localtime</item>
- <item>lock</item>
- <item>log</item>
- <item>lstat</item>
- <item>map</item>
- <item>mkdir</item>
- <item>msgctl</item>
- <item>msgget</item>
- <item>msgrcv</item>
- <item>msgsnd</item>
- <item>oct</item>
- <item>open</item>
- <item>opendir</item>
- <item>ord</item>
- <item>pack</item>
- <item>package</item>
- <item>pipe</item>
- <item>pop</item>
- <item>pos</item>
- <item>print</item>
- <item>printf</item>
- <item>prototype</item>
- <item>push</item>
- <item>quotemeta</item>
- <item>rand</item>
- <item>read</item>
- <item>readdir</item>
- <item>readline</item>
- <item>readlink</item>
- <item>recv</item>
- <item>redo</item>
- <item>ref</item>
- <item>rename</item>
- <item>reset</item>
- <item>return</item>
- <item>reverse</item>
- <item>rewinddir</item>
- <item>rindex</item>
- <item>rmdir</item>
- <item>scalar</item>
- <item>seek</item>
- <item>seekdir</item>
- <item>select</item>
- <item>semctl</item>
- <item>semget</item>
- <item>semop</item>
- <item>send</item>
- <item>setgrent</item>
- <item>sethostent</item>
- <item>setnetent</item>
- <item>setpgrp</item>
- <item>setpriority</item>
- <item>setprotoent</item>
- <item>setpwent</item>
- <item>setservent</item>
- <item>setsockopt</item>
- <item>shift</item>
- <item>shmctl</item>
- <item>shmget</item>
- <item>shmread</item>
- <item>shmwrite</item>
- <item>shutdown</item>
- <item>sin</item>
- <item>sleep</item>
- <item>socket</item>
- <item>socketpair</item>
- <item>sort</item>
- <item>splice</item>
- <item>split</item>
- <item>sprintf</item>
- <item>sqrt</item>
- <item>srand</item>
- <item>stat</item>
- <item>study</item>
- <item>sub</item>
- <item>substr</item>
- <item>symlink</item>
- <item>syscall</item>
- <item>sysread</item>
- <item>sysseek</item>
- <item>system</item>
- <item>syswrite</item>
- <item>tell</item>
- <item>telldir</item>
- <item>tie</item>
- <item>time</item>
- <item>times</item>
- <item>truncate</item>
- <item>uc</item>
- <item>ucfirst</item>
- <item>umask</item>
- <item>undef</item>
- <item>unlink</item>
- <item>unpack</item>
- <item>unshift</item>
- <item>untie</item>
- <item>utime</item>
- <item>values</item>
- <item>vec</item>
- <item>wait</item>
- <item>waitpid</item>
- <item>wantarray</item>
- <item>warn</item>
- <item>write</item>
- </list>
- <list name="pragmas">
- <item>strict</item>
- <item>english</item>
- <item>warnings</item>
- <item>vars</item>
- <item>subs</item>
- <item>utf8</item>
- <item>sigtrap</item>
- <item>locale</item>
- <item>open</item>
- <item>less</item>
- <item>integer</item>
- <item>filetest</item>
- <item>constant</item>
- <item>bytes</item>
- <item>diagnostics</item>
- </list>
- <contexts>
- <context name="normal" attribute="Normal Text" lineEndContext="#stay">
- <RegExpr attribute="Keyword" context="#stay" String="^#!\/.*" />
- <RegExpr attribute="Keyword" context="data_handle" String="^__DATA__" />
- <RegExpr attribute="Keyword" context="#stay" String="^__END__" />
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Operator" context="#stay" String="operators" />
- <keyword attribute="Function" context="#stay" String="functions" />
- <keyword attribute="Pragma" context="#stay" String="pragmas" />
- <RegExpr attribute="Comment" context="comment" String="#" />
- <RegExpr attribute="Pod" context="pod" String="^\=(?:head[1-6]|over|back|item|for|begin|end|pod)\s*.*" beginRegion="POD"/>
- <RegExpr attribute="Keyword" context="sub_name_def" String="\s*sub\s+" />
-
- <HlCOct attribute="Octal" context="slash_safe_escape" />
- <HlCHex attribute="Hex" context="slash_safe_escape" />
- <Float attribute="Float" context="slash_safe_escape" />
- <Int attribute="Decimal" context="slash_safe_escape" />
-
- <RegExpr attribute="Normal Text" context="#stay" String="\\[&quot;']" />
- <Detect2Chars attribute="Normal Text" context="#stay" char="&amp;" char1="'" />
- <DetectChar attribute="String (interpolated)" context="ip_string" char="&quot;"/>
- <DetectChar attribute="String" context="string" char="'"/>
- <DetectChar attribute="Operator" context="Backticked" char="`" />
- <AnyChar attribute="Operator" context="#stay" String="&amp;\" />
-
- <RegExpr attribute="Special Variable" context="var_detect" String="\$[0-9]+" />
- <RegExpr attribute="Special Variable" context="var_detect" String="[@\$](?:[\+\-_]\B|ARGV\b|INC\b)" />
- <RegExpr attribute="Special Variable" context="var_detect" String="[%\$](?:INC\b|ENV\b|SIG\b)" />
- <RegExpr attribute="Data Type" context="var_detect" String="\$\$[\$\w_]" />
- <RegExpr attribute="Data Type" context="var_detect" String="\$[#_][\w_]" />
- <RegExpr attribute="Special Variable" context="slash_safe_escape" String="\$[^a-zA-Z0-9\s{][A-Z]?" />
- <RegExpr attribute="Data Type" context="var_detect" String="[\$@%]\{[\w_]+\}" />
- <RegExpr attribute="Data Type" context="var_detect" String="[\$@%]" />
- <RegExpr attribute="Data Type" context="var_detect" String="\*[a-zA-Z_]+" />
-
- <RegExpr attribute="Keyword" context="#stay" String="&lt;[A-Z0-9_]+&gt;" />
- <RegExpr attribute="Keyword" context="#stay" String="\s*&lt;&lt;\s*[&quot;']?[A-Z0-9_\-]+[&quot;']?" />
- <RegExpr attribute="Normal Text" context="#stay" String="\s*[)}]\s*/" />
- <RegExpr attribute="Normal Text" context="sub_name_def" String="\w+::" />
- <RegExpr attribute="Normal Text" context="#stay" String="\w+[=]" />
-
- <RegExpr attribute="String (interpolated)" context="ip_string_2" String="q[qx]\(" />
- <RegExpr attribute="String (interpolated)" context="ip_string_3" String="q[qx]\{" />
- <RegExpr attribute="String (interpolated)" context="ip_string_4" String="q[qx]\[" />
- <RegExpr attribute="String (interpolated)" context="ip_string_5" String="q[qx]&lt;" />
- <RegExpr attribute="String (interpolated)" context="#stay" String="q[qx]([^a-zA-Z0-9_\s[\]{}()]).*\1" minimal="true" />
-
- <Detect2Chars attribute="String" context="string_2" char="q" char1="(" />
- <Detect2Chars attribute="String" context="string_3" char="q" char1="{" />
- <Detect2Chars attribute="String" context="string_4" char="q" char1="[" />
- <Detect2Chars attribute="String" context="string_5" char="q" char1="&lt;" />
- <RegExpr attribute="String" context="#stay" String="q([^a-zA-Z0-9_\s[\]{}()]).+\1" />
-
- <StringDetect attribute="Normal Text" context="quote_word" String="qw/" />
-
- <Detect2Chars attribute="Pattern" context="subst_curlybrace_pattern" char="s" char1="{" />
- <Detect2Chars attribute="Pattern" context="subst_paren_pattern" char="s" char1="(" />
- <Detect2Chars attribute="Pattern" context="subst_bracket_pattern" char="s" char1="[" />
- <Detect2Chars attribute="Pattern" context="subst_slash_pattern" char="s" char1="/" />
-
- <RegExpr attribute="Pattern" context="#stay" String="(?:s|tr|y)\([^)]*\)\s*\([^)]*\)" />
- <RegExpr attribute="Pattern" context="#stay" String="(?:s|tr|y)\{[^}]*\}\s*\{[^}]*\}" />
- <RegExpr attribute="Pattern" context="#stay" String="(?:s|tr|y)\[[^}]*\]\s*\[[^\]]*\]" />
- <RegExpr attribute="Pattern" context="#stay" String="(?:s|tr|y)([^a-zA-Z0-9_\s[\]{}()]).*\1.*\1" minimal="true"/>
-
- <RegExpr attribute="Normal Text" context="#stay" String="[\w_]{3,}[[{:\-.;,]" />
- <RegExpr attribute="Normal Text" context="#stay" String="[\w_]([mqsy]|q[rx])\(" />
-
- <RegExpr attribute="Pattern" context="pattern_slash" String="(?:m|qr)\/" />
- <RegExpr attribute="Pattern" context="#stay" String="(?:m|q[rx])\([^)]*\)" />
- <RegExpr attribute="Pattern" context="#stay" String="(?:m|q[rx])\{[^}]*\}" />
- <RegExpr attribute="Pattern" context="#stay" String="(?:m|q[rx])\[[^\]]*\]" />
- <RegExpr attribute="Pattern" context="#stay" String="(?:m|q[rx])([^a-zA-Z0-9_-\s[\]{}()/]).+\1" minimal="true"/>
- <RegExpr attribute="Normal Text" context="#stay" String="[\w_]+\s*/" />
- <RegExpr attribute="Normal Text" context="#stay" String="[&lt;&gt;&quot;':]/" />
- <DetectChar attribute="Pattern" context="pattern_slash" char="/" />
- <RegExpr attribute="Operator" context="#stay" String="-[rwxoRWXOeszfdlpSbctugkTBMAC]" />
-
- <DetectChar attribute="Normal Text" context="#stay" char="{" beginRegion="Brace1" />
- <DetectChar attribute="Normal Text" context="#stay" char="}" endRegion="Brace1" />
- </context>
-
- <context name="pod" attribute="Pod" lineEndContext="#stay">
- <LineContinue attribute="Pod" context="#stay" />
- <RegExpr attribute="Pod" context="#stay" String="^\=(?:head[1-6]|over|back|item|for|begin|end|pod)\s*.*" beginRegion="POD" endRegion="POD"/>
- <RegExpr attribute="Pod" context="#pop" String="^\=cut.*$" endRegion="POD"/>
- </context>
-
- <context name="regex_pattern_internal" attribute="Pattern" lineEndContext="#stay">
- <RegExpr attribute="Comment" context="#stay" String="^\s*#.*$" />
- <RegExpr attribute="Pattern Character Class" context="#stay" String="\\[anDdSsWw]" />
- <RegExpr attribute="Pattern Internal Operator" context="#stay" String="\\[ABbEGLlNUuQdQZz]" />
- <RegExpr attribute="Special Variable" context="#stay" String="\\[\d]+" />
- <RegExpr attribute="Pattern" context="#stay" String="\\." />
- <RegExpr attribute="Data Type" context="#stay" String="[\$@]#?[a-zA-Z_]+[a-zA-Z0-9_]*" />
- <Detect2Chars attribute="Pattern Internal Operator" context="pat_ext" char="(" char1="?" />
- <DetectChar attribute="Pattern Internal Operator" context="pat_char_class" char="[" />
- <RegExpr attribute="Pattern Internal Operator" context="#stay" String="[()?^*+|]" />
- <RegExpr attribute="Pattern Internal Operator" context="#stay" String="\{[\d, ]+\}" />
- <DetectChar attribute="Pattern Internal Operator" context="#stay" char="$" />
- <RegExpr attribute="Comment" context="#stay" String="\s{3,}#.*$" />
- </context>
-
-<!-- ====== Contexts for strings ===== -->
- <context name="ipstring_internal" attribute="String (interpolated)" lineEndContext="#stay">
- <RegExpr attribute="String (interpolated)" context="#stay" String="\\[\$@%]" />
- <RegExpr attribute="Special Variable" context="#stay" String="\$[0-9]+" />
- <RegExpr attribute="Data Type" context="var_detect" String="\$+#?[a-zA-Z_]+[a-zA-Z0-9_]*" />
- <RegExpr attribute="Data Type" context="var_detect" String="[@%][\$a-zA-Z_]+[a-zA-Z0-9_]*" />
- <RegExpr attribute="String Special Character" context="#stay" String="\\[UuLlEtnaefr]" />
- </context>
- <context name="ip_string" attribute="String (interpolated)" lineEndContext="#stay">
- <LineContinue attribute="String (interpolated)" context="#stay"/>
- <Detect2Chars attribute="String" context="#stay" char="\" char1="\" />
- <Detect2Chars attribute="String (interpolated)" context="#stay" char="\" char1="&quot;" />
- <DetectChar attribute="String (interpolated)" context="#pop" char="&quot;"/>
- <IncludeRules context="ipstring_internal" />
- </context>
- <context name="string" attribute="String" lineEndContext="#stay">
- <LineContinue attribute="String" context="#stay"/>
- <Detect2Chars attribute="String" context="#stay" char="\" char1="\" />
- <Detect2Chars attribute="String" context="#stay" char="\" char1="'" />
- <DetectChar attribute="String" context="#pop" char="'" />
- </context>
- <context name="ip_string_2" attribute="String (interpolated)" lineEndContext="#stay">
- <LineContinue attribute="String (interpolated)" context="#stay" />
- <Detect2Chars attribute="String (interpolated)" context="#stay" char="\" char1="(" />
- <Detect2Chars attribute="String (interpolated)" context="#stay" char="\" char1=")" />
- <RangeDetect attribute="String (interpolated)" context="#stay" char="(" char1=")" />
- <DetectChar attribute="String (interpolated)" context="#pop" char=")" />
- <IncludeRules context="ipstring_internal" />
- </context>
- <context name="ip_string_3" attribute="String (interpolated)" lineEndContext="#stay">
- <LineContinue attribute="String (interpolated)" context="#stay" />
- <Detect2Chars attribute="String (interpolated)" context="#stay" char="\" char1="{" />
- <Detect2Chars attribute="String (interpolated)" context="#stay" char="\" char1="}" />
- <RangeDetect attribute="String (interpolated)" context="#stay" char="{" char1="}" />
- <DetectChar attribute="String (interpolated)" context="#pop" char="}" />
- <IncludeRules context="ipstring_internal" />
- </context>
- <context name="ip_string_4" attribute="String (interpolated)" lineEndContext="#stay">
- <LineContinue attribute="String (interpolated)" context="#stay" />
- <Detect2Chars attribute="String (interpolated)" context="#stay" char="\" char1="[" />
- <Detect2Chars attribute="String (interpolated)" context="#stay" char="\" char1="]" />
- <RangeDetect attribute="String (interpolated)" context="#stay" char="[" char1="]" />
- <DetectChar attribute="String (interpolated)" context="#pop" char="]" />
- <IncludeRules context="ipstring_internal" />
- </context>
- <context name="ip_string_5" attribute="String (interpolated)" lineEndContext="#stay">
- <LineContinue attribute="String (interpolated)" context="#stay" />
- <Detect2Chars attribute="String (interpolated)" context="#stay" char="\" char1="&lt;" />
- <Detect2Chars attribute="String (interpolated)" context="#stay" char="\" char1="&gt;" />
- <RangeDetect attribute="String (interpolated)" context="#stay" char="&lt;" char1="&gt;" />
- <DetectChar attribute="String (interpolated)" context="#pop" char="&gt;" />
- <IncludeRules context="ipstring_internal" />
- </context>
- <context name="string_2" attribute="String" lineEndContext="#stay">
- <LineContinue attribute="String" context="#stay" />
- <Detect2Chars attribute="String" context="#stay" char="\" char1="(" />
- <Detect2Chars attribute="String" context="#stay" char="\" char1=")" />
- <RangeDetect attribute="String" context="#stay" char="(" char1=")" />
- <DetectChar attribute="String" context="#pop" char=")" />
- </context>
- <context name="string_3" attribute="String" lineEndContext="#stay">
- <Detect2Chars attribute="String" context="#stay" char="\" char1="{" />
- <Detect2Chars attribute="String" context="#stay" char="\" char1="}" />
- <RangeDetect attribute="String" context="#stay" char="{" char1="}" />
- <LineContinue attribute="String" context="#stay" />
- <DetectChar attribute="String" context="#pop" char="}" />
- </context>
- <context name="string_4" attribute="String" lineEndContext="#stay">
- <LineContinue attribute="String" context="#stay" />
- <Detect2Chars attribute="String" context="#stay" char="\" char1="[" />
- <Detect2Chars attribute="String" context="#stay" char="\" char1="]" />
- <RangeDetect attribute="String" context="#stay" char="[" char1="]" />
- <DetectChar attribute="String" context="#pop" char="]" />
- </context>
- <context name="string_5" attribute="String" lineEndContext="#stay">
- <LineContinue attribute="String" context="#stay" />
- <Detect2Chars attribute="String" context="#stay" char="\" char1="&lt;" />
- <Detect2Chars attribute="String" context="#stay" char="\" char1="&gt;" />
- <RangeDetect attribute="String" context="#stay" char="&lt;" char1="&gt;" />
- <DetectChar attribute="String" context="#pop" char="&gt;" />
- </context>
-
-<!-- ====== contexts for s/// etc ====== -->
- <context name="subst_replace" attribute="normal text">
- <LineContinue attribute="Normal Text" context="#stay" />
- <RegExpr attribute="Normal Text" context="#stay" String="[&quot;'\]" />
- <RegExpr attribute="Comment" context="#stay" String="\s*#.*$" />
- <RegExpr attribute="Special Variable" context="#stay" String="\$[0-9]+" />
- <RegExpr attribute="Data Type" context="#stay" String="\$+#?[a-zA-Z_]+[a-zA-Z0-9_]*" />
- <RegExpr attribute="Data Type" context="#stay" String="[@%][\$a-zA-Z_]+[a-zA-Z0-9_]*" />
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Operator" context="#stay" String="operators" />
- <keyword attribute="Function" context="#stay" String="functions" />
- </context>
- <context name="subst_curlybrace_pattern" attribute="Pattern" lineEndContext="#stay">
- <LineContinue attribute="Pattern" context="#stay" />
- <RegExpr attribute="Comment" context="#stay" String="\s+#.*$" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1="{" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1="}" />
- <IncludeRules context="regex_pattern_internal" />
- <DetectChar attribute="Pattern" context="subst_curlybrace_replace" char="}" />
- </context>
- <context name="subst_curlybrace_replace" attribute="Normal Text" lineEndContext="#stay">
- <IncludeRules context="subst_replace" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1="{" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1="}" />
- <DetectChar attribute="Pattern" context="#stay" char="{" />
- <DetectChar attribute="Pattern" context="#pop#pop" char="}" />
- </context>
- <context name="subst_paren_pattern" attribute="Pattern" lineEndContext="#stay">
- <LineContinue attribute="Pattern" context="#stay" />
- <RegExpr attribute="Comment" context="#stay" String="\s+#.*$" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1="(" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1=")" />
- <IncludeRules context="regex_pattern_internal" />
- <DetectChar attribute="Pattern" context="subst_curlybrace_replace" char="}" />
- </context>
- <context name="subst_paren_replace" attribute="Normal Text" lineEndContext="#stay">
- <IncludeRules context="subst_replace" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1="(" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1=")" />
- <DetectChar attribute="Pattern" context="#stay" char="(" />
- <DetectChar attribute="Pattern" context="#pop#pop" char=")" />
- </context>
- <context name="subst_bracket_pattern" attribute="Pattern" lineEndContext="#stay">
- <LineContinue attribute="Pattern" context="#stay" />
- <RegExpr attribute="Comment" context="#stay" String="\s+#.*$" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1="[" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1="]" />
- <IncludeRules context="regex_pattern_internal" />
- <DetectChar attribute="Pattern" context="subst_curlybrace_replace" char="]" />
- </context>
- <context name="subst_bracket_replace" attribute="Normal Text" lineEndContext="#stay">
- <IncludeRules context="subst_replace" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1="[" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1="]" />
- <DetectChar attribute="Pattern" context="#stay" char="[" />
- <DetectChar attribute="Pattern" context="#pop#pop" char="]" />
- </context>
- <context name="subst_slash_pattern" attribute="Pattern" lineEndContext="#stay">
- <LineContinue attribute="Pattern" context="#stay" />
- <RegExpr attribute="Comment" context="#stay" String="\s+#.*$" />
- <IncludeRules context="regex_pattern_internal" />
- <DetectChar attribute="Pattern" context="subst_slash_replace" char="/" />
- </context>
- <context name="subst_slash_replace" attribute="Normal Text" lineEndContext="#stay">
- <IncludeRules context="subst_replace" />
- <Detect2Chars attribute="Pattern" context="#stay" char="\" char1="/" />
- <DetectChar attribute="Pattern" context="#pop#pop" char="/" />
- </context>
-
- <context name="quote_word" attribute="Normal Text" lineEndContext="#stay">
- <LineContinue attribute="Normal Text" context="#stay" />
- <Detect2Chars attribute="Normal Text" context="#stay" char="\" char1="/" />
- <DetectChar attribute="Normal Text" context="#pop" char="/" />
- <RegExpr attribute="Data Type" context="#stay" String="\$+#?[a-zA-Z_]+[a-zA-Z0-9_]*" />
- <RegExpr attribute="Data Type" context="#stay" String="[@%][\$a-zA-Z_]+[a-zA-Z0-9_]*" />
- </context>
- <context name="pattern_slash" attribute="Pattern" lineEndContext="#stay">
- <RegExpr attribute="Comment" context="#stay" String="^\s*#.*$" />
- <LineContinue attribute="Pattern" context="#stay" />
- <IncludeRules context="regex_pattern_internal" />
- <DetectChar attribute="Pattern" context="#pop" char="/" />
- </context>
-
-<!-- ====== ====== -->
- <context name="data_handle" attribute="Data" lineEndContext="#stay">
- <LineContinue attribute="Data" context="#stay"/>
- <RegExpr attribute="Pod" context="pod" String="^\=(?:head[1-6]|over|back|item|for|begin|end|pod)\s*.*"/>
- <RegExpr attribute="Keyword" context="normal" String="^__END__" />
- </context>
- <context name="end_handle" attribute="Nothing" lineEndContext="#stay">
- <LineContinue attribute="Nothing" context="#stay" />
- <RegExpr attribute="Pod" context="pod" String="^\=(?:head[1-6]|over|back|item|for|begin|end|pod)\s*.*"/>
- <RegExpr attribute="Keyword" context="data_handle" String="^__DATA__" />
- </context>
- <context name="var_detect" attribute="Normal Text" lineEndContext="#stay" fallthrough="true" fallthroughContext="#pop">
- <RegExpr attribute="Data Type" context="#stay" String="[\w_]+" />
- <AnyChar attribute="Normal Text" context="#pop" String="[;,*=!&amp;/" />
- <RegExpr attribute="Normal Text" context="#stay" String="\s*[})]?\s*/" />
- <DetectChar attribute="Operator" context="#stay" char="'" />
- <RegExpr attribute="Normal Text" context="in_hash_elem" String="\s*\{" />
- <RegExpr attribute="Operator" context="#stay" String="(\+\+|--)" />
- <Detect2Chars attribute="Normal Text" context="#stay" char=":" char1=":" />
- <RegExpr attribute="Normal Text" context="#stay" String="\s*\}?\s*-&gt;\s*" />
- <RegExpr attribute="Normal Text" context="in_hash_elem" String="\s*\}\s*\{\s*" />
- <RegExpr attribute="Data Type" context="#stay" String="[\$@%]" />
- </context>
- <context name="slash_safe_escape" attribute="Normal Text" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop">
- <RegExpr attribute="Normal Text" context="#pop" String="\s*[)}\]]?\s*/" />
- <keyword attribute="Keyword" context="#pop" String="keywords" />
- </context>
- <context name="sub_name_def" attribute="Normal Text" lineEndContext="#pop">
- <RegExpr attribute="Normal Text" context="#stay" String="[\w_]+" />
- <DetectChar attribute="Data Type" context="var_detect" char="$" />
- <RegExpr attribute="Normal Text" context="sub_arg_definition" String="\s*\(" />
- <DetectChar attribute="Normal Text" context="#pop" char="{" beginRegion="Brace1" />
- <DetectChar attribute="Normal Text" context="#pop" char=";" />
- </context>
- <context name="package_qualified_blank" attribute="Normal Text" lineEndContext="#stay">
- <RegExpr attribute="Normal Text" context="#pop" String="[\w_]+" />
- </context>
- <context name="in_hash_elem" attribute="Normal Text" lineEndContext="#pop">
- <DetectChar attribute="String (interpolated)" context="ip_string" char="&quot;" />
- <DetectChar attribute="String" context="string" char="'" />
- <RegExpr attribute="String" context="#stay" String="\s*[\w_]+\s*(?![\w_\(])" />
- <RegExpr attribute="Special Variable" context="#stay" String="\$[0-9]+" />
- <RegExpr attribute="Special Variable" context="#stay" String="[@\$](?:[\+\-_]\B|ARGV\b|INC\b)" />
- <RegExpr attribute="Special Variable" context="#stay" String="[%\$](?:INC\b|ENV\b|SIG\b)" />
- <RegExpr attribute="Data Type" context="var_detect" String="\$\$[\$\w_]" />
- <RegExpr attribute="Data Type" context="var_detect" String="\$[#_][\w_]" />
- <RegExpr attribute="Special Variable" context="#stay" String="\$[^a-zA-Z0-9\s{][A-Z]" />
- <RegExpr attribute="Data Type" context="var_detect" String="[\$@%]" />
- <RegExpr attribute="Normal Text" context="#pop" String="\s*[\w_]+\s*\(" />
- <DetectChar attribute="Normal Text" context="#pop" char="}" />
- </context>
- <context name="sub_arg_definition" attribute="Normal Text" lineEndContext="#stay" fallthrough="true" fallthroughContext="#pop#pop">
- <RegExpr attribute="Data Type" context="#stay" String="[\$@%]" />
- <DetectChar attribute="Normal Text" context="slash_safe_escape" char=")" />
- </context>
- <context name="pat_ext" attribute="Pattern Internal Operator" lineEndContext="#stay">
- <RegExpr attribute="Comment" context="#pop" String="\#[^)]*" />
- <RegExpr attribute="Pattern Internal Operator" context="#pop" String="[:=!&gt;&lt;]+" />
- <DetectChar attribute="Pattern Internal Operator" context="#pop" char=")" />
- </context>
- <context name="pat_char_class" attribute="Pattern Character Class" lineEndContext="#stay">
- <LineContinue attribute="Pattern Character Class" context="#stay" />
- <DetectChar attribute="Pattern Internal Operator" context="#stay" char="^" />
- <Detect2Chars attribute="Pattern Character Class" context="#stay" char="\" char1="\" />
- <Detect2Chars attribute="Pattern Character Class" context="#stay" char="\" char1="]" />
- <RangeDetect attribute="Pattern Character Class" context="#stay" char="[" char1="]" />
- <DetectChar attribute="Pattern Internal Operator" context="#pop" char="]" />
- </context>
- <context name="comment" attribute="Comment" lineEndContext="#pop">
- <RegExpr attribute="Note" context="#stay" String="(?:FIXME|TODO|NOTE):?" />
- </context>
- <context name="Backticked" attribute="String (interpolated)" lineEndContext="#stay">
- <IncludeRules context="ipstring_internal"/>
- <DetectChar attribute="Operator" context="#pop" char="`"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="Pragma" defStyleNum="dsKeyword" />
- <itemData name="Function" defStyleNum="dsNormal" color="#000080" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Operator" defStyleNum="dsKeyword" />
- <itemData name="Data Type" defStyleNum="dsDataType" />
- <itemData name="Special Variable" defStyleNum="dsDataType" color="#C00000" selColor="#C00000" bold="0" italic="0" />
- <itemData name="Decimal" defStyleNum="dsDecVal" />
- <itemData name="Octal" defStyleNum="dsBaseN" />
- <itemData name="Hex" defStyleNum="dsBaseN" />
- <itemData name="Float" defStyleNum="dsFloat" />
- <itemData name="String" defStyleNum="dsString" color="#FF6C6C" selColor="#FF6C6C" bold="0" italic="0" />
- <itemData name="String (interpolated)" defStyleNum="dsString" />
- <itemData name="String Special Character" defStyleNum="dsChar" />
- <itemData name="Pattern" defStyleNum="dsOthers" />
- <itemData name="Pattern Internal Operator" defStyleNum="dsChar" />
- <itemData name="Pattern Character Class" defStyleNum="dsBaseN" />
- <itemData name="Data" defStyleNum="dsNormal" />
- <itemData name="Comment" defStyleNum="dsComment" />
- <itemData name="Pod" defStyleNum="dsComment" />
- <itemData name="Nothing" defStyleNum="dsComment" />
- <itemData name="Note" defStyleNum="dsDecVal" color="#0000FF" selColor="#ffffff" bold="1" italic="0"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="#" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<!-- kate: space-indent on; indent-width 2; replace-tabs on; -->
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="PHP" version="1.09" kateversion="2.1" section="Scripts"
- extensions="*.php;*.php3;*.wml;*.phtml;*.phtm;*.inc"
- mimetype="text/x-php4-src;text/x-php3-src;text/vnd.wap.wml">
- <highlighting>
- <list name="control structures">
- <item>as</item>
- <item>case</item>
- <item>if</item>
- <item>else</item>
- <item>elseif</item>
- <item>while</item>
- <item>do</item>
- <item>for</item>
- <item>foreach</item>
- <item>break</item>
- <item>continue</item>
- <item>switch</item>
- <item>declare</item>
- <item>return</item>
- <item>require</item>
- <item>include</item>
- <item>require_once</item>
- <item>include_once</item>
- </list>
- <list name="keywords">
- <item> var </item>
- <item> class </item>
- <item> new </item>
- <item> function </item>
- <item> default </item>
- <item> E_ALL </item>
- <item> E_ERROR </item>
- <item> E_NOTICE </item>
- <item> E_PARSE </item>
- <item> E_USER_ERROR </item>
- <item> E_USER_NOTICE </item>
- <item> E_USER_WARNING </item>
- <item> E_WARNING </item>
- <item> FALSE </item>
- <item> PHP_OS </item>
- <item> PHP_VERSION </item>
- <item> __FILE__ </item>
- <item> __LINE__ </item>
- <item> TRUE </item>
- </list>
- <list name="functions">
- <item> abs </item>
- <item> acos </item>
- <item> acosh </item>
- <item> addcslashes </item>
- <item> addslashes </item>
- <item> apache_child_terminate </item>
- <item> apache_lookup_uri </item>
- <item> apache_note </item>
- <item> apache_setenv </item>
- <item> array </item>
- <item> array_change_key_case </item>
- <item> array_chunk </item>
- <item> array_count_values </item>
- <item> array_diff </item>
- <item> array_fill </item>
- <item> array_filter </item>
- <item> array_flip </item>
- <item> array_intersect </item>
- <item> array_key_exists </item>
- <item> array_keys </item>
- <item> array_map </item>
- <item> array_merge </item>
- <item> array_merge_recursive </item>
- <item> array_multisort </item>
- <item> array_pad </item>
- <item> array_pop </item>
- <item> array_push </item>
- <item> array_rand </item>
- <item> array_reduce </item>
- <item> array_reverse </item>
- <item> array_search </item>
- <item> array_shift </item>
- <item> array_slice </item>
- <item> array_splice </item>
- <item> array_sum </item>
- <item> array_unique </item>
- <item> array_unshift </item>
- <item> array_values </item>
- <item> array_walk </item>
- <item> arsort </item>
- <item> ascii2ebcdic </item>
- <item> asin </item>
- <item> asinh </item>
- <item> asort </item>
- <item> aspell_check </item>
- <item> aspell_check_raw </item>
- <item> aspell_new </item>
- <item> aspell_suggest </item>
- <item> assert </item>
- <item> assert_options </item>
- <item> atan </item>
- <item> atan2 </item>
- <item> atanh </item>
- <item> base64_decode </item>
- <item> base64_encode </item>
- <item> base_convert </item>
- <item> basename </item>
- <item> bcadd </item>
- <item> bccomp </item>
- <item> bcdiv </item>
- <item> bcmod </item>
- <item> bcmul </item>
- <item> bcpow </item>
- <item> bcscale </item>
- <item> bcsqrt </item>
- <item> bcsub </item>
- <item> bin2hex </item>
- <item> bind_textdomain_codeset </item>
- <item> bindec </item>
- <item> bindtextdomain </item>
- <item> bzclose </item>
- <item> bzcompress </item>
- <item> bzdecompress </item>
- <item> bzerrno </item>
- <item> bzerror </item>
- <item> bzerrstr </item>
- <item> bzflush </item>
- <item> bzopen </item>
- <item> bzread </item>
- <item> bzwrite </item>
- <item> cal_days_in_month </item>
- <item> cal_from_jd </item>
- <item> cal_info </item>
- <item> cal_to_jd </item>
- <item> call_user_func </item>
- <item> call_user_func_array </item>
- <item> call_user_method </item>
- <item> call_user_method_array </item>
- <item> ccvs_add </item>
- <item> ccvs_auth </item>
- <item> ccvs_command </item>
- <item> ccvs_count </item>
- <item> ccvs_delete </item>
- <item> ccvs_done </item>
- <item> ccvs_init </item>
- <item> ccvs_lookup </item>
- <item> ccvs_new </item>
- <item> ccvs_report </item>
- <item> ccvs_return </item>
- <item> ccvs_reverse </item>
- <item> ccvs_sale </item>
- <item> ccvs_status </item>
- <item> ccvs_textvalue </item>
- <item> ccvs_void </item>
- <item> ceil </item>
- <item> chdir </item>
- <item> checkdate </item>
- <item> checkdnsrr </item>
- <item> chgrp </item>
- <item> chmod </item>
- <item> chop </item>
- <item> chown </item>
- <item> chr </item>
- <item> chroot </item>
- <item> chunk_split </item>
- <item> class_exists </item>
- <item> clearstatcache </item>
- <item> closedir </item>
- <item> closelog </item>
- <item> com </item>
- <item> com_addref </item>
- <item> com_get </item>
- <item> com_invoke </item>
- <item> com_isenum </item>
- <item> com_load </item>
- <item> com_load_typelib </item>
- <item> com_propget </item>
- <item> com_propput </item>
- <item> com_propset </item>
- <item> com_release </item>
- <item> com_set </item>
- <item> compact </item>
- <item> connection_aborted </item>
- <item> connection_status </item>
- <item> connection_timeout </item>
- <item> constant </item>
- <item> convert_cyr_string </item>
- <item> copy </item>
- <item> cos </item>
- <item> cosh </item>
- <item> count </item>
- <item> count_chars </item>
- <item> cpdf_add_annotation </item>
- <item> cpdf_add_outline </item>
- <item> cpdf_arc </item>
- <item> cpdf_begin_text </item>
- <item> cpdf_circle </item>
- <item> cpdf_clip </item>
- <item> cpdf_close </item>
- <item> cpdf_closepath </item>
- <item> cpdf_closepath_fill_stroke </item>
- <item> cpdf_closepath_stroke </item>
- <item> cpdf_continue_text </item>
- <item> cpdf_curveto </item>
- <item> cpdf_end_text </item>
- <item> cpdf_fill </item>
- <item> cpdf_fill_stroke </item>
- <item> cpdf_finalize </item>
- <item> cpdf_finalize_page </item>
- <item> cpdf_global_set_document_limits </item>
- <item> cpdf_import_jpeg </item>
- <item> cpdf_lineto </item>
- <item> cpdf_moveto </item>
- <item> cpdf_newpath </item>
- <item> cpdf_open </item>
- <item> cpdf_output_buffer </item>
- <item> cpdf_page_init </item>
- <item> cpdf_place_inline_image </item>
- <item> cpdf_rect </item>
- <item> cpdf_restore </item>
- <item> cpdf_rlineto </item>
- <item> cpdf_rmoveto </item>
- <item> cpdf_rotate </item>
- <item> cpdf_rotate_text </item>
- <item> cpdf_save </item>
- <item> cpdf_save_to_file </item>
- <item> cpdf_scale </item>
- <item> cpdf_set_action_url </item>
- <item> cpdf_set_char_spacing </item>
- <item> cpdf_set_creator </item>
- <item> cpdf_set_current_page </item>
- <item> cpdf_set_font </item>
- <item> cpdf_set_font_directories </item>
- <item> cpdf_set_font_map_file </item>
- <item> cpdf_set_horiz_scaling </item>
- <item> cpdf_set_keywords </item>
- <item> cpdf_set_leading </item>
- <item> cpdf_set_page_animation </item>
- <item> cpdf_set_subject </item>
- <item> cpdf_set_text_matrix </item>
- <item> cpdf_set_text_pos </item>
- <item> cpdf_set_text_rendering </item>
- <item> cpdf_set_text_rise </item>
- <item> cpdf_set_title </item>
- <item> cpdf_set_viewer_preferences </item>
- <item> cpdf_set_word_spacing </item>
- <item> cpdf_setdash </item>
- <item> cpdf_setflat </item>
- <item> cpdf_setgray </item>
- <item> cpdf_setgray_fill </item>
- <item> cpdf_setgray_stroke </item>
- <item> cpdf_setlinecap </item>
- <item> cpdf_setlinejoin </item>
- <item> cpdf_setlinewidth </item>
- <item> cpdf_setmiterlimit </item>
- <item> cpdf_setrgbcolor </item>
- <item> cpdf_setrgbcolor_fill </item>
- <item> cpdf_setrgbcolor_stroke </item>
- <item> cpdf_show </item>
- <item> cpdf_show_xy </item>
- <item> cpdf_stringwidth </item>
- <item> cpdf_stroke </item>
- <item> cpdf_text </item>
- <item> cpdf_translate </item>
- <item> crack_check </item>
- <item> crack_closedict </item>
- <item> crack_getlastmessage </item>
- <item> crack_opendict </item>
- <item> crc32 </item>
- <item> create_function </item>
- <item> crypt </item>
- <item> ctype_alnum </item>
- <item> ctype_alpha </item>
- <item> ctype_cntrl </item>
- <item> ctype_digit </item>
- <item> ctype_graph </item>
- <item> ctype_lower </item>
- <item> ctype_print </item>
- <item> ctype_punct </item>
- <item> ctype_space </item>
- <item> ctype_upper </item>
- <item> ctype_xdigit </item>
- <item> curl_close </item>
- <item> curl_errno </item>
- <item> curl_error </item>
- <item> curl_exec </item>
- <item> curl_getinfo </item>
- <item> curl_init </item>
- <item> curl_setopt </item>
- <item> curl_version </item>
- <item> current </item>
- <item> cybercash_base64_decode </item>
- <item> cybercash_base64_encode </item>
- <item> cybercash_decr </item>
- <item> cybercash_encr </item>
- <item> cybermut_creerformulairecm </item>
- <item> cybermut_creerreponsecm </item>
- <item> cybermut_testmac </item>
- <item> cyrus_authenticate </item>
- <item> cyrus_bind </item>
- <item> cyrus_close </item>
- <item> cyrus_connect </item>
- <item> cyrus_query </item>
- <item> cyrus_unbind </item>
- <item> date </item>
- <item> dba_close </item>
- <item> dba_delete </item>
- <item> dba_exists </item>
- <item> dba_fetch </item>
- <item> dba_firstkey </item>
- <item> dba_insert </item>
- <item> dba_nextkey </item>
- <item> dba_open </item>
- <item> dba_optimize </item>
- <item> dba_popen </item>
- <item> dba_replace </item>
- <item> dba_sync </item>
- <item> dbase_add_record </item>
- <item> dbase_close </item>
- <item> dbase_create </item>
- <item> dbase_delete_record </item>
- <item> dbase_get_record </item>
- <item> dbase_get_record_with_names </item>
- <item> dbase_numfields </item>
- <item> dbase_numrecords </item>
- <item> dbase_open </item>
- <item> dbase_pack </item>
- <item> dbase_replace_record </item>
- <item> dblist </item>
- <item> dbmclose </item>
- <item> dbmdelete </item>
- <item> dbmexists </item>
- <item> dbmfetch </item>
- <item> dbmfirstkey </item>
- <item> dbminsert </item>
- <item> dbmnextkey </item>
- <item> dbmopen </item>
- <item> dbmreplace </item>
- <item> dbplus_add </item>
- <item> dbplus_aql </item>
- <item> dbplus_chdir </item>
- <item> dbplus_close </item>
- <item> dbplus_curr </item>
- <item> dbplus_errcode </item>
- <item> dbplus_errno </item>
- <item> dbplus_find </item>
- <item> dbplus_first </item>
- <item> dbplus_flush </item>
- <item> dbplus_freealllocks </item>
- <item> dbplus_freelock </item>
- <item> dbplus_freerlocks </item>
- <item> dbplus_getlock </item>
- <item> dbplus_getunique </item>
- <item> dbplus_info </item>
- <item> dbplus_last </item>
- <item> dbplus_lockrel </item>
- <item> dbplus_next </item>
- <item> dbplus_open </item>
- <item> dbplus_prev </item>
- <item> dbplus_rchperm </item>
- <item> dbplus_rcreate </item>
- <item> dbplus_rcrtexact </item>
- <item> dbplus_rcrtlike </item>
- <item> dbplus_resolve </item>
- <item> dbplus_restorepos </item>
- <item> dbplus_rkeys </item>
- <item> dbplus_ropen </item>
- <item> dbplus_rquery </item>
- <item> dbplus_rrename </item>
- <item> dbplus_rsecindex </item>
- <item> dbplus_runlink </item>
- <item> dbplus_rzap </item>
- <item> dbplus_savepos </item>
- <item> dbplus_setindex </item>
- <item> dbplus_setindexbynumber </item>
- <item> dbplus_sql </item>
- <item> dbplus_tcl </item>
- <item> dbplus_tremove </item>
- <item> dbplus_undo </item>
- <item> dbplus_undoprepare </item>
- <item> dbplus_unlockrel </item>
- <item> dbplus_unselect </item>
- <item> dbplus_update </item>
- <item> dbplus_xlockrel </item>
- <item> dbplus_xunlockrel </item>
- <item> dbx_close </item>
- <item> dbx_compare </item>
- <item> dbx_connect </item>
- <item> dbx_error </item>
- <item> dbx_query </item>
- <item> dbx_sort </item>
- <item> dcgettext </item>
- <item> dcngettext </item>
- <item> debugger_off </item>
- <item> debugger_on </item>
- <item> decbin </item>
- <item> dechex </item>
- <item> decoct </item>
- <item> define </item>
- <item> define_syslog_variables </item>
- <item> defined </item>
- <item> deg2rad </item>
- <item> delete </item>
- <item> dgettext </item>
- <item> die </item>
- <item> dio_close </item>
- <item> dio_fcntl </item>
- <item> dio_open </item>
- <item> dio_read </item>
- <item> dio_seek </item>
- <item> dio_stat </item>
- <item> dio_truncate </item>
- <item> dio_write </item>
- <item> dir </item>
- <item> dirname </item>
- <item> disk_free_space </item>
- <item> disk_total_space </item>
- <item> diskfreespace </item>
- <item> dl </item>
- <item> dngettext </item>
- <item> domxml_add_root </item>
- <item> domxml_attributes </item>
- <item> domxml_children </item>
- <item> domxml_dumpmem </item>
- <item> domxml_get_attribute </item>
- <item> domxml_new_child </item>
- <item> domxml_new_xmldoc </item>
- <item> domxml_node </item>
- <item> domxml_node_set_content </item>
- <item> domxml_node_unlink_node </item>
- <item> domxml_root </item>
- <item> domxml_set_attribute </item>
- <item> domxml_version </item>
- <item> dotnet_load </item>
- <item> doubleval </item>
- <item> each </item>
- <item> easter_date </item>
- <item> easter_days </item>
- <item> ebcdic2ascii </item>
- <item> echo </item>
- <item> empty </item>
- <item> end </item>
- <item> ereg </item>
- <item> ereg_replace </item>
- <item> eregi </item>
- <item> eregi_replace </item>
- <item> error_log </item>
- <item> error_reporting </item>
- <item> escapeshellarg </item>
- <item> escapeshellcmd </item>
- <item> eval </item>
- <item> exec </item>
- <item> exif_imagetype </item>
- <item> exif_read_data </item>
- <item> exif_thumbnail </item>
- <item> exit </item>
- <item> exp </item>
- <item> explode </item>
- <item> expm1 </item>
- <item> extension_loaded </item>
- <item> extract </item>
- <item> ezmlm_hash </item>
- <item> fbsql_affected_rows </item>
- <item> fbsql_autocommit </item>
- <item> fbsql_change_user </item>
- <item> fbsql_close </item>
- <item> fbsql_commit </item>
- <item> fbsql_connect </item>
- <item> fbsql_create_blob </item>
- <item> fbsql_create_clob </item>
- <item> fbsql_create_db </item>
- <item> fbsql_data_seek </item>
- <item> fbsql_database </item>
- <item> fbsql_database_password </item>
- <item> fbsql_db_query </item>
- <item> fbsql_db_status </item>
- <item> fbsql_drop_db </item>
- <item> fbsql_errno </item>
- <item> fbsql_error </item>
- <item> fbsql_fetch_array </item>
- <item> fbsql_fetch_assoc </item>
- <item> fbsql_fetch_field </item>
- <item> fbsql_fetch_lengths </item>
- <item> fbsql_fetch_object </item>
- <item> fbsql_fetch_row </item>
- <item> fbsql_field_flags </item>
- <item> fbsql_field_len </item>
- <item> fbsql_field_name </item>
- <item> fbsql_field_seek </item>
- <item> fbsql_field_table </item>
- <item> fbsql_field_type </item>
- <item> fbsql_free_result </item>
- <item> fbsql_get_autostart_info </item>
- <item> fbsql_hostname </item>
- <item> fbsql_insert_id </item>
- <item> fbsql_list_dbs </item>
- <item> fbsql_list_fields </item>
- <item> fbsql_list_tables </item>
- <item> fbsql_next_result </item>
- <item> fbsql_num_fields </item>
- <item> fbsql_num_rows </item>
- <item> fbsql_password </item>
- <item> fbsql_pconnect </item>
- <item> fbsql_query </item>
- <item> fbsql_read_blob </item>
- <item> fbsql_read_clob </item>
- <item> fbsql_result </item>
- <item> fbsql_rollback </item>
- <item> fbsql_select_db </item>
- <item> fbsql_set_lob_mode </item>
- <item> fbsql_set_transaction </item>
- <item> fbsql_start_db </item>
- <item> fbsql_stop_db </item>
- <item> fbsql_tablename </item>
- <item> fbsql_username </item>
- <item> fbsql_warnings </item>
- <item> fclose </item>
- <item> fdf_add_template </item>
- <item> fdf_close </item>
- <item> fdf_create </item>
- <item> fdf_get_file </item>
- <item> fdf_get_status </item>
- <item> fdf_get_value </item>
- <item> fdf_next_field_name </item>
- <item> fdf_open </item>
- <item> fdf_save </item>
- <item> fdf_set_ap </item>
- <item> fdf_set_encoding </item>
- <item> fdf_set_file </item>
- <item> fdf_set_flags </item>
- <item> fdf_set_javascript_action </item>
- <item> fdf_set_opt </item>
- <item> fdf_set_status </item>
- <item> fdf_set_submit_form_action </item>
- <item> fdf_set_value </item>
- <item> feof </item>
- <item> fflush </item>
- <item> fgetc </item>
- <item> fgetcsv </item>
- <item> fgets </item>
- <item> fgetss </item>
- <item> fgetwrapperdata </item>
- <item> file </item>
- <item> file_exists </item>
- <item> file_get_contents </item>
- <item> fileatime </item>
- <item> filectime </item>
- <item> filegroup </item>
- <item> fileinode </item>
- <item> filemtime </item>
- <item> fileowner </item>
- <item> fileperms </item>
- <item> filepro </item>
- <item> filepro_fieldcount </item>
- <item> filepro_fieldname </item>
- <item> filepro_fieldtype </item>
- <item> filepro_fieldwidth </item>
- <item> filepro_retrieve </item>
- <item> filepro_rowcount </item>
- <item> filesize </item>
- <item> filetype </item>
- <item> floatval </item>
- <item> flock </item>
- <item> floor </item>
- <item> flush </item>
- <item> fopen </item>
- <item> fpassthru </item>
- <item> fputs </item>
- <item> fread </item>
- <item> frenchtojd </item>
- <item> fribidi_log2vis </item>
- <item> fscanf </item>
- <item> fseek </item>
- <item> fsockopen </item>
- <item> fstat </item>
- <item> ftell </item>
- <item> ftok </item>
- <item> ftp_cdup </item>
- <item> ftp_chdir </item>
- <item> ftp_close </item>
- <item> ftp_connect </item>
- <item> ftp_delete </item>
- <item> ftp_exec </item>
- <item> ftp_fget </item>
- <item> ftp_fput </item>
- <item> ftp_get </item>
- <item> ftp_get_option </item>
- <item> ftp_login </item>
- <item> ftp_mdtm </item>
- <item> ftp_mkdir </item>
- <item> ftp_nlist </item>
- <item> ftp_pasv </item>
- <item> ftp_put </item>
- <item> ftp_pwd </item>
- <item> ftp_quit </item>
- <item> ftp_rawlist </item>
- <item> ftp_rename </item>
- <item> ftp_rmdir </item>
- <item> ftp_set_option </item>
- <item> ftp_site </item>
- <item> ftp_size </item>
- <item> ftp_systype </item>
- <item> ftruncate </item>
- <item> func_get_arg </item>
- <item> func_get_args </item>
- <item> func_num_args </item>
- <item> function_exists </item>
- <item> fwrite </item>
- <item> get_browser </item>
- <item> get_cfg_var </item>
- <item> get_class </item>
- <item> get_class_methods </item>
- <item> get_class_vars </item>
- <item> get_current_user </item>
- <item> get_declared_classes </item>
- <item> get_defined_constants </item>
- <item> get_defined_functions </item>
- <item> get_defined_vars </item>
- <item> get_extension_funcs </item>
- <item> get_html_translation_table </item>
- <item> get_included_files </item>
- <item> get_loaded_extensions </item>
- <item> get_magic_quotes_gpc </item>
- <item> get_magic_quotes_runtime </item>
- <item> get_meta_tags </item>
- <item> get_object_vars </item>
- <item> get_parent_class </item>
- <item> get_required_files </item>
- <item> get_resource_type </item>
- <item> getallheaders </item>
- <item> getcwd </item>
- <item> getdate </item>
- <item> getenv </item>
- <item> gethostbyaddr </item>
- <item> gethostbyname </item>
- <item> gethostbynamel </item>
- <item> getimagesize </item>
- <item> getlastmod </item>
- <item> getmxrr </item>
- <item> getmygid </item>
- <item> getmyinode </item>
- <item> getmypid </item>
- <item> getmyuid </item>
- <item> getprotobyname </item>
- <item> getprotobynumber </item>
- <item> getrandmax </item>
- <item> getrusage </item>
- <item> getservbyname </item>
- <item> getservbyport </item>
- <item> gettext </item>
- <item> gettimeofday </item>
- <item> gettype </item>
- <item> global </item>
- <item> gmdate </item>
- <item> gmmktime </item>
- <item> gmp_abs </item>
- <item> gmp_add </item>
- <item> gmp_and </item>
- <item> gmp_clrbit </item>
- <item> gmp_cmp </item>
- <item> gmp_com </item>
- <item> gmp_div </item>
- <item> gmp_div_q </item>
- <item> gmp_div_qr </item>
- <item> gmp_div_r </item>
- <item> gmp_divexact </item>
- <item> gmp_fact </item>
- <item> gmp_gcd </item>
- <item> gmp_gcdext </item>
- <item> gmp_hamdist </item>
- <item> gmp_init </item>
- <item> gmp_intval </item>
- <item> gmp_invert </item>
- <item> gmp_jacobi </item>
- <item> gmp_legendre </item>
- <item> gmp_mod </item>
- <item> gmp_mul </item>
- <item> gmp_neg </item>
- <item> gmp_or </item>
- <item> gmp_perfect_square </item>
- <item> gmp_popcount </item>
- <item> gmp_pow </item>
- <item> gmp_powm </item>
- <item> gmp_prob_prime </item>
- <item> gmp_random </item>
- <item> gmp_scan0 </item>
- <item> gmp_scan1 </item>
- <item> gmp_setbit </item>
- <item> gmp_sign </item>
- <item> gmp_sqrt </item>
- <item> gmp_sqrtrem </item>
- <item> gmp_strval </item>
- <item> gmp_sub </item>
- <item> gmp_xor </item>
- <item> gmstrftime </item>
- <item> gregoriantojd </item>
- <item> gzclose </item>
- <item> gzcompress </item>
- <item> gzdeflate </item>
- <item> gzencode </item>
- <item> gzeof </item>
- <item> gzfile </item>
- <item> gzgetc </item>
- <item> gzgets </item>
- <item> gzgetss </item>
- <item> gzinflate </item>
- <item> gzopen </item>
- <item> gzpassthru </item>
- <item> gzputs </item>
- <item> gzread </item>
- <item> gzrewind </item>
- <item> gzseek </item>
- <item> gztell </item>
- <item> gzuncompress </item>
- <item> gzwrite </item>
- <item> header </item>
- <item> headers_sent </item>
- <item> hebrev </item>
- <item> hebrevc </item>
- <item> hexdec </item>
- <item> highlight_file </item>
- <item> highlight_string </item>
- <item> htmlentities </item>
- <item> htmlspecialchars </item>
- <item> hw_array2objrec </item>
- <item> hw_changeobject </item>
- <item> hw_children </item>
- <item> hw_childrenobj </item>
- <item> hw_close </item>
- <item> hw_connect </item>
- <item> hw_connection_info </item>
- <item> hw_cp </item>
- <item> hw_deleteobject </item>
- <item> hw_docbyanchor </item>
- <item> hw_docbyanchorobj </item>
- <item> hw_document_attributes </item>
- <item> hw_document_bodytag </item>
- <item> hw_document_content </item>
- <item> hw_document_setcontent </item>
- <item> hw_document_size </item>
- <item> hw_dummy </item>
- <item> hw_edittext </item>
- <item> hw_error </item>
- <item> hw_errormsg </item>
- <item> hw_free_document </item>
- <item> hw_getanchors </item>
- <item> hw_getanchorsobj </item>
- <item> hw_getandlock </item>
- <item> hw_getchildcoll </item>
- <item> hw_getchildcollobj </item>
- <item> hw_getchilddoccoll </item>
- <item> hw_getchilddoccollobj </item>
- <item> hw_getobject </item>
- <item> hw_getobjectbyquery </item>
- <item> hw_getobjectbyquerycoll </item>
- <item> hw_getobjectbyquerycollobj </item>
- <item> hw_getobjectbyqueryobj </item>
- <item> hw_getparents </item>
- <item> hw_getparentsobj </item>
- <item> hw_getrellink </item>
- <item> hw_getremote </item>
- <item> hw_getremotechildren </item>
- <item> hw_getsrcbydestobj </item>
- <item> hw_gettext </item>
- <item> hw_getusername </item>
- <item> hw_identify </item>
- <item> hw_incollections </item>
- <item> hw_info </item>
- <item> hw_inscoll </item>
- <item> hw_insdoc </item>
- <item> hw_insertanchors </item>
- <item> hw_insertdocument </item>
- <item> hw_insertobject </item>
- <item> hw_mapid </item>
- <item> hw_modifyobject </item>
- <item> hw_mv </item>
- <item> hw_new_document </item>
- <item> hw_objrec2array </item>
- <item> hw_output_document </item>
- <item> hw_pconnect </item>
- <item> hw_pipedocument </item>
- <item> hw_root </item>
- <item> hw_setlinkroot </item>
- <item> hw_stat </item>
- <item> hw_unlock </item>
- <item> hw_who </item>
- <item> hypot </item>
- <item> ibase_blob_add </item>
- <item> ibase_blob_cancel </item>
- <item> ibase_blob_close </item>
- <item> ibase_blob_create </item>
- <item> ibase_blob_echo </item>
- <item> ibase_blob_get </item>
- <item> ibase_blob_import </item>
- <item> ibase_blob_info </item>
- <item> ibase_blob_open </item>
- <item> ibase_close </item>
- <item> ibase_commit </item>
- <item> ibase_connect </item>
- <item> ibase_errmsg </item>
- <item> ibase_execute </item>
- <item> ibase_fetch_object </item>
- <item> ibase_fetch_row </item>
- <item> ibase_field_info </item>
- <item> ibase_free_query </item>
- <item> ibase_free_result </item>
- <item> ibase_num_fields </item>
- <item> ibase_pconnect </item>
- <item> ibase_prepare </item>
- <item> ibase_query </item>
- <item> ibase_rollback </item>
- <item> ibase_timefmt </item>
- <item> ibase_trans </item>
- <item> icap_close </item>
- <item> icap_create_calendar </item>
- <item> icap_delete_calendar </item>
- <item> icap_delete_event </item>
- <item> icap_fetch_event </item>
- <item> icap_list_alarms </item>
- <item> icap_list_events </item>
- <item> icap_open </item>
- <item> icap_rename_calendar </item>
- <item> icap_reopen </item>
- <item> icap_snooze </item>
- <item> icap_store_event </item>
- <item> iconv </item>
- <item> iconv_get_encoding </item>
- <item> iconv_set_encoding </item>
- <item> ifx_affected_rows </item>
- <item> ifx_blobinfile_mode </item>
- <item> ifx_byteasvarchar </item>
- <item> ifx_close </item>
- <item> ifx_connect </item>
- <item> ifx_copy_blob </item>
- <item> ifx_create_blob </item>
- <item> ifx_create_char </item>
- <item> ifx_do </item>
- <item> ifx_error </item>
- <item> ifx_errormsg </item>
- <item> ifx_fetch_row </item>
- <item> ifx_fieldproperties </item>
- <item> ifx_fieldtypes </item>
- <item> ifx_free_blob </item>
- <item> ifx_free_char </item>
- <item> ifx_free_result </item>
- <item> ifx_get_blob </item>
- <item> ifx_get_char </item>
- <item> ifx_getsqlca </item>
- <item> ifx_htmltbl_result </item>
- <item> ifx_nullformat </item>
- <item> ifx_num_fields </item>
- <item> ifx_num_rows </item>
- <item> ifx_pconnect </item>
- <item> ifx_prepare </item>
- <item> ifx_query </item>
- <item> ifx_textasvarchar </item>
- <item> ifx_update_blob </item>
- <item> ifx_update_char </item>
- <item> ifxus_close_slob </item>
- <item> ifxus_create_slob </item>
- <item> ifxus_free_slob </item>
- <item> ifxus_open_slob </item>
- <item> ifxus_read_slob </item>
- <item> ifxus_seek_slob </item>
- <item> ifxus_tell_slob </item>
- <item> ifxus_write_slob </item>
- <item> ignore_user_abort </item>
- <item> image2wbmp </item>
- <item> imagealphablending </item>
- <item> imagearc </item>
- <item> imagechar </item>
- <item> imagecharup </item>
- <item> imagecolorallocate </item>
- <item> imagecolorat </item>
- <item> imagecolorclosest </item>
- <item> imagecolorclosestalpha </item>
- <item> imagecolorclosesthwb </item>
- <item> imagecolordeallocate </item>
- <item> imagecolorexact </item>
- <item> imagecolorexactalpha </item>
- <item> imagecolorresolve </item>
- <item> imagecolorresolvealpha </item>
- <item> imagecolorset </item>
- <item> imagecolorsforindex </item>
- <item> imagecolorstotal </item>
- <item> imagecolortransparent </item>
- <item> imagecopy </item>
- <item> imagecopymerge </item>
- <item> imagecopymergegray </item>
- <item> imagecopyresampled </item>
- <item> imagecopyresized </item>
- <item> imagecreate </item>
- <item> imagecreatefromgd </item>
- <item> imagecreatefromgd2 </item>
- <item> imagecreatefromgd2part </item>
- <item> imagecreatefromgif </item>
- <item> imagecreatefromjpeg </item>
- <item> imagecreatefrompng </item>
- <item> imagecreatefromstring </item>
- <item> imagecreatefromwbmp </item>
- <item> imagecreatefromxbm </item>
- <item> imagecreatefromxpm </item>
- <item> imagecreatetruecolor </item>
- <item> imagedashedline </item>
- <item> imagedestroy </item>
- <item> imageellipse </item>
- <item> imagefill </item>
- <item> imagefilledarc </item>
- <item> imagefilledellipse </item>
- <item> imagefilledpolygon </item>
- <item> imagefilledrectangle </item>
- <item> imagefilltoborder </item>
- <item> imagefontheight </item>
- <item> imagefontwidth </item>
- <item> imageftbbox </item>
- <item> imagefttext </item>
- <item> imagegammacorrect </item>
- <item> imagegd </item>
- <item> imagegd2 </item>
- <item> imagegif </item>
- <item> imageinterlace </item>
- <item> imagejpeg </item>
- <item> imageline </item>
- <item> imageloadfont </item>
- <item> imagepalettecopy </item>
- <item> imagepng </item>
- <item> imagepolygon </item>
- <item> imagepsbbox </item>
- <item> imagepsencodefont </item>
- <item> imagepsextendfont </item>
- <item> imagepsfreefont </item>
- <item> imagepsloadfont </item>
- <item> imagepsslantfont </item>
- <item> imagepstext </item>
- <item> imagerectangle </item>
- <item> imagesetbrush </item>
- <item> imagesetpixel </item>
- <item> imagesetstyle </item>
- <item> imagesetthickness </item>
- <item> imagesettile </item>
- <item> imagestring </item>
- <item> imagestringup </item>
- <item> imagesx </item>
- <item> imagesy </item>
- <item> imagetruecolortopalette </item>
- <item> imagettfbbox </item>
- <item> imagettftext </item>
- <item> imagetypes </item>
- <item> imagewbmp </item>
- <item> imap_8bit </item>
- <item> imap_alerts </item>
- <item> imap_append </item>
- <item> imap_base64 </item>
- <item> imap_binary </item>
- <item> imap_body </item>
- <item> imap_bodystruct </item>
- <item> imap_check </item>
- <item> imap_clearflag_full </item>
- <item> imap_close </item>
- <item> imap_createmailbox </item>
- <item> imap_delete </item>
- <item> imap_deletemailbox </item>
- <item> imap_errors </item>
- <item> imap_expunge </item>
- <item> imap_fetch_overview </item>
- <item> imap_fetchbody </item>
- <item> imap_fetchheader </item>
- <item> imap_fetchstructure </item>
- <item> imap_get_quota </item>
- <item> imap_getmailboxes </item>
- <item> imap_getsubscribed </item>
- <item> imap_header </item>
- <item> imap_headerinfo </item>
- <item> imap_headers </item>
- <item> imap_last_error </item>
- <item> imap_listmailbox </item>
- <item> imap_listsubscribed </item>
- <item> imap_mail </item>
- <item> imap_mail_compose </item>
- <item> imap_mail_copy </item>
- <item> imap_mail_move </item>
- <item> imap_mailboxmsginfo </item>
- <item> imap_mime_header_decode </item>
- <item> imap_msgno </item>
- <item> imap_num_msg </item>
- <item> imap_num_recent </item>
- <item> imap_open </item>
- <item> imap_ping </item>
- <item> imap_popen </item>
- <item> imap_qprint </item>
- <item> imap_renamemailbox </item>
- <item> imap_reopen </item>
- <item> imap_rfc822_parse_adrlist </item>
- <item> imap_rfc822_parse_headers </item>
- <item> imap_rfc822_write_address </item>
- <item> imap_scanmailbox </item>
- <item> imap_search </item>
- <item> imap_set_quota </item>
- <item> imap_setacl </item>
- <item> imap_setflag_full </item>
- <item> imap_sort </item>
- <item> imap_status </item>
- <item> imap_subscribe </item>
- <item> imap_thread </item>
- <item> imap_uid </item>
- <item> imap_undelete </item>
- <item> imap_unsubscribe </item>
- <item> imap_utf7_decode </item>
- <item> imap_utf7_encode </item>
- <item> imap_utf8 </item>
- <item> implode </item>
- <item> import_request_variables </item>
- <item> in_array </item>
- <item> include </item>
- <item> include_once </item>
- <item> ingres_autocommit </item>
- <item> ingres_close </item>
- <item> ingres_commit </item>
- <item> ingres_connect </item>
- <item> ingres_fetch_array </item>
- <item> ingres_fetch_object </item>
- <item> ingres_fetch_row </item>
- <item> ingres_field_length </item>
- <item> ingres_field_name </item>
- <item> ingres_field_nullable </item>
- <item> ingres_field_precision </item>
- <item> ingres_field_scale </item>
- <item> ingres_field_type </item>
- <item> ingres_num_fields </item>
- <item> ingres_num_rows </item>
- <item> ingres_pconnect </item>
- <item> ingres_query </item>
- <item> ingres_rollback </item>
- <item> ini_alter </item>
- <item> ini_get </item>
- <item> ini_get_all </item>
- <item> ini_restore </item>
- <item> ini_set </item>
- <item> intval </item>
- <item> ip2long </item>
- <item> iptcembed </item>
- <item> iptcparse </item>
- <item> ircg_channel_mode </item>
- <item> ircg_disconnect </item>
- <item> ircg_fetch_error_msg </item>
- <item> ircg_get_username </item>
- <item> ircg_html_encode </item>
- <item> ircg_ignore_add </item>
- <item> ircg_ignore_del </item>
- <item> ircg_is_conn_alive </item>
- <item> ircg_join </item>
- <item> ircg_kick </item>
- <item> ircg_lookup_format_messages </item>
- <item> ircg_msg </item>
- <item> ircg_nick </item>
- <item> ircg_nickname_escape </item>
- <item> ircg_nickname_unescape </item>
- <item> ircg_notice </item>
- <item> ircg_part </item>
- <item> ircg_pconnect </item>
- <item> ircg_register_format_messages </item>
- <item> ircg_set_current </item>
- <item> ircg_set_file </item>
- <item> ircg_set_on_die </item>
- <item> ircg_topic </item>
- <item> ircg_whois </item>
- <item> is_a </item>
- <item> is_array </item>
- <item> is_bool </item>
- <item> is_callable </item>
- <item> is_dir </item>
- <item> is_double </item>
- <item> is_executable </item>
- <item> is_file </item>
- <item> is_finite </item>
- <item> is_float </item>
- <item> is_infinite </item>
- <item> is_int </item>
- <item> is_integer </item>
- <item> is_link </item>
- <item> is_long </item>
- <item> is_nan </item>
- <item> is_null </item>
- <item> is_numeric </item>
- <item> is_object </item>
- <item> is_readable </item>
- <item> is_real </item>
- <item> is_resource </item>
- <item> is_scalar </item>
- <item> is_string </item>
- <item> is_subclass_of </item>
- <item> is_uploaded_file </item>
- <item> is_writable </item>
- <item> is_writeable </item>
- <item> isset </item>
- <item> java_last_exception_clear </item>
- <item> java_last_exception_get </item>
- <item> jddayofweek </item>
- <item> jdmonthname </item>
- <item> jdtofrench </item>
- <item> jdtogregorian </item>
- <item> jdtojewish </item>
- <item> jdtojulian </item>
- <item> jdtounix </item>
- <item> jewishtojd </item>
- <item> join </item>
- <item> jpeg2wbmp </item>
- <item> juliantojd </item>
- <item> key </item>
- <item> krsort </item>
- <item> ksort </item>
- <item> lcg_value </item>
- <item> ldap_8859_to_t61 </item>
- <item> ldap_add </item>
- <item> ldap_bind </item>
- <item> ldap_close </item>
- <item> ldap_compare </item>
- <item> ldap_connect </item>
- <item> ldap_count_entries </item>
- <item> ldap_delete </item>
- <item> ldap_dn2ufn </item>
- <item> ldap_err2str </item>
- <item> ldap_errno </item>
- <item> ldap_error </item>
- <item> ldap_explode_dn </item>
- <item> ldap_first_attribute </item>
- <item> ldap_first_entry </item>
- <item> ldap_first_reference </item>
- <item> ldap_free_result </item>
- <item> ldap_get_attributes </item>
- <item> ldap_get_dn </item>
- <item> ldap_get_entries </item>
- <item> ldap_get_option </item>
- <item> ldap_get_values </item>
- <item> ldap_get_values_len </item>
- <item> ldap_list </item>
- <item> ldap_mod_add </item>
- <item> ldap_mod_del </item>
- <item> ldap_mod_replace </item>
- <item> ldap_modify </item>
- <item> ldap_next_attribute </item>
- <item> ldap_next_entry </item>
- <item> ldap_next_reference </item>
- <item> ldap_parse_reference </item>
- <item> ldap_parse_result </item>
- <item> ldap_read </item>
- <item> ldap_rename </item>
- <item> ldap_search </item>
- <item> ldap_set_option </item>
- <item> ldap_set_rebind_proc </item>
- <item> ldap_sort </item>
- <item> ldap_start_tls </item>
- <item> ldap_t61_to_8859 </item>
- <item> ldap_unbind </item>
- <item> leak </item>
- <item> levenshtein </item>
- <item> link </item>
- <item> linkinfo </item>
- <item> list </item>
- <item> localeconv </item>
- <item> localtime </item>
- <item> log </item>
- <item> log10 </item>
- <item> log1p </item>
- <item> long2ip </item>
- <item> lstat </item>
- <item> ltrim </item>
- <item> mail </item>
- <item> mailparse_determine_best_xfer_encoding </item>
- <item> mailparse_msg_create </item>
- <item> mailparse_msg_extract_part </item>
- <item> mailparse_msg_extract_part_file </item>
- <item> mailparse_msg_free </item>
- <item> mailparse_msg_get_part </item>
- <item> mailparse_msg_get_part_data </item>
- <item> mailparse_msg_get_structure </item>
- <item> mailparse_msg_parse </item>
- <item> mailparse_msg_parse_file </item>
- <item> mailparse_rfc822_parse_addresses </item>
- <item> mailparse_stream_encode </item>
- <item> mailparse_uudecode_all </item>
- <item> max </item>
- <item> mb_convert_encoding </item>
- <item> mb_convert_kana </item>
- <item> mb_convert_variables </item>
- <item> mb_decode_mimeheader </item>
- <item> mb_decode_numericentity </item>
- <item> mb_detect_encoding </item>
- <item> mb_detect_order </item>
- <item> mb_encode_mimeheader </item>
- <item> mb_encode_numericentity </item>
- <item> mb_ereg </item>
- <item> mb_ereg_match </item>
- <item> mb_ereg_replace </item>
- <item> mb_ereg_search </item>
- <item> mb_ereg_search_getpos </item>
- <item> mb_ereg_search_getregs </item>
- <item> mb_ereg_search_init </item>
- <item> mb_ereg_search_pos </item>
- <item> mb_ereg_search_regs </item>
- <item> mb_ereg_search_setpos </item>
- <item> mb_eregi </item>
- <item> mb_eregi_replace </item>
- <item> mb_get_info </item>
- <item> mb_http_input </item>
- <item> mb_http_output </item>
- <item> mb_internal_encoding </item>
- <item> mb_language </item>
- <item> mb_output_handler </item>
- <item> mb_parse_str </item>
- <item> mb_preferred_mime_name </item>
- <item> mb_regex_encoding </item>
- <item> mb_send_mail </item>
- <item> mb_split </item>
- <item> mb_strcut </item>
- <item> mb_strimwidth </item>
- <item> mb_strlen </item>
- <item> mb_strpos </item>
- <item> mb_strrpos </item>
- <item> mb_strwidth </item>
- <item> mb_substitute_character </item>
- <item> mb_substr </item>
- <item> mcal_append_event </item>
- <item> mcal_close </item>
- <item> mcal_create_calendar </item>
- <item> mcal_date_compare </item>
- <item> mcal_date_valid </item>
- <item> mcal_day_of_week </item>
- <item> mcal_day_of_year </item>
- <item> mcal_days_in_month </item>
- <item> mcal_delete_calendar </item>
- <item> mcal_delete_event </item>
- <item> mcal_event_add_attribute </item>
- <item> mcal_event_init </item>
- <item> mcal_event_set_alarm </item>
- <item> mcal_event_set_category </item>
- <item> mcal_event_set_class </item>
- <item> mcal_event_set_description </item>
- <item> mcal_event_set_end </item>
- <item> mcal_event_set_recur_daily </item>
- <item> mcal_event_set_recur_monthly_mday </item>
- <item> mcal_event_set_recur_monthly_wday </item>
- <item> mcal_event_set_recur_none </item>
- <item> mcal_event_set_recur_weekly </item>
- <item> mcal_event_set_recur_yearly </item>
- <item> mcal_event_set_start </item>
- <item> mcal_event_set_title </item>
- <item> mcal_expunge </item>
- <item> mcal_fetch_current_stream_event </item>
- <item> mcal_fetch_event </item>
- <item> mcal_is_leap_year </item>
- <item> mcal_list_alarms </item>
- <item> mcal_list_events </item>
- <item> mcal_next_recurrence </item>
- <item> mcal_open </item>
- <item> mcal_popen </item>
- <item> mcal_rename_calendar </item>
- <item> mcal_reopen </item>
- <item> mcal_snooze </item>
- <item> mcal_store_event </item>
- <item> mcal_time_valid </item>
- <item> mcal_week_of_year </item>
- <item> mcrypt_cbc </item>
- <item> mcrypt_cfb </item>
- <item> mcrypt_create_iv </item>
- <item> mcrypt_decrypt </item>
- <item> mcrypt_ecb </item>
- <item> mcrypt_enc_get_algorithms_name </item>
- <item> mcrypt_enc_get_block_size </item>
- <item> mcrypt_enc_get_iv_size </item>
- <item> mcrypt_enc_get_key_size </item>
- <item> mcrypt_enc_get_modes_name </item>
- <item> mcrypt_enc_get_supported_key_sizes </item>
- <item> mcrypt_enc_is_block_algorithm </item>
- <item> mcrypt_enc_is_block_algorithm_mode </item>
- <item> mcrypt_enc_is_block_mode </item>
- <item> mcrypt_enc_self_test </item>
- <item> mcrypt_encrypt </item>
- <item> mcrypt_generic </item>
- <item> mcrypt_generic_deinit </item>
- <item> mcrypt_generic_end </item>
- <item> mcrypt_generic_init </item>
- <item> mcrypt_get_block_size </item>
- <item> mcrypt_get_cipher_name </item>
- <item> mcrypt_get_iv_size </item>
- <item> mcrypt_get_key_size </item>
- <item> mcrypt_list_algorithms </item>
- <item> mcrypt_list_modes </item>
- <item> mcrypt_module_close </item>
- <item> mcrypt_module_get_algo_block_size </item>
- <item> mcrypt_module_get_algo_key_size </item>
- <item> mcrypt_module_get_supported_key_sizes </item>
- <item> mcrypt_module_is_block_algorithm </item>
- <item> mcrypt_module_is_block_algorithm_mode </item>
- <item> mcrypt_module_is_block_mode </item>
- <item> mcrypt_module_open </item>
- <item> mcrypt_module_self_test </item>
- <item> mcrypt_ofb </item>
- <item> md5 </item>
- <item> md5_file </item>
- <item> mdecrypt_generic </item>
- <item> metaphone </item>
- <item> method_exists </item>
- <item> mhash </item>
- <item> mhash_count </item>
- <item> mhash_get_block_size </item>
- <item> mhash_get_hash_name </item>
- <item> mhash_keygen_s2k </item>
- <item> microtime </item>
- <item> min </item>
- <item> ming_setcubicthreshold </item>
- <item> ming_setscale </item>
- <item> ming_useswfversion </item>
- <item> mkdir </item>
- <item> mktime </item>
- <item> move_uploaded_file </item>
- <item> msession_connect </item>
- <item> msession_count </item>
- <item> msession_create </item>
- <item> msession_destroy </item>
- <item> msession_disconnect </item>
- <item> msession_find </item>
- <item> msession_get </item>
- <item> msession_get_array </item>
- <item> msession_getdata </item>
- <item> msession_inc </item>
- <item> msession_list </item>
- <item> msession_listvar </item>
- <item> msession_lock </item>
- <item> msession_plugin </item>
- <item> msession_randstr </item>
- <item> msession_set </item>
- <item> msession_set_array </item>
- <item> msession_setdata </item>
- <item> msession_timeout </item>
- <item> msession_uniq </item>
- <item> msession_unlock </item>
- <item> msql </item>
- <item> msql_affected_rows </item>
- <item> msql_close </item>
- <item> msql_connect </item>
- <item> msql_create_db </item>
- <item> msql_createdb </item>
- <item> msql_data_seek </item>
- <item> msql_dbname </item>
- <item> msql_drop_db </item>
- <item> msql_dropdb </item>
- <item> msql_error </item>
- <item> msql_fetch_array </item>
- <item> msql_fetch_field </item>
- <item> msql_fetch_object </item>
- <item> msql_fetch_row </item>
- <item> msql_field_seek </item>
- <item> msql_fieldflags </item>
- <item> msql_fieldlen </item>
- <item> msql_fieldname </item>
- <item> msql_fieldtable </item>
- <item> msql_fieldtype </item>
- <item> msql_free_result </item>
- <item> msql_freeresult </item>
- <item> msql_list_dbs </item>
- <item> msql_list_fields </item>
- <item> msql_list_tables </item>
- <item> msql_listdbs </item>
- <item> msql_listfields </item>
- <item> msql_listtables </item>
- <item> msql_num_fields </item>
- <item> msql_num_rows </item>
- <item> msql_numfields </item>
- <item> msql_numrows </item>
- <item> msql_pconnect </item>
- <item> msql_query </item>
- <item> msql_regcase </item>
- <item> msql_result </item>
- <item> msql_select_db </item>
- <item> msql_selectdb </item>
- <item> msql_tablename </item>
- <item> mssql_bind </item>
- <item> mssql_close </item>
- <item> mssql_connect </item>
- <item> mssql_data_seek </item>
- <item> mssql_execute </item>
- <item> mssql_fetch_array </item>
- <item> mssql_fetch_assoc </item>
- <item> mssql_fetch_batch </item>
- <item> mssql_fetch_field </item>
- <item> mssql_fetch_object </item>
- <item> mssql_fetch_row </item>
- <item> mssql_field_length </item>
- <item> mssql_field_name </item>
- <item> mssql_field_seek </item>
- <item> mssql_field_type </item>
- <item> mssql_free_result </item>
- <item> mssql_get_last_message </item>
- <item> mssql_guid_string </item>
- <item> mssql_init </item>
- <item> mssql_min_error_severity </item>
- <item> mssql_min_message_severity </item>
- <item> mssql_next_result </item>
- <item> mssql_num_fields </item>
- <item> mssql_num_rows </item>
- <item> mssql_pconnect </item>
- <item> mssql_query </item>
- <item> mssql_result </item>
- <item> mssql_rows_affected </item>
- <item> mssql_select_db </item>
- <item> mt_getrandmax </item>
- <item> mt_rand </item>
- <item> mt_srand </item>
- <item> muscat_close </item>
- <item> muscat_get </item>
- <item> muscat_give </item>
- <item> muscat_setup </item>
- <item> muscat_setup_net </item>
- <item> mysql_affected_rows </item>
- <item> mysql_change_user </item>
- <item> mysql_character_set_name </item>
- <item> mysql_close </item>
- <item> mysql_connect </item>
- <item> mysql_create_db </item>
- <item> mysql_data_seek </item>
- <item> mysql_db_name </item>
- <item> mysql_db_query </item>
- <item> mysql_drop_db </item>
- <item> mysql_errno </item>
- <item> mysql_error </item>
- <item> mysql_escape_string </item>
- <item> mysql_fetch_array </item>
- <item> mysql_fetch_assoc </item>
- <item> mysql_fetch_field </item>
- <item> mysql_fetch_lengths </item>
- <item> mysql_fetch_object </item>
- <item> mysql_fetch_row </item>
- <item> mysql_field_flags </item>
- <item> mysql_field_len </item>
- <item> mysql_field_name </item>
- <item> mysql_field_seek </item>
- <item> mysql_field_table </item>
- <item> mysql_field_type </item>
- <item> mysql_free_result </item>
- <item> mysql_get_client_info </item>
- <item> mysql_get_host_info </item>
- <item> mysql_get_proto_info </item>
- <item> mysql_get_server_info </item>
- <item> mysql_info </item>
- <item> mysql_insert_id </item>
- <item> mysql_list_dbs </item>
- <item> mysql_list_fields </item>
- <item> mysql_list_processes </item>
- <item> mysql_list_tables </item>
- <item> mysql_num_fields </item>
- <item> mysql_num_rows </item>
- <item> mysql_pconnect </item>
- <item> mysql_ping </item>
- <item> mysql_query </item>
- <item> mysql_real_escape_string </item>
- <item> mysql_result </item>
- <item> mysql_select_db </item>
- <item> mysql_stat </item>
- <item> mysql_tablename </item>
- <item> mysql_thread_id </item>
- <item> mysql_unbuffered_query </item>
- <item> natcasesort </item>
- <item> natsort </item>
- <item> ncurses_addch </item>
- <item> ncurses_addchnstr </item>
- <item> ncurses_addchstr </item>
- <item> ncurses_addnstr </item>
- <item> ncurses_addstr </item>
- <item> ncurses_assume_default_colors </item>
- <item> ncurses_attroff </item>
- <item> ncurses_attron </item>
- <item> ncurses_attrset </item>
- <item> ncurses_baudrate </item>
- <item> ncurses_beep </item>
- <item> ncurses_bkgd </item>
- <item> ncurses_bkgdset </item>
- <item> ncurses_border </item>
- <item> ncurses_can_change_color </item>
- <item> ncurses_cbreak </item>
- <item> ncurses_clear </item>
- <item> ncurses_clrtobot </item>
- <item> ncurses_clrtoeol </item>
- <item> ncurses_color_set </item>
- <item> ncurses_curs_set </item>
- <item> ncurses_def_prog_mode </item>
- <item> ncurses_def_shell_mode </item>
- <item> ncurses_define_key </item>
- <item> ncurses_delay_output </item>
- <item> ncurses_delch </item>
- <item> ncurses_deleteln </item>
- <item> ncurses_delwin </item>
- <item> ncurses_doupdate </item>
- <item> ncurses_echo </item>
- <item> ncurses_echochar </item>
- <item> ncurses_end </item>
- <item> ncurses_erase </item>
- <item> ncurses_erasechar </item>
- <item> ncurses_filter </item>
- <item> ncurses_flash </item>
- <item> ncurses_flushinp </item>
- <item> ncurses_getch </item>
- <item> ncurses_getmouse </item>
- <item> ncurses_halfdelay </item>
- <item> ncurses_has_colors </item>
- <item> ncurses_has_ic </item>
- <item> ncurses_has_il </item>
- <item> ncurses_has_key </item>
- <item> ncurses_hline </item>
- <item> ncurses_inch </item>
- <item> ncurses_init </item>
- <item> ncurses_init_color </item>
- <item> ncurses_init_pair </item>
- <item> ncurses_insch </item>
- <item> ncurses_insdelln </item>
- <item> ncurses_insertln </item>
- <item> ncurses_insstr </item>
- <item> ncurses_instr </item>
- <item> ncurses_isendwin </item>
- <item> ncurses_keyok </item>
- <item> ncurses_killchar </item>
- <item> ncurses_longname </item>
- <item> ncurses_mouseinterval </item>
- <item> ncurses_mousemask </item>
- <item> ncurses_move </item>
- <item> ncurses_mvaddch </item>
- <item> ncurses_mvaddchnstr </item>
- <item> ncurses_mvaddchstr </item>
- <item> ncurses_mvaddnstr </item>
- <item> ncurses_mvaddstr </item>
- <item> ncurses_mvcur </item>
- <item> ncurses_mvdelch </item>
- <item> ncurses_mvgetch </item>
- <item> ncurses_mvhline </item>
- <item> ncurses_mvinch </item>
- <item> ncurses_mvvline </item>
- <item> ncurses_mvwaddstr </item>
- <item> ncurses_napms </item>
- <item> ncurses_newwin </item>
- <item> ncurses_nl </item>
- <item> ncurses_nocbreak </item>
- <item> ncurses_noecho </item>
- <item> ncurses_nonl </item>
- <item> ncurses_noqiflush </item>
- <item> ncurses_noraw </item>
- <item> ncurses_putp </item>
- <item> ncurses_qiflush </item>
- <item> ncurses_raw </item>
- <item> ncurses_refresh </item>
- <item> ncurses_resetty </item>
- <item> ncurses_savetty </item>
- <item> ncurses_scr_dump </item>
- <item> ncurses_scr_init </item>
- <item> ncurses_scr_restore </item>
- <item> ncurses_scr_set </item>
- <item> ncurses_scrl </item>
- <item> ncurses_slk_attr </item>
- <item> ncurses_slk_attroff </item>
- <item> ncurses_slk_attron </item>
- <item> ncurses_slk_attrset </item>
- <item> ncurses_slk_clear </item>
- <item> ncurses_slk_color </item>
- <item> ncurses_slk_init </item>
- <item> ncurses_slk_noutrefresh </item>
- <item> ncurses_slk_refresh </item>
- <item> ncurses_slk_restore </item>
- <item> ncurses_slk_touch </item>
- <item> ncurses_standend </item>
- <item> ncurses_standout </item>
- <item> ncurses_start_color </item>
- <item> ncurses_termattrs </item>
- <item> ncurses_termname </item>
- <item> ncurses_timeout </item>
- <item> ncurses_typeahead </item>
- <item> ncurses_ungetch </item>
- <item> ncurses_ungetmouse </item>
- <item> ncurses_use_default_colors </item>
- <item> ncurses_use_env </item>
- <item> ncurses_use_extended_names </item>
- <item> ncurses_vidattr </item>
- <item> ncurses_vline </item>
- <item> ncurses_wrefresh </item>
- <item> next </item>
- <item> ngettext </item>
- <item> nl2br </item>
- <item> nl_langinfo </item>
- <item> notes_body </item>
- <item> notes_copy_db </item>
- <item> notes_create_db </item>
- <item> notes_create_note </item>
- <item> notes_drop_db </item>
- <item> notes_find_note </item>
- <item> notes_header_info </item>
- <item> notes_list_msgs </item>
- <item> notes_mark_read </item>
- <item> notes_mark_unread </item>
- <item> notes_nav_create </item>
- <item> notes_search </item>
- <item> notes_unread </item>
- <item> notes_version </item>
- <item> number_format </item>
- <item> ob_clean </item>
- <item> ob_end_clean </item>
- <item> ob_end_flush </item>
- <item> ob_flush </item>
- <item> ob_get_contents </item>
- <item> ob_get_length </item>
- <item> ob_get_level </item>
- <item> ob_gzhandler </item>
- <item> ob_iconv_handler </item>
- <item> ob_implicit_flush </item>
- <item> ob_start </item>
- <item> ocibindbyname </item>
- <item> ocicancel </item>
- <item> ocicollappend </item>
- <item> ocicollassign </item>
- <item> ocicollassignelem </item>
- <item> ocicollgetelem </item>
- <item> ocicollmax </item>
- <item> ocicollsize </item>
- <item> ocicolltrim </item>
- <item> ocicolumnisnull </item>
- <item> ocicolumnname </item>
- <item> ocicolumnprecision </item>
- <item> ocicolumnscale </item>
- <item> ocicolumnsize </item>
- <item> ocicolumntype </item>
- <item> ocicolumntyperaw </item>
- <item> ocicommit </item>
- <item> ocidefinebyname </item>
- <item> ocierror </item>
- <item> ociexecute </item>
- <item> ocifetch </item>
- <item> ocifetchinto </item>
- <item> ocifetchstatement </item>
- <item> ocifreecollection </item>
- <item> ocifreecursor </item>
- <item> ocifreedesc </item>
- <item> ocifreestatement </item>
- <item> ociinternaldebug </item>
- <item> ociloadlob </item>
- <item> ocilogoff </item>
- <item> ocilogon </item>
- <item> ocinewcollection </item>
- <item> ocinewcursor </item>
- <item> ocinewdescriptor </item>
- <item> ocinlogon </item>
- <item> ocinumcols </item>
- <item> ociparse </item>
- <item> ociplogon </item>
- <item> ociresult </item>
- <item> ocirollback </item>
- <item> ocirowcount </item>
- <item> ocisavelob </item>
- <item> ocisavelobfile </item>
- <item> ociserverversion </item>
- <item> ocisetprefetch </item>
- <item> ocistatementtype </item>
- <item> ociwritelobtofile </item>
- <item> octdec </item>
- <item> odbc_autocommit </item>
- <item> odbc_binmode </item>
- <item> odbc_close </item>
- <item> odbc_close_all </item>
- <item> odbc_columnprivileges </item>
- <item> odbc_columns </item>
- <item> odbc_commit </item>
- <item> odbc_connect </item>
- <item> odbc_cursor </item>
- <item> odbc_do </item>
- <item> odbc_error </item>
- <item> odbc_errormsg </item>
- <item> odbc_exec </item>
- <item> odbc_execute </item>
- <item> odbc_fetch_array </item>
- <item> odbc_fetch_into </item>
- <item> odbc_fetch_object </item>
- <item> odbc_fetch_row </item>
- <item> odbc_field_len </item>
- <item> odbc_field_name </item>
- <item> odbc_field_num </item>
- <item> odbc_field_precision </item>
- <item> odbc_field_scale </item>
- <item> odbc_field_type </item>
- <item> odbc_foreignkeys </item>
- <item> odbc_free_result </item>
- <item> odbc_gettypeinfo </item>
- <item> odbc_longreadlen </item>
- <item> odbc_next_result </item>
- <item> odbc_num_fields </item>
- <item> odbc_num_rows </item>
- <item> odbc_pconnect </item>
- <item> odbc_prepare </item>
- <item> odbc_primarykeys </item>
- <item> odbc_procedurecolumns </item>
- <item> odbc_procedures </item>
- <item> odbc_result </item>
- <item> odbc_result_all </item>
- <item> odbc_rollback </item>
- <item> odbc_setoption </item>
- <item> odbc_specialcolumns </item>
- <item> odbc_statistics </item>
- <item> odbc_tableprivileges </item>
- <item> odbc_tables </item>
- <item> opendir </item>
- <item> openlog </item>
- <item> openssl_csr_export </item>
- <item> openssl_csr_export_to_file </item>
- <item> openssl_csr_new </item>
- <item> openssl_csr_sign </item>
- <item> openssl_error_string </item>
- <item> openssl_free_key </item>
- <item> openssl_get_privatekey </item>
- <item> openssl_get_publickey </item>
- <item> openssl_open </item>
- <item> openssl_pkcs7_decrypt </item>
- <item> openssl_pkcs7_encrypt </item>
- <item> openssl_pkcs7_sign </item>
- <item> openssl_pkcs7_verify </item>
- <item> openssl_pkey_export </item>
- <item> openssl_pkey_export_to_file </item>
- <item> openssl_pkey_new </item>
- <item> openssl_private_decrypt </item>
- <item> openssl_private_encrypt </item>
- <item> openssl_public_decrypt </item>
- <item> openssl_public_encrypt </item>
- <item> openssl_seal </item>
- <item> openssl_sign </item>
- <item> openssl_verify </item>
- <item> openssl_x509_check_private_key </item>
- <item> openssl_x509_checkpurpose </item>
- <item> openssl_x509_export </item>
- <item> openssl_x509_export_to_file </item>
- <item> openssl_x509_free </item>
- <item> openssl_x509_parse </item>
- <item> openssl_x509_read </item>
- <item> ora_bind </item>
- <item> ora_close </item>
- <item> ora_columnname </item>
- <item> ora_columnsize </item>
- <item> ora_columntype </item>
- <item> ora_commit </item>
- <item> ora_commitoff </item>
- <item> ora_commiton </item>
- <item> ora_do </item>
- <item> ora_error </item>
- <item> ora_errorcode </item>
- <item> ora_exec </item>
- <item> ora_fetch </item>
- <item> ora_fetch_into </item>
- <item> ora_getcolumn </item>
- <item> ora_logoff </item>
- <item> ora_logon </item>
- <item> ora_numcols </item>
- <item> ora_numrows </item>
- <item> ora_open </item>
- <item> ora_parse </item>
- <item> ora_plogon </item>
- <item> ora_rollback </item>
- <item> ord </item>
- <item> overload </item>
- <item> ovrimos_close </item>
- <item> ovrimos_commit </item>
- <item> ovrimos_connect </item>
- <item> ovrimos_cursor </item>
- <item> ovrimos_exec </item>
- <item> ovrimos_execute </item>
- <item> ovrimos_fetch_into </item>
- <item> ovrimos_fetch_row </item>
- <item> ovrimos_field_len </item>
- <item> ovrimos_field_name </item>
- <item> ovrimos_field_num </item>
- <item> ovrimos_field_type </item>
- <item> ovrimos_free_result </item>
- <item> ovrimos_longreadlen </item>
- <item> ovrimos_num_fields </item>
- <item> ovrimos_num_rows </item>
- <item> ovrimos_prepare </item>
- <item> ovrimos_result </item>
- <item> ovrimos_result_all </item>
- <item> ovrimos_rollback </item>
- <item> pack </item>
- <item> parse_ini_file </item>
- <item> parse_str </item>
- <item> parse_url </item>
- <item> passthru </item>
- <item> pathinfo </item>
- <item> pclose </item>
- <item> pcntl_exec </item>
- <item> pcntl_fork </item>
- <item> pcntl_signal </item>
- <item> pcntl_waitpid </item>
- <item> pcntl_wexitstatus </item>
- <item> pcntl_wifexited </item>
- <item> pcntl_wifsignaled </item>
- <item> pcntl_wifstopped </item>
- <item> pcntl_wstopsig </item>
- <item> pcntl_wtermsig </item>
- <item> pdf_add_annotation </item>
- <item> pdf_add_bookmark </item>
- <item> pdf_add_launchlink </item>
- <item> pdf_add_locallink </item>
- <item> pdf_add_note </item>
- <item> pdf_add_outline </item>
- <item> pdf_add_pdflink </item>
- <item> pdf_add_thumbnail </item>
- <item> pdf_add_weblink </item>
- <item> pdf_arc </item>
- <item> pdf_arcn </item>
- <item> pdf_attach_file </item>
- <item> pdf_begin_page </item>
- <item> pdf_begin_pattern </item>
- <item> pdf_begin_template </item>
- <item> pdf_circle </item>
- <item> pdf_clip </item>
- <item> pdf_close </item>
- <item> pdf_close_image </item>
- <item> pdf_close_pdi </item>
- <item> pdf_close_pdi_page </item>
- <item> pdf_closepath </item>
- <item> pdf_closepath_fill_stroke </item>
- <item> pdf_closepath_stroke </item>
- <item> pdf_concat </item>
- <item> pdf_continue_text </item>
- <item> pdf_curveto </item>
- <item> pdf_delete </item>
- <item> pdf_end_page </item>
- <item> pdf_end_pattern </item>
- <item> pdf_end_template </item>
- <item> pdf_endpath </item>
- <item> pdf_fill </item>
- <item> pdf_fill_stroke </item>
- <item> pdf_findfont </item>
- <item> pdf_get_buffer </item>
- <item> pdf_get_font </item>
- <item> pdf_get_fontname </item>
- <item> pdf_get_fontsize </item>
- <item> pdf_get_image_height </item>
- <item> pdf_get_image_width </item>
- <item> pdf_get_majorversion </item>
- <item> pdf_get_minorversion </item>
- <item> pdf_get_parameter </item>
- <item> pdf_get_pdi_parameter </item>
- <item> pdf_get_pdi_value </item>
- <item> pdf_get_value </item>
- <item> pdf_initgraphics </item>
- <item> pdf_lineto </item>
- <item> pdf_makespotcolor </item>
- <item> pdf_moveto </item>
- <item> pdf_new </item>
- <item> pdf_open </item>
- <item> pdf_open_ccitt </item>
- <item> pdf_open_file </item>
- <item> pdf_open_gif </item>
- <item> pdf_open_image </item>
- <item> pdf_open_image_file </item>
- <item> pdf_open_jpeg </item>
- <item> pdf_open_memory_image </item>
- <item> pdf_open_pdi </item>
- <item> pdf_open_pdi_page </item>
- <item> pdf_open_png </item>
- <item> pdf_open_tiff </item>
- <item> pdf_place_image </item>
- <item> pdf_place_pdi_page </item>
- <item> pdf_rect </item>
- <item> pdf_restore </item>
- <item> pdf_rotate </item>
- <item> pdf_save </item>
- <item> pdf_scale </item>
- <item> pdf_set_border_color </item>
- <item> pdf_set_border_dash </item>
- <item> pdf_set_border_style </item>
- <item> pdf_set_char_spacing </item>
- <item> pdf_set_duration </item>
- <item> pdf_set_font </item>
- <item> pdf_set_horiz_scaling </item>
- <item> pdf_set_info </item>
- <item> pdf_set_info_author </item>
- <item> pdf_set_info_creator </item>
- <item> pdf_set_info_keywords </item>
- <item> pdf_set_info_subject </item>
- <item> pdf_set_info_title </item>
- <item> pdf_set_leading </item>
- <item> pdf_set_parameter </item>
- <item> pdf_set_text_pos </item>
- <item> pdf_set_text_rendering </item>
- <item> pdf_set_text_rise </item>
- <item> pdf_set_transition </item>
- <item> pdf_set_value </item>
- <item> pdf_set_word_spacing </item>
- <item> pdf_setcolor </item>
- <item> pdf_setdash </item>
- <item> pdf_setflat </item>
- <item> pdf_setfont </item>
- <item> pdf_setgray </item>
- <item> pdf_setgray_fill </item>
- <item> pdf_setgray_stroke </item>
- <item> pdf_setlinecap </item>
- <item> pdf_setlinejoin </item>
- <item> pdf_setlinewidth </item>
- <item> pdf_setmatrix </item>
- <item> pdf_setmiterlimit </item>
- <item> pdf_setpolydash </item>
- <item> pdf_setrgbcolor </item>
- <item> pdf_setrgbcolor_fill </item>
- <item> pdf_setrgbcolor_stroke </item>
- <item> pdf_show </item>
- <item> pdf_show_boxed </item>
- <item> pdf_show_xy </item>
- <item> pdf_skew </item>
- <item> pdf_stringwidth </item>
- <item> pdf_stroke </item>
- <item> pdf_translate </item>
- <item> pfpro_cleanup </item>
- <item> pfpro_init </item>
- <item> pfpro_process </item>
- <item> pfpro_process_raw </item>
- <item> pfpro_version </item>
- <item> pfsockopen </item>
- <item> pg_affected_rows </item>
- <item> pg_cancel_query </item>
- <item> pg_client_encoding </item>
- <item> pg_close </item>
- <item> pg_connect </item>
- <item> pg_connection_busy </item>
- <item> pg_connection_reset </item>
- <item> pg_connection_status </item>
- <item> pg_copy_from </item>
- <item> pg_copy_to </item>
- <item> pg_dbname </item>
- <item> pg_end_copy </item>
- <item> pg_escape_bytea </item>
- <item> pg_escape_string </item>
- <item> pg_fetch_array </item>
- <item> pg_fetch_object </item>
- <item> pg_fetch_result </item>
- <item> pg_fetch_row </item>
- <item> pg_field_is_null </item>
- <item> pg_field_name </item>
- <item> pg_field_num </item>
- <item> pg_field_prtlen </item>
- <item> pg_field_size </item>
- <item> pg_field_type </item>
- <item> pg_free_result </item>
- <item> pg_get_result </item>
- <item> pg_host </item>
- <item> pg_last_error </item>
- <item> pg_last_notice </item>
- <item> pg_last_oid </item>
- <item> pg_lo_close </item>
- <item> pg_lo_create </item>
- <item> pg_lo_export </item>
- <item> pg_lo_import </item>
- <item> pg_lo_open </item>
- <item> pg_lo_read </item>
- <item> pg_lo_read_all </item>
- <item> pg_lo_seek </item>
- <item> pg_lo_tell </item>
- <item> pg_lo_unlink </item>
- <item> pg_lo_write </item>
- <item> pg_num_fields </item>
- <item> pg_num_rows </item>
- <item> pg_options </item>
- <item> pg_pconnect </item>
- <item> pg_port </item>
- <item> pg_put_line </item>
- <item> pg_query </item>
- <item> pg_result_error </item>
- <item> pg_result_status </item>
- <item> pg_send_query </item>
- <item> pg_set_client_encoding </item>
- <item> pg_trace </item>
- <item> pg_tty </item>
- <item> pg_untrace </item>
- <item> php_logo_guid </item>
- <item> php_sapi_name </item>
- <item> php_uname </item>
- <item> phpcredits </item>
- <item> phpinfo </item>
- <item> phpversion </item>
- <item> pi </item>
- <item> png2wbmp </item>
- <item> popen </item>
- <item> pos </item>
- <item> posix_ctermid </item>
- <item> posix_getcwd </item>
- <item> posix_getegid </item>
- <item> posix_geteuid </item>
- <item> posix_getgid </item>
- <item> posix_getgrgid </item>
- <item> posix_getgrnam </item>
- <item> posix_getgroups </item>
- <item> posix_getlogin </item>
- <item> posix_getpgid </item>
- <item> posix_getpgrp </item>
- <item> posix_getpid </item>
- <item> posix_getppid </item>
- <item> posix_getpwnam </item>
- <item> posix_getpwuid </item>
- <item> posix_getrlimit </item>
- <item> posix_getsid </item>
- <item> posix_getuid </item>
- <item> posix_isatty </item>
- <item> posix_kill </item>
- <item> posix_mkfifo </item>
- <item> posix_setegid </item>
- <item> posix_seteuid </item>
- <item> posix_setgid </item>
- <item> posix_setpgid </item>
- <item> posix_setsid </item>
- <item> posix_setuid </item>
- <item> posix_times </item>
- <item> posix_ttyname </item>
- <item> posix_uname </item>
- <item> pow </item>
- <item> preg_grep </item>
- <item> preg_match </item>
- <item> preg_match_all </item>
- <item> preg_quote </item>
- <item> preg_replace </item>
- <item> preg_replace_callback </item>
- <item> preg_split </item>
- <item> prev </item>
- <item> print </item>
- <item> print_r </item>
- <item> printer_abort </item>
- <item> printer_close </item>
- <item> printer_create_brush </item>
- <item> printer_create_dc </item>
- <item> printer_create_font </item>
- <item> printer_create_pen </item>
- <item> printer_delete_brush </item>
- <item> printer_delete_dc </item>
- <item> printer_delete_font </item>
- <item> printer_delete_pen </item>
- <item> printer_draw_bmp </item>
- <item> printer_draw_chord </item>
- <item> printer_draw_elipse </item>
- <item> printer_draw_line </item>
- <item> printer_draw_pie </item>
- <item> printer_draw_rectangle </item>
- <item> printer_draw_roundrect </item>
- <item> printer_draw_text </item>
- <item> printer_end_doc </item>
- <item> printer_end_page </item>
- <item> printer_get_option </item>
- <item> printer_list </item>
- <item> printer_logical_fontheight </item>
- <item> printer_open </item>
- <item> printer_select_brush </item>
- <item> printer_select_font </item>
- <item> printer_select_pen </item>
- <item> printer_set_option </item>
- <item> printer_start_doc </item>
- <item> printer_start_page </item>
- <item> printer_write </item>
- <item> printf </item>
- <item> pspell_add_to_personal </item>
- <item> pspell_add_to_session </item>
- <item> pspell_check </item>
- <item> pspell_clear_session </item>
- <item> pspell_config_create </item>
- <item> pspell_config_ignore </item>
- <item> pspell_config_mode </item>
- <item> pspell_config_personal </item>
- <item> pspell_config_repl </item>
- <item> pspell_config_runtogether </item>
- <item> pspell_config_save_repl </item>
- <item> pspell_new </item>
- <item> pspell_new_config </item>
- <item> pspell_new_personal </item>
- <item> pspell_save_wordlist </item>
- <item> pspell_store_replacement </item>
- <item> pspell_suggest </item>
- <item> putenv </item>
- <item> qdom_error </item>
- <item> qdom_tree </item>
- <item> quoted_printable_decode </item>
- <item> quotemeta </item>
- <item> rad2deg </item>
- <item> rand </item>
- <item> range </item>
- <item> rawurldecode </item>
- <item> rawurlencode </item>
- <item> read_exif_data </item>
- <item> readdir </item>
- <item> readfile </item>
- <item> readgzfile </item>
- <item> readline </item>
- <item> readline_add_history </item>
- <item> readline_clear_history </item>
- <item> readline_completion_function </item>
- <item> readline_info </item>
- <item> readline_list_history </item>
- <item> readline_read_history </item>
- <item> readline_write_history </item>
- <item> readlink </item>
- <item> realpath </item>
- <item> recode </item>
- <item> recode_file </item>
- <item> recode_string </item>
- <item> register_shutdown_function </item>
- <item> register_tick_function </item>
- <item> rename </item>
- <item> require </item>
- <item> require_once </item>
- <item> reset </item>
- <item> restore_error_handler </item>
- <item> return </item>
- <item> rewind </item>
- <item> rewinddir </item>
- <item> rmdir </item>
- <item> round </item>
- <item> rsort </item>
- <item> rtrim </item>
- <item> sem_acquire </item>
- <item> sem_get </item>
- <item> sem_release </item>
- <item> sem_remove </item>
- <item> serialize </item>
- <item> sesam_affected_rows </item>
- <item> sesam_commit </item>
- <item> sesam_connect </item>
- <item> sesam_diagnostic </item>
- <item> sesam_disconnect </item>
- <item> sesam_errormsg </item>
- <item> sesam_execimm </item>
- <item> sesam_fetch_array </item>
- <item> sesam_fetch_result </item>
- <item> sesam_fetch_row </item>
- <item> sesam_field_array </item>
- <item> sesam_field_name </item>
- <item> sesam_free_result </item>
- <item> sesam_num_fields </item>
- <item> sesam_query </item>
- <item> sesam_rollback </item>
- <item> sesam_seek_row </item>
- <item> sesam_settransaction </item>
- <item> session_cache_expire </item>
- <item> session_cache_limiter </item>
- <item> session_decode </item>
- <item> session_destroy </item>
- <item> session_encode </item>
- <item> session_get_cookie_params </item>
- <item> session_id </item>
- <item> session_is_registered </item>
- <item> session_module_name </item>
- <item> session_name </item>
- <item> session_register </item>
- <item> session_save_path </item>
- <item> session_set_cookie_params </item>
- <item> session_set_save_handler </item>
- <item> session_start </item>
- <item> session_unregister </item>
- <item> session_unset </item>
- <item> session_write_close </item>
- <item> set_error_handler </item>
- <item> set_file_buffer </item>
- <item> set_magic_quotes_runtime </item>
- <item> set_time_limit </item>
- <item> setcookie </item>
- <item> setlocale </item>
- <item> settype </item>
- <item> shell_exec </item>
- <item> shm_attach </item>
- <item> shm_detach </item>
- <item> shm_get_var </item>
- <item> shm_put_var </item>
- <item> shm_remove </item>
- <item> shm_remove_var </item>
- <item> shmop_close </item>
- <item> shmop_delete </item>
- <item> shmop_open </item>
- <item> shmop_read </item>
- <item> shmop_size </item>
- <item> shmop_write </item>
- <item> show_source </item>
- <item> shuffle </item>
- <item> similar_text </item>
- <item> sin </item>
- <item> sinh </item>
- <item> sizeof </item>
- <item> sleep </item>
- <item> snmp_get_quick_print </item>
- <item> snmp_set_quick_print </item>
- <item> snmpget </item>
- <item> snmprealwalk </item>
- <item> snmpset </item>
- <item> snmpwalk </item>
- <item> snmpwalkoid </item>
- <item> socket_accept </item>
- <item> socket_bind </item>
- <item> socket_close </item>
- <item> socket_connect </item>
- <item> socket_create </item>
- <item> socket_create_listen </item>
- <item> socket_create_pair </item>
- <item> socket_fd_alloc </item>
- <item> socket_fd_clear </item>
- <item> socket_fd_free </item>
- <item> socket_fd_isset </item>
- <item> socket_fd_set </item>
- <item> socket_fd_zero </item>
- <item> socket_get_status </item>
- <item> socket_getopt </item>
- <item> socket_getpeername </item>
- <item> socket_getsockname </item>
- <item> socket_iovec_add </item>
- <item> socket_iovec_alloc </item>
- <item> socket_iovec_delete </item>
- <item> socket_iovec_fetch </item>
- <item> socket_iovec_free </item>
- <item> socket_iovec_set </item>
- <item> socket_last_error </item>
- <item> socket_listen </item>
- <item> socket_read </item>
- <item> socket_readv </item>
- <item> socket_recv </item>
- <item> socket_recvfrom </item>
- <item> socket_recvmsg </item>
- <item> socket_select </item>
- <item> socket_send </item>
- <item> socket_sendmsg </item>
- <item> socket_sendto </item>
- <item> socket_set_blocking </item>
- <item> socket_set_nonblock </item>
- <item> socket_set_timeout </item>
- <item> socket_setopt </item>
- <item> socket_shutdown </item>
- <item> socket_strerror </item>
- <item> socket_write </item>
- <item> socket_writev </item>
- <item> sort </item>
- <item> soundex </item>
- <item> split </item>
- <item> spliti </item>
- <item> sprintf </item>
- <item> sql_regcase </item>
- <item> sqrt </item>
- <item> srand </item>
- <item> sscanf </item>
- <item> stat </item>
- <item> str_pad </item>
- <item> str_repeat </item>
- <item> str_replace </item>
- <item> str_rot13 </item>
- <item> strcasecmp </item>
- <item> strchr </item>
- <item> strcmp </item>
- <item> strcoll </item>
- <item> strcspn </item>
- <item> strftime </item>
- <item> strip_tags </item>
- <item> stripcslashes </item>
- <item> stripslashes </item>
- <item> stristr </item>
- <item> strlen </item>
- <item> strnatcasecmp </item>
- <item> strnatcmp </item>
- <item> strncasecmp </item>
- <item> strncmp </item>
- <item> strpos </item>
- <item> strrchr </item>
- <item> strrev </item>
- <item> strrpos </item>
- <item> strspn </item>
- <item> strstr </item>
- <item> strtok </item>
- <item> strtolower </item>
- <item> strtotime </item>
- <item> strtoupper </item>
- <item> strtr </item>
- <item> strval </item>
- <item> substr </item>
- <item> substr_count </item>
- <item> substr_replace </item>
- <item> swf_actiongeturl </item>
- <item> swf_actiongotoframe </item>
- <item> swf_actiongotolabel </item>
- <item> swf_actionnextframe </item>
- <item> swf_actionplay </item>
- <item> swf_actionprevframe </item>
- <item> swf_actionsettarget </item>
- <item> swf_actionstop </item>
- <item> swf_actiontogglequality </item>
- <item> swf_actionwaitforframe </item>
- <item> swf_addbuttonrecord </item>
- <item> swf_addcolor </item>
- <item> swf_closefile </item>
- <item> swf_definebitmap </item>
- <item> swf_definefont </item>
- <item> swf_defineline </item>
- <item> swf_definepoly </item>
- <item> swf_definerect </item>
- <item> swf_definetext </item>
- <item> swf_endbutton </item>
- <item> swf_enddoaction </item>
- <item> swf_endshape </item>
- <item> swf_endsymbol </item>
- <item> swf_fontsize </item>
- <item> swf_fontslant </item>
- <item> swf_fonttracking </item>
- <item> swf_getbitmapinfo </item>
- <item> swf_getfontinfo </item>
- <item> swf_getframe </item>
- <item> swf_labelframe </item>
- <item> swf_lookat </item>
- <item> swf_modifyobject </item>
- <item> swf_mulcolor </item>
- <item> swf_nextid </item>
- <item> swf_oncondition </item>
- <item> swf_openfile </item>
- <item> swf_ortho </item>
- <item> swf_ortho2 </item>
- <item> swf_perspective </item>
- <item> swf_placeobject </item>
- <item> swf_polarview </item>
- <item> swf_popmatrix </item>
- <item> swf_posround </item>
- <item> swf_pushmatrix </item>
- <item> swf_removeobject </item>
- <item> swf_rotate </item>
- <item> swf_scale </item>
- <item> swf_setfont </item>
- <item> swf_setframe </item>
- <item> swf_shapearc </item>
- <item> swf_shapecurveto </item>
- <item> swf_shapecurveto3 </item>
- <item> swf_shapefillbitmapclip </item>
- <item> swf_shapefillbitmaptile </item>
- <item> swf_shapefilloff </item>
- <item> swf_shapefillsolid </item>
- <item> swf_shapelinesolid </item>
- <item> swf_shapelineto </item>
- <item> swf_shapemoveto </item>
- <item> swf_showframe </item>
- <item> swf_startbutton </item>
- <item> swf_startdoaction </item>
- <item> swf_startshape </item>
- <item> swf_startsymbol </item>
- <item> swf_textwidth </item>
- <item> swf_translate </item>
- <item> swf_viewport </item>
- <item> swfaction </item>
- <item> swfbitmap </item>
- <item> swfbitmap.getheight </item>
- <item> swfbitmap.getwidth </item>
- <item> swfbutton </item>
- <item> swfbutton.addaction </item>
- <item> swfbutton.addshape </item>
- <item> swfbutton.setaction </item>
- <item> swfbutton.setdown </item>
- <item> swfbutton.sethit </item>
- <item> swfbutton.setover </item>
- <item> swfbutton.setup </item>
- <item> swfbutton_keypress </item>
- <item> swfdisplayitem </item>
- <item> swfdisplayitem.addcolor </item>
- <item> swfdisplayitem.move </item>
- <item> swfdisplayitem.moveto </item>
- <item> swfdisplayitem.multcolor </item>
- <item> swfdisplayitem.remove </item>
- <item> swfdisplayitem.rotate </item>
- <item> swfdisplayitem.rotateto </item>
- <item> swfdisplayitem.scale </item>
- <item> swfdisplayitem.scaleto </item>
- <item> swfdisplayitem.setdepth </item>
- <item> swfdisplayitem.setname </item>
- <item> swfdisplayitem.setratio </item>
- <item> swfdisplayitem.skewx </item>
- <item> swfdisplayitem.skewxto </item>
- <item> swfdisplayitem.skewy </item>
- <item> swfdisplayitem.skewyto </item>
- <item> swffill </item>
- <item> swffill.moveto </item>
- <item> swffill.rotateto </item>
- <item> swffill.scaleto </item>
- <item> swffill.skewxto </item>
- <item> swffill.skewyto </item>
- <item> swffont </item>
- <item> swffont.getwidth </item>
- <item> swfgradient </item>
- <item> swfgradient.addentry </item>
- <item> swfmorph </item>
- <item> swfmorph.getshape1 </item>
- <item> swfmorph.getshape2 </item>
- <item> swfmovie </item>
- <item> swfmovie.add </item>
- <item> swfmovie.nextframe </item>
- <item> swfmovie.output </item>
- <item> swfmovie.remove </item>
- <item> swfmovie.save </item>
- <item> swfmovie.setbackground </item>
- <item> swfmovie.setdimension </item>
- <item> swfmovie.setframes </item>
- <item> swfmovie.setrate </item>
- <item> swfmovie.streammp3 </item>
- <item> swfshape </item>
- <item> swfshape.addfill </item>
- <item> swfshape.drawcurve </item>
- <item> swfshape.drawcurveto </item>
- <item> swfshape.drawline </item>
- <item> swfshape.drawlineto </item>
- <item> swfshape.movepen </item>
- <item> swfshape.movepento </item>
- <item> swfshape.setleftfill </item>
- <item> swfshape.setline </item>
- <item> swfshape.setrightfill </item>
- <item> swfsprite </item>
- <item> swfsprite.add </item>
- <item> swfsprite.nextframe </item>
- <item> swfsprite.remove </item>
- <item> swfsprite.setframes </item>
- <item> swftext </item>
- <item> swftext.addstring </item>
- <item> swftext.getwidth </item>
- <item> swftext.moveto </item>
- <item> swftext.setcolor </item>
- <item> swftext.setfont </item>
- <item> swftext.setheight </item>
- <item> swftext.setspacing </item>
- <item> swftextfield </item>
- <item> swftextfield.addstring </item>
- <item> swftextfield.align </item>
- <item> swftextfield.setbounds </item>
- <item> swftextfield.setcolor </item>
- <item> swftextfield.setfont </item>
- <item> swftextfield.setheight </item>
- <item> swftextfield.setindentation </item>
- <item> swftextfield.setleftmargin </item>
- <item> swftextfield.setlinespacing </item>
- <item> swftextfield.setmargins </item>
- <item> swftextfield.setname </item>
- <item> swftextfield.setrightmargin </item>
- <item> sybase_affected_rows </item>
- <item> sybase_close </item>
- <item> sybase_connect </item>
- <item> sybase_data_seek </item>
- <item> sybase_fetch_array </item>
- <item> sybase_fetch_field </item>
- <item> sybase_fetch_object </item>
- <item> sybase_fetch_row </item>
- <item> sybase_field_seek </item>
- <item> sybase_free_result </item>
- <item> sybase_get_last_message </item>
- <item> sybase_min_client_severity </item>
- <item> sybase_min_error_severity </item>
- <item> sybase_min_message_severity </item>
- <item> sybase_min_server_severity </item>
- <item> sybase_num_fields </item>
- <item> sybase_num_rows </item>
- <item> sybase_pconnect </item>
- <item> sybase_query </item>
- <item> sybase_result </item>
- <item> sybase_select_db </item>
- <item> symlink </item>
- <item> syslog </item>
- <item> system </item>
- <item> tan </item>
- <item> tanh </item>
- <item> tempnam </item>
- <item> textdomain </item>
- <item> time </item>
- <item> tmpfile </item>
- <item> touch </item>
- <item> trigger_error </item>
- <item> trim </item>
- <item> uasort </item>
- <item> ucfirst </item>
- <item> ucwords </item>
- <item> udm_add_search_limit </item>
- <item> udm_alloc_agent </item>
- <item> udm_api_version </item>
- <item> udm_cat_list </item>
- <item> udm_cat_path </item>
- <item> udm_check_charset </item>
- <item> udm_check_stored </item>
- <item> udm_clear_search_limits </item>
- <item> udm_close_stored </item>
- <item> udm_crc32 </item>
- <item> udm_errno </item>
- <item> udm_error </item>
- <item> udm_find </item>
- <item> udm_free_agent </item>
- <item> udm_free_ispell_data </item>
- <item> udm_free_res </item>
- <item> udm_get_doc_count </item>
- <item> udm_get_res_field </item>
- <item> udm_get_res_param </item>
- <item> udm_load_ispell_data </item>
- <item> udm_open_stored </item>
- <item> udm_set_agent_param </item>
- <item> uksort </item>
- <item> umask </item>
- <item> uniqid </item>
- <item> unixtojd </item>
- <item> unlink </item>
- <item> unpack </item>
- <item> unregister_tick_function </item>
- <item> unserialize </item>
- <item> unset </item>
- <item> urldecode </item>
- <item> urlencode </item>
- <item> user_error </item>
- <item> usleep </item>
- <item> usort </item>
- <item> utf8_decode </item>
- <item> utf8_encode </item>
- <item> var_dump </item>
- <item> var_export </item>
- <item> variant </item>
- <item> version_compare </item>
- <item> virtual </item>
- <item> vpopmail_add_alias_domain </item>
- <item> vpopmail_add_alias_domain_ex </item>
- <item> vpopmail_add_domain </item>
- <item> vpopmail_add_domain_ex </item>
- <item> vpopmail_add_user </item>
- <item> vpopmail_alias_add </item>
- <item> vpopmail_alias_del </item>
- <item> vpopmail_alias_del_domain </item>
- <item> vpopmail_alias_get </item>
- <item> vpopmail_alias_get_all </item>
- <item> vpopmail_auth_user </item>
- <item> vpopmail_del_domain </item>
- <item> vpopmail_del_domain_ex </item>
- <item> vpopmail_del_user </item>
- <item> vpopmail_error </item>
- <item> vpopmail_passwd </item>
- <item> vpopmail_set_user_quota </item>
- <item> vprintf </item>
- <item> vsprintf </item>
- <item> w32api_deftype </item>
- <item> w32api_init_dtype </item>
- <item> w32api_invoke_function </item>
- <item> w32api_register_function </item>
- <item> w32api_set_call_method </item>
- <item> wddx_add_vars </item>
- <item> wddx_deserialize </item>
- <item> wddx_packet_end </item>
- <item> wddx_packet_start </item>
- <item> wddx_serialize_value </item>
- <item> wddx_serialize_vars </item>
- <item> wordwrap </item>
- <item> xml_error_string </item>
- <item> xml_get_current_byte_index </item>
- <item> xml_get_current_column_number </item>
- <item> xml_get_current_line_number </item>
- <item> xml_get_error_code </item>
- <item> xml_parse </item>
- <item> xml_parse_into_struct </item>
- <item> xml_parser_create </item>
- <item> xml_parser_create_ns </item>
- <item> xml_parser_free </item>
- <item> xml_parser_get_option </item>
- <item> xml_parser_set_option </item>
- <item> xml_set_character_data_handler </item>
- <item> xml_set_default_handler </item>
- <item> xml_set_element_handler </item>
- <item> xml_set_end_namespace_decl_handler </item>
- <item> xml_set_external_entity_ref_handler </item>
- <item> xml_set_notation_decl_handler </item>
- <item> xml_set_object </item>
- <item> xml_set_processing_instruction_handler </item>
- <item> xml_set_start_namespace_decl_handler </item>
- <item> xml_set_unparsed_entity_decl_handler </item>
- <item> xmldoc </item>
- <item> xmldocfile </item>
- <item> xmlrpc_decode </item>
- <item> xmlrpc_decode_request </item>
- <item> xmlrpc_encode </item>
- <item> xmlrpc_encode_request </item>
- <item> xmlrpc_get_type </item>
- <item> xmlrpc_parse_method_descriptions </item>
- <item> xmlrpc_server_add_introspection_data </item>
- <item> xmlrpc_server_call_method </item>
- <item> xmlrpc_server_create </item>
- <item> xmlrpc_server_destroy </item>
- <item> xmlrpc_server_register_introspection_callback </item>
- <item> xmlrpc_server_register_method </item>
- <item> xmlrpc_set_type </item>
- <item> xmltree </item>
- <item> xpath_eval </item>
- <item> xpath_eval_expression </item>
- <item> xpath_new_context </item>
- <item> xptr_eval </item>
- <item> xptr_new_context </item>
- <item> xslt_create </item>
- <item> xslt_errno </item>
- <item> xslt_error </item>
- <item> xslt_free </item>
- <item> xslt_process </item>
- <item> xslt_set_base </item>
- <item> xslt_set_encoding </item>
- <item> xslt_set_error_handler </item>
- <item> xslt_set_log </item>
- <item> xslt_set_sax_handler </item>
- <item> xslt_set_sax_handlers </item>
- <item> xslt_set_scheme_handler </item>
- <item> xslt_set_scheme_handlers </item>
- <item> yaz_addinfo </item>
- <item> yaz_ccl_conf </item>
- <item> yaz_ccl_parse </item>
- <item> yaz_close </item>
- <item> yaz_connect </item>
- <item> yaz_database </item>
- <item> yaz_element </item>
- <item> yaz_errno </item>
- <item> yaz_error </item>
- <item> yaz_hits </item>
- <item> yaz_itemorder </item>
- <item> yaz_present </item>
- <item> yaz_range </item>
- <item> yaz_record </item>
- <item> yaz_scan </item>
- <item> yaz_scan_result </item>
- <item> yaz_search </item>
- <item> yaz_sort </item>
- <item> yaz_syntax </item>
- <item> yaz_wait </item>
- <item> yp_all </item>
- <item> yp_cat </item>
- <item> yp_err_string </item>
- <item> yp_errno </item>
- <item> yp_first </item>
- <item> yp_get_default_domain </item>
- <item> yp_master </item>
- <item> yp_match </item>
- <item> yp_next </item>
- <item> yp_order </item>
- <item> zend_logo_guid </item>
- <item> zend_version </item>
- <item> zip_close </item>
- <item> zip_entry_close </item>
- <item> zip_entry_compressedsize </item>
- <item> zip_entry_compressionmethod </item>
- <item> zip_entry_filesize </item>
- <item> zip_entry_name </item>
- <item> zip_entry_open </item>
- <item> zip_entry_read </item>
- <item> zip_open </item>
- <item> zip_read </item>
- </list>
- <contexts>
- <context name="nosource" attribute="Normal Text" lineEndContext="#stay">
- <StringDetect attribute="Keyword" context="phpsource" String="&lt;?php" />
- <StringDetect attribute="Keyword" context="phpsource" String="&lt;?" />
- <RegExpr attribute="HTML Tag" context="scripts" String="&lt;\s*script(\s|&gt;)" insensitive="TRUE" />
- <RegExpr attribute="HTML Tag" context="htmltag" String="&lt;\s*\/?\s*[a-zA-Z_:][a-zA-Z0-9._:-]*" />
- <StringDetect attribute="HTML Comment" context="htmlcomment" String="&lt;!--" />
- </context>
- <context name="phpsource" attribute="PHP Text" lineEndContext="#stay">
- <StringDetect attribute="Keyword" context="#pop" String="?&gt;" />
- <DetectChar attribute="Comment" context="php_onelinecomment" char="#" />
- <Detect2Chars attribute="Comment" context="php_onelinecomment" char="/" char1="/" />
- <Detect2Chars attribute="Comment" context="twolinecomment" char="/" char1="&#42;" beginRegion="Comment"/>
- <keyword attribute="Control Structures" context="#stay" String="control structures" />
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Function" context="#stay" String="functions" />
- <DetectChar attribute="String" context="doblequotestring" char="&quot;" />
- <DetectChar attribute="String" context="singlequotestring" char="&#39;" />
- <RegExpr attribute="String" context="" String="" />
- <RegExpr attribute="Variable" context="#stay" String="\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*" />
- <RegExpr attribute="String" context="#stay" String="[0123456789]*\.\.\.[0123456789]*" />
- <HlCOct attribute="Octal" context="#stay" />
- <HlCHex attribute="Hex" context="#stay" />
- <Float attribute="Float" context="#stay" />
- <Int attribute="Decimal" context="#stay" />
- <DetectChar attribute="Normal Text" context="#stay" char="{" beginRegion="Brace1" />
- <DetectChar attribute="Normal Text" context="#stay" char="}" endRegion="Brace1" />
- <AnyChar attribute="Other" context="#stay" String=";()}{:,[]" />
- <keyword attribute="Other" context="#stay" String="Others" />
- </context>
- <context name="php_onelinecomment" attribute="Comment" lineEndContext="#pop">
- <StringDetect attribute="Keyword" context="#pop#pop" String="?&gt;" />
- </context>
- <context name="twolinecomment" attribute="Comment" lineEndContext="#stay">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment" />
- </context>
- <context name="doblequotestring" attribute="String" lineEndContext="#stay">
- <Detect2Chars attribute="Backslash Code" context="#stay" char="\" char1="&quot;" />
- <Detect2Chars attribute="Backslash Code" context="#stay" char="\" char1="\" />
- <Detect2Chars attribute="Backslash Code" context="#stay" char="\" char1="n" />
- <Detect2Chars attribute="Backslash Code" context="#stay" char="\" char1="r" />
- <Detect2Chars attribute="Backslash Code" context="#stay" char="\" char1="t" />
- <Detect2Chars attribute="Backslash Code" context="#stay" char="\" char1="$" />
- <RegExpr attribute="Backslash Code" context="#stay" String="\\[0-7]{1,3}" />
- <RegExpr attribute="Backslash Code" context="#stay" String="\\x[0-9A-Fa-f]{1,2}" />
- <RegExpr attribute="Variable" context="#stay" String="\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\[[a-zA-Z0-9_]*\])*" />
- <RegExpr attribute="Variable" context="#stay" String="\$\{[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\[[a-zA-Z0-9_]*\])*\}" />
- <RegExpr attribute="Variable" context="#stay" String="\{\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\[([0-9]*|&quot;[a-zA-Z_]*&quot;)|'[a-zA-Z_]*'|\])*(->[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\[[a-zA-Z0-9_]*\])*(\[([0-9]*|&quot;[a-zA-Z_]*&quot;)|'[a-zA-Z_]*'|\])*)*\}" />
- <DetectChar attribute="String" context="#pop" char="&quot;" />
- </context>
- <context name="singlequotestring" attribute="String" lineEndContext="#stay">
- <Detect2Chars attribute="Backslash Code" context="#stay" char="\" char1="'"/>
- <Detect2Chars attribute="Backslash Code" context="#stay" char="\" char1="\"/>
- <DetectChar attribute="String" context="#pop" char="'" />
- </context>
- <context name="htmltag" attribute="Identifier" lineEndContext="#stay">
- <Detect2Chars attribute="HTML Tag" context="#pop" char="/" char1="&gt;" />
- <DetectChar attribute="HTML Tag" context="#pop" char="&gt;"/>
- <StringDetect attribute="Keyword" context="phpsource" String="&lt;?php" />
- <StringDetect attribute="Keyword" context="phpsource" String="&lt;?" />
- <RegExpr attribute="Identifier" context="identifiers" String="\s*=\s*"/>
- </context>
- <context name="htmlcomment" attribute="HTML Comment" lineEndContext="#stay">
- <StringDetect attribute="Keyword" context="phpsource" String="&lt;?php" />
- <StringDetect attribute="Keyword" context="phpsource" String="&lt;?" />
- <StringDetect attribute="HTML Comment" context="#pop" String="--&gt;" />
- <RegExpr attribute="Normal Text" context="identifiers" String="\s*=\s*"/>
- </context>
- <context name="identifiers" attribute="Identifier" lineEndContext="#stay">
- <RegExpr attribute="String" context="#pop" String="\s*#?[a-zA-Z0-9]*" />
- <DetectChar attribute="Types" context="types1" char="'" />
- <DetectChar attribute="Types" context="types2" char="&quot;" />
- </context>
-
- <context name="types1" attribute="Types" lineEndContext="#stay">
- <StringDetect attribute="Keyword" context="phpsource" String="&lt;?php" />
- <StringDetect attribute="Keyword" context="phpsource" String="&lt;?" />
- <DetectChar attribute="Types" context="#pop#pop" char="'" />
- </context>
-
- <context name="types2" attribute="Types" lineEndContext="#stay">
- <StringDetect attribute="Keyword" context="phpsource" String="&lt;?php" />
- <StringDetect attribute="Keyword" context="phpsource" String="&lt;?" />
- <DetectChar attribute="Types" context="#pop#pop" char="&quot;" />
- </context>
-
- <context name="scripts" attribute="Normal Text" lineEndContext="#stay">
- <Detect2Chars attribute="Comment" context="scripts_onelinecomment" char="/" char1="/" />
- <Detect2Chars attribute="Comment" context="twolinecomment" char="/" char1="&#42;" />
- <keyword attribute="Control Structures" context="#stay" String="control structures" />
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Function" context="#stay" String="functions" />
- <StringDetect attribute="Keyword" context="phpsource" String="&lt;?php"/>
- <StringDetect attribute="Keyword" context="phpsource" String="&lt;?"/>
- <RegExpr attribute="HTML Tag" context="#pop" String="&lt;\s*\/\s*script\s*&gt;" insensitive="TRUE" />
-
- <DetectChar attribute="String" context="doblequotestring" char="&quot;" />
- <DetectChar attribute="String" context="singlequotestring" char="&#39;" />
- <HlCOct attribute="Octal" context="#stay" />
- <HlCHex attribute="Hex" context="#stay" />
- <Float attribute="Float" context="#stay" />
- <Int attribute="Decimal" context="#stay" />
- <DetectChar attribute="Normal Text" context="#stay" char="{" beginRegion="Brace1" />
- <DetectChar attribute="Normal Text" context="#stay" char="}" endRegion="Brace1" />
- <AnyChar attribute="Other" context="#stay" String=";()}{:,[]" />
- <keyword attribute="Other" context="#stay" String="Others" />
- </context>
- <context name="scripts_onelinecomment" attribute="Comment" lineEndContext="#pop">
- <RegExpr attribute="HTML Tag" context="#pop#pop" String="&lt;\s*\/\s*script\s*&gt;" insensitive="TRUE" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="PHP Text" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="Function" defStyleNum="dsKeyword" color="#0000FF" selColor="#00ffff" bold="0" italic="0"/>
- <itemData name="Decimal" defStyleNum="dsDecVal" />
- <itemData name="Octal" defStyleNum="dsBaseN" />
- <itemData name="Hex" defStyleNum="dsBaseN" />
- <itemData name="Float" defStyleNum="dsFloat" />
- <itemData name="String" defStyleNum="dsString" />
- <itemData name="Comment" defStyleNum="dsComment" />
- <itemData name="Variable" defStyleNum="dsKeyword" color="#5555FF" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Control Structures" defStyleNum="dsKeyword" color="#A1A100" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Backslash Code" defStyleNum="dsKeyword" color="#0F0F8F" selColor="#ffffff" bold="1" italic="0" />
- <itemData name="Other" defStyleNum="dsOthers" />
-
- <itemData name="HTML Tag" defStyleNum="dsKeyword" color="#0F0000" selColor="#ffffff" bold="1" italic="0" />
- <itemData name="HTML Comment" defStyleNum="dsComment" />
- <itemData name="Identifier" defStyleNum="dsOthers" />
- <itemData name="Types" defStyleNum="dsDataType" />
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="0" weakDeliminator=""/>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!-- PIC (14 bits) assembler syntaxfile for gpasm/mpasm assembler by
- Alain GIBAUD (alain.gibaud@univ-valenciennes.fr)
-Small modifications for the new DTD by Joseph Wenninger <jowenn@kde.org>
- -->
-<language name="PicAsm" version="1.02" kateversion="2.0" section="Sources"
- extensions="*.src;*.SRC;*.asm;*.ASM;*.pic;*.PIC" mimetype="text/x-PicSrc;text/x-PicHdr"
- author="Alain GIBAUD (alain.gibaud@univ-valenciennes.fr)" license="">
-
- <highlighting>
- <list name="directives">
- <item> __BADRAM </item>
- <item> __CONFIG </item>
- <item> __IDLOCS </item>
- <item> __MAXRAM </item>
-
- <item> cblock </item>
- <item> constant </item>
- <item> da </item>
- <item> data </item>
- <item> db </item>
- <item> de </item>
- <item> dt </item>
- <item> dw </item>
- <item> endm </item>
- <item> equ </item>
- <item> error </item>
- <item> errorlevel </item>
- <item> exitm </item>
- <item> fill </item>
- <item> list </item>
- <item> local </item>
- <item> macro </item>
- <item> messg </item>
- <item> noexpand </item>
- <item> nolist </item>
- <item> org </item>
- <item> page </item>
- <item> processor </item>
- <item> radix </item>
- <item> res </item>
- <item> set </item>
- <item> space </item>
- <item> subtitle </item>
- <item> title </item>
- <item> variable </item>
- <item> end </item>
-
- <item> CBLOCK </item>
- <item> CONSTANT </item>
- <item> DA </item>
- <item> DATA </item>
- <item> DB </item>
- <item> DE </item>
- <item> DT </item>
- <item> DW </item>
- <item> ENDM </item>
- <item> EQU </item>
- <item> ERROR </item>
- <item> ERRORLEVEL </item>
- <item> EXITM </item>
- <item> FILL </item>
- <item> LIST </item>
- <item> LOCAL </item>
- <item> MACRO </item>
- <item> MESSG </item>
- <item> NOEXPAND </item>
- <item> NOLIST </item>
- <item> ORG </item>
- <item> PAGE </item>
- <item> PROCESSOR </item>
- <item> RADIX </item>
- <item> RES </item>
- <item> SET </item>
- <item> SPACE </item>
- <item> SUBTITLE </item>
- <item> TITLE </item>
- <item> VARIABLE </item>
- <item> END </item>
- </list>
-
- <list name="conditionnal">
- <item> if </item>
- <item> else </item>
- <item> idef </item>
- <item> ifndef </item>
- <item> endif </item>
- <item> while </item>
- <item> include </item>
- <item> endw </item>
- <item> { </item>
- <item> } </item>
- </list>
-
- <list name="gpasm_macro">
- <item> addcf </item>
- <item> b </item>
- <item> bc </item>
- <item> bz </item>
- <item> bnc </item>
- <item> bnz </item>
- <item> clrc </item>
- <item> clrz </item>
- <item> setc </item>
- <item> setz </item>
- <item> movfw </item>
- <item> negf </item>
- <item> skpc </item>
- <item> skpz </item>
- <item> skpnc </item>
- <item> skpnz </item>
- <item> subcf </item>
- <item> tstf </item>
-
- <item> ADDCF </item>
- <item> B </item>
- <item> BC </item>
- <item> BZ </item>
- <item> BNC </item>
- <item> BNZ </item>
- <item> CLRC </item>
- <item> CLRZ </item>
- <item> SETC </item>
- <item> SETZ </item>
- <item> MOVFW </item>
- <item> NEGF </item>
- <item> SKPC </item>
- <item> SKPZ </item>
- <item> SKPNC </item>
- <item> SKPNZ </item>
- <item> SUBCF </item>
- <item> TSTF </item>
- </list>
-
- <list name="instructions">
- <item> addlw </item>
- <item> addwf </item>
- <item> bcf </item>
- <item> bsf </item>
- <item> btfsc </item>
- <item> btfss </item>
- <item> call </item>
- <item> clrf </item>
- <item> clrw </item>
- <item> clrwtd </item>
- <item> comf </item>
- <item> decf </item>
- <item> decfsz </item>
- <item> goto </item>
- <item> incf </item>
- <item> incfsz </item>
- <item> iorlw </item>
- <item> movf </item>
- <item> movlw </item>
- <item> movwf </item>
- <item> nop </item>
- <item> option </item>
- <item> retfie </item>
- <item> retlw </item>
- <item> return </item>
- <item> rlf </item>
- <item> rrf </item>
- <item> sleep </item>
- <item> sublw </item>
- <item> subwf </item>
- <item> swapf </item>
- <item> tris </item>
- <item> xorlw </item>
- <item> xorwf </item>
-
- <item> ADDLW </item>
- <item> ADDWF </item>
- <item> BCF </item>
- <item> BSF </item>
- <item> BTFSC </item>
- <item> BTFSS </item>
- <item> CALL </item>
- <item> CLRF </item>
- <item> CLRW </item>
- <item> CLRWTD </item>
- <item> COMF </item>
- <item> DECF </item>
- <item> DECFSZ </item>
- <item> GOTO </item>
- <item> INCF </item>
- <item> INCFSZ </item>
- <item> IORLW </item>
- <item> MOVF </item>
- <item> MOVLW </item>
- <item> MOVWF </item>
- <item> NOP </item>
- <item> OPTION </item>
- <item> RETFIE </item>
- <item> RETLW </item>
- <item> RETURN </item>
- <item> RLF </item>
- <item> RRF </item>
- <item> SLEEP </item>
- <item> SUBLW </item>
- <item> SUBWF </item>
- <item> SWAPF </item>
- <item> TRIS </item>
- <item> XORLW </item>
- <item> XORWF </item>
- </list>
- <contexts>
-
- <context name="normal" attribute="Normal Text" lineEndContext="#stay">
- <keyword attribute="Directives" context="#stay" String="directives"/>
- <keyword attribute="Instructions" context="#stay" String="instructions"/>
- <keyword attribute="Preprocessor" context="#stay" String="conditionnal"/>
- <keyword attribute="GPASM-macros" context="#stay" String="gpasm_macro"/>
- <HlCHex attribute="Based Numbers" context="#stay"/>
- <RegExpr attribute="Based Numbers" context="#stay" String="([0-9A-F]+H)" insensitive="TRUE" />
- <RegExpr attribute="Based Numbers" context="#stay" String="([0-9]+D)" insensitive="TRUE" />
- <RegExpr attribute="Based Numbers" context="#stay" String="([0-7]+O)" insensitive="TRUE" />
- <RegExpr attribute="Based Numbers" context="#stay" String="([0-1]+B)" insensitive="TRUE" />
- <Int attribute="Non Based Numbers" context="#stay" />
- <HlCChar attribute="Char" context="#stay"/>
- <StringDetect attribute="Char" context="ASCIIChar" String="A'" insensitive="TRUE" />
- <StringDetect attribute="Based Numbers" context="binaryDigits" String="B'" insensitive="TRUE" />
- <StringDetect attribute="Based Numbers" context="hexDigits" String="H'" insensitive="TRUE" />
- <StringDetect attribute="Based Numbers" context="octDigits" String="O'" insensitive="TRUE" />
- <StringDetect attribute="Based Numbers" context="decimalDigits" String="D'" insensitive="TRUE" />
- <DetectChar attribute="String" context="string" char="&quot;"/>
- <DetectChar attribute="Comment" context="comment" char=";" />
- <RegExpr attribute="Symbol" context="#stay" String="[-/*%+=&gt;&lt;&amp;|^!~]"/>
- <RegExpr attribute="Symbol" context="#stay" String="(HIGH|LOW)"/>
- <RegExpr attribute="Preprocessor" context="#stay" String="(#define|#undefine|#v)"/>
- </context>
-
- <context name="string" attribute="String" lineEndContext="#pop">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
-
-
- <context name="comment" attribute="Comment" lineEndContext="#pop">
- <RegExpr attribute="Instructions" context="#stay"
- String="(FIXME|TODO|fixme|todo|INPUT|OUTPUT|PARAMETERS|AUTHOR|EMAIL)" />
- </context>
-
-
- <context name="decimalDigits" attribute="Based Numbers" lineEndContext="#pop">
- <DetectChar attribute="Based Numbers" context="#pop" char="'"/>
- <RegExpr attribute="Normal Text" context="#pop" String="[^0-9]" />
- </context>
-
- <context name="binaryDigits" attribute="Based Numbers" lineEndContext="#pop">
- <DetectChar attribute="Based Numbers" context="#pop" char="'"/>
- <RegExpr attribute="Normal Text" context="#pop" String="[^0-1]" />
- </context>
-
- <context name="hexDigits" attribute="Based Numbers" lineEndContext="#pop">
- <DetectChar attribute="Based Numbers" context="#pop" char="'"/>
- <RegExpr attribute="Normal Text" context="#pop" String="[^0-9A-Fa-f]" />
- </context>
-
- <context name="octDigits" attribute="Based Numbers" lineEndContext="#pop">
- <DetectChar attribute="Based Numbers" context="#pop" char="'"/>
- <RegExpr attribute="Normal Text" context="#pop" String="[^0-7]" />
- </context>
-
- <context name="ASCIIChar" attribute="Char" lineEndContext="#pop">
- <DetectChar attribute="Char" context="#pop" char="'"/>
- </context>
-
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Directives" defStyleNum="dsOthers"/>
- <itemData name="Preprocessor" defStyleNum="dsNormal" color="#D819D8" selColor="#D819D8" bold="0" italic="0"/>
- <itemData name="Instructions" defStyleNum="dsKeyword"/>
- <itemData name="Non Based Numbers" defStyleNum="dsDecVal"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsNormal" color="#FF3118" selColor="#FF3118" bold="0" italic="1" />
- <itemData name="Symbol" defStyleNum="dsNormal" color="#FF0000" selColor="#083194" bold="0" italic="0" />
- <itemData name="Prep. Lib" defStyleNum="dsOthers"/>
- <itemData name="Based Numbers" defStyleNum="dsBaseN" />
- <itemData name="GPASM-macros" defStyleNum="dsNormal" color="#000000" selColor="#000000" bold="1" italic="1"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start=";" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="PostScript" version="1.01" kateversion="2.1" section="Markup" extensions="*.ps;*.ai;*.eps" mimetype="application/postscript">
-<highlighting>
- <list name="keywords">
- <item> abs </item>
- <item> add </item>
- <item> aload </item>
- <item> anchorsearch </item>
- <item> and </item>
- <item> arc </item>
- <item> arcn </item>
- <item> arct </item>
- <item> arcto </item>
- <item> array </item>
- <item> ashow </item>
- <item> astore </item>
- <item> awidthshow </item>
- <item> begin </item>
- <item> bind </item>
- <item> bitshift </item>
- <item> ceiling </item>
- <item> charpath </item>
- <item> clear </item>
- <item> cleartomark </item>
- <item> clip </item>
- <item> clippath </item>
- <item> closepath </item>
- <item> concat </item>
- <item> concatmatrix </item>
- <item> copy </item>
- <item> count </item>
- <item> counttomark </item>
- <item> currentcmykcolor </item>
- <item> currentdash </item>
- <item> currentdict </item>
- <item> currentfile </item>
- <item> currentfont </item>
- <item> currentgray </item>
- <item> currentgstate </item>
- <item> currenthsbcolor </item>
- <item> currentlinecap </item>
- <item> currentlinejoin </item>
- <item> currentlinewidth </item>
- <item> currentmatrix </item>
- <item> currentpoint </item>
- <item> currentrgbcolor </item>
- <item> currentshared </item>
- <item> curveto </item>
- <item> cvi </item>
- <item> cvlit </item>
- <item> cvn </item>
- <item> cvr </item>
- <item> cvrs </item>
- <item> cvs </item>
- <item> cvx </item>
- <item> def </item>
- <item> defineusername </item>
- <item> dict </item>
- <item> div </item>
- <item> dtransform </item>
- <item> dup </item>
- <item> end </item>
- <item> eoclip </item>
- <item> eofill </item>
- <item> eoviewclip </item>
- <item> eq </item>
- <item> exch </item>
- <item> exec </item>
- <item> exit </item>
- <item> file </item>
- <item> fill </item>
- <item> findfont </item>
- <item> flattenpath </item>
- <item> floor </item>
- <item> flush </item>
- <item> flushfile </item>
- <item> for </item>
- <item> forall </item>
- <item> ge </item>
- <item> get </item>
- <item> getinterval </item>
- <item> grestore </item>
- <item> gsave </item>
- <item> gstate </item>
- <item> gt </item>
- <item> identmatrix </item>
- <item> idiv </item>
- <item> idtransform </item>
- <item> if </item>
- <item> ifelse </item>
- <item> image </item>
- <item> imagemask </item>
- <item> index </item>
- <item> ineofill </item>
- <item> infill </item>
- <item> initviewclip </item>
- <item> inueofill </item>
- <item> inufill </item>
- <item> invertmatrix </item>
- <item> itransform </item>
- <item> known </item>
- <item> le </item>
- <item> length </item>
- <item> lineto </item>
- <item> load </item>
- <item> loop </item>
- <item> lt </item>
- <item> makefont </item>
- <item> matrix </item>
- <item> maxlength </item>
- <item> mod </item>
- <item> moveto </item>
- <item> mul </item>
- <item> ne </item>
- <item> neg </item>
- <item> newpath </item>
- <item> not </item>
- <item> null </item>
- <item> or </item>
- <item> pathbbox </item>
- <item> pathforall </item>
- <item> pop </item>
- <item> print </item>
- <item> printobject </item>
- <item> put </item>
- <item> putinterval </item>
- <item> rcurveto </item>
- <item> read </item>
- <item> readhexstring </item>
- <item> readline </item>
- <item> readstring </item>
- <item> rectclip </item>
- <item> rectfill </item>
- <item> rectstroke </item>
- <item> rectviewclip </item>
- <item> repeat </item>
- <item> restore </item>
- <item> rlineto </item>
- <item> rmoveto </item>
- <item> roll </item>
- <item> rotate </item>
- <item> round </item>
- <item> save </item>
- <item> scale </item>
- <item> scalefont </item>
- <item> search </item>
- <item> selectfont </item>
- <item> setbbox </item>
- <item> setcachedevice </item>
- <item> setcachedevice2 </item>
- <item> setcharwidth </item>
- <item> setcmykcolor </item>
- <item> setdash </item>
- <item> setfont </item>
- <item> setgray </item>
- <item> setgstate </item>
- <item> sethsbcolor </item>
- <item> setlinecap </item>
- <item> setlinejoin </item>
- <item> setlinewidth </item>
- <item> setmatrix </item>
- <item> setrgbcolor </item>
- <item> setshared </item>
- <item> shareddict </item>
- <item> show </item>
- <item> showpage </item>
- <item> stop </item>
- <item> stopped </item>
- <item> store </item>
- <item> string </item>
- <item> stringwidth </item>
- <item> stroke </item>
- <item> strokepath </item>
- <item> sub </item>
- <item> systemdict </item>
- <item> token </item>
- <item> transform </item>
- <item> translate </item>
- <item> truncate </item>
- <item> type </item>
- <item> uappend </item>
- <item> ucache </item>
- <item> ueofill </item>
- <item> ufill </item>
- <item> undef </item>
- <item> upath </item>
- <item> userdict </item>
- <item> ustroke </item>
- <item> viewclip </item>
- <item> viewclippath </item>
- <item> where </item>
- <item> widthshow </item>
- <item> write </item>
- <item> writehexstring </item>
- <item> writeobject </item>
- <item> writestring </item>
- <item> wtranslation </item>
- <item> xor </item>
- <item> xshow </item>
- <item> xyshow </item>
- <item> yshow </item>
- <item> FontDirectory </item>
- <item> SharedFontDirectory </item>
- <item> Courier </item>
- <item> Courier-Bold </item>
- <item> Courier-BoldOblique </item>
- <item> Courier-Oblique </item>
- <item> Helvetica </item>
- <item> Helvetica-Bold </item>
- <item> Helvetica-BoldOblique </item>
- <item> Helvetica-Oblique </item>
- <item> Symbol </item>
- <item> Times-Bold </item>
- <item> Times-BoldItalic </item>
- <item> Times-Italic </item>
- <item> Times-Roman </item>
- <item> execuserobject </item>
- <item> currentcolor </item>
- <item> currentcolorspace </item>
- <item> currentglobal </item>
- <item> execform </item>
- <item> filter </item>
- <item> findresource </item>
- <item> globaldict </item>
- <item> makepattern </item>
- <item> setcolor </item>
- <item> setcolorspace </item>
- <item> setglobal </item>
- <item> setpagedevice </item>
- <item> setpattern </item>
- <item> ISOLatin1Encoding </item>
- <item> StandardEncoding </item>
- <item> atan </item>
- <item> banddevice </item>
- <item> bytesavailable </item>
- <item> cachestatus </item>
- <item> closefile </item>
- <item> colorimage </item>
- <item> condition </item>
- <item> copypage </item>
- <item> cos </item>
- <item> countdictstack </item>
- <item> countexecstack </item>
- <item> cshow </item>
- <item> currentblackgeneration </item>
- <item> currentcacheparams </item>
- <item> currentcolorscreen </item>
- <item> currentcolortransfer </item>
- <item> currentcontext </item>
- <item> currentflat </item>
- <item> currenthalftone </item>
- <item> currenthalftonephase </item>
- <item> currentmiterlimit </item>
- <item> currentobjectformat </item>
- <item> currentpacking </item>
- <item> currentscreen </item>
- <item> currentstrokeadjust </item>
- <item> currenttransfer </item>
- <item> currentundercolorremoval </item>
- <item> defaultmatrix </item>
- <item> definefont </item>
- <item> deletefile </item>
- <item> detach </item>
- <item> deviceinfo </item>
- <item> dictstack </item>
- <item> echo </item>
- <item> erasepage </item>
- <item> errordict </item>
- <item> execstack </item>
- <item> executeonly </item>
- <item> exp </item>
- <item> false </item>
- <item> filenameforall </item>
- <item> fileposition </item>
- <item> fork </item>
- <item> framedevice </item>
- <item> grestoreall </item>
- <item> handleerror </item>
- <item> initclip </item>
- <item> initgraphics </item>
- <item> initmatrix </item>
- <item> instroke </item>
- <item> inustroke </item>
- <item> join </item>
- <item> kshow </item>
- <item> ln </item>
- <item> lock </item>
- <item> log </item>
- <item> mark </item>
- <item> monitor </item>
- <item> noaccess </item>
- <item> notify </item>
- <item> nulldevice </item>
- <item> packedarray </item>
- <item> quit </item>
- <item> rand </item>
- <item> rcheck </item>
- <item> readonly </item>
- <item> realtime </item>
- <item> renamefile </item>
- <item> renderbands </item>
- <item> resetfile </item>
- <item> reversepath </item>
- <item> rootfont </item>
- <item> rrand </item>
- <item> run </item>
- <item> scheck </item>
- <item> setblackgeneration </item>
- <item> setcachelimit </item>
- <item> setcacheparams </item>
- <item> setcolorscreen </item>
- <item> setcolortransfer </item>
- <item> setfileposition </item>
- <item> setflat </item>
- <item> sethalftone </item>
- <item> sethalftonephase </item>
- <item> setmiterlimit </item>
- <item> setobjectformat </item>
- <item> setpacking </item>
- <item> setscreen </item>
- <item> setstrokeadjust </item>
- <item> settransfer </item>
- <item> setucacheparams </item>
- <item> setundercolorremoval </item>
- <item> sin </item>
- <item> sqrt </item>
- <item> srand </item>
- <item> stack </item>
- <item> status </item>
- <item> statusdict </item>
- <item> true </item>
- <item> ucachestatus </item>
- <item> undefinefont </item>
- <item> usertime </item>
- <item> ustrokepath </item>
- <item> version </item>
- <item> vmreclaim </item>
- <item> vmstatus </item>
- <item> wait </item>
- <item> wcheck </item>
- <item> xcheck </item>
- <item> yield </item>
- <item> defineuserobject </item>
- <item> undefineuserobject </item>
- <item> UserObjects </item>
- <item> cleardictstack </item>
- <item> setvmthreshold </item>
- <item> currentcolorrendering </item>
- <item> currentdevparams </item>
- <item> currentoverprint </item>
- <item> currentpagedevice </item>
- <item> currentsystemparams </item>
- <item> currentuserparams </item>
- <item> defineresource </item>
- <item> findencoding </item>
- <item> gcheck </item>
- <item> glyphshow </item>
- <item> languagelevel </item>
- <item> product </item>
- <item> pstack </item>
- <item> resourceforall </item>
- <item> resourcestatus </item>
- <item> revision </item>
- <item> serialnumber </item>
- <item> setcolorrendering </item>
- <item> setdevparams </item>
- <item> setoverprint </item>
- <item> setsystemparams </item>
- <item> setuserparams </item>
- <item> startjob </item>
- <item> undefineresource </item>
- <item> GlobalFontDirectory </item>
- <item> ASCII85Decode </item>
- <item> ASCII85Encode </item>
- <item> ASCIIHexDecode </item>
- <item> ASCIIHexEncode </item>
- <item> CCITTFaxDecode </item>
- <item> CCITTFaxEncode </item>
- <item> DCTDecode </item>
- <item> DCTEncode </item>
- <item> LZWDecode </item>
- <item> LZWEncode </item>
- <item> NullEncode </item>
- <item> RunLengthDecode </item>
- <item> RunLengthEncode </item>
- <item> SubFileDecode </item>
- <item> CIEBasedA </item>
- <item> CIEBasedABC </item>
- <item> DeviceCMYK </item>
- <item> DeviceGray </item>
- <item> DeviceRGB </item>
- <item> Indexed </item>
- <item> Pattern </item>
- <item> Separation </item>
- <item> CIEBasedDEF </item>
- <item> CIEBasedDEFG </item>
- <item> DeviceN </item>
- </list>
-
- <contexts>
- <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <Detect2Chars attribute="Header" context="Header" char="%" char1="!"/>
- <DetectChar attribute="Comment" context="Comment" char="%"/>
- <Float attribute="Float" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- <DetectChar attribute="String" context="String" char="("/>
- <RegExpr attribute="Data Type" context="#stay" String="\/{1,2}[^\s\(\)\{\}\[\]%/]*"/>
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Comment"/>
- <context attribute="Header" lineEndContext="#pop" name="Header"/>
- <context attribute="String" lineEndContext="#stay" name="String">
- <DetectChar attribute="String" context="#pop" char=")" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Header" defStyleNum="dsOthers"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- </itemDatas>
-</highlighting>
-<general>
- <comments>
- <comment name="singleLine" start="%" />
- </comments>
- <keywords casesensitive="0" />
-</general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Povray" version="0.1" kateversion="2.1" section="Other" extensions="*.inc;*.pov" mimetype="text/plain" priority="9">
- <highlighting>
- <list name="keywords">
- <item> aa-level </item>
- <item> aa-threshold </item>
- <item> absorbtion </item>
- <item> accuracy </item>
- <item> adaptive </item>
- <item> adc_bailout </item>
- <item> all </item>
- <item> all_intersections </item>
- <item> alpha </item>
- <item> altitude </item>
- <item> always_sample </item>
- <item> ambient </item>
- <item> ambient_light </item>
- <item> angle </item>
- <item> aperture </item>
- <item> append </item>
- <item> arc_angle </item>
- <item> area_light </item>
- <item> ascii </item>
- <item> assumed_gamma </item>
- <item> autostop </item>
-
- <item> back_hole </item>
- <item> blue </item>
- <item> blur_samples </item>
- <item> bounded_by </item>
- <item> break </item>
- <item> brick_size </item>
- <item> brightness </item>
- <item> brilliance </item>
- <item> bump_size </item>
-
- <item> case </item>
- <item> caustics </item>
- <item> charset </item>
- <item> circular </item>
- <item> clipped_by </item>
- <item> collect </item>
- <item> color </item>
- <item> colour </item>
- <item> component </item>
- <item> composite </item>
- <item> confidence </item>
- <item> conic_sweep </item>
- <item> conserve_energy </item>
- <item> contained_by </item>
- <item> control0 </item>
- <item> control1 </item>
- <item> coords </item>
- <item> count </item>
- <item> crand </item>
- <item> cubic_spline </item>
- <item> cubic_wave </item>
- <item> cutaway_textures </item>
-
- <item> diffuse </item>
- <item> direction </item>
- <item> dispersion </item>
- <item> dispersion_samples </item>
- <item> dist_exp </item>
- <item> distance </item>
- <item> double_illuminate </item>
-
- <item> eccentricity </item>
- <item> emission </item>
- <item> error_bound </item>
- <item> evaluate </item>
- <item> expand_thresholds </item>
- <item> exponent </item>
- <item> exterior </item>
- <item> extinction </item>
-
- <item> face_indices </item>
- <item> fade_color </item>
- <item> fade_colour </item>
- <item> fade_distance </item>
- <item> fade_power </item>
- <item> falloff </item>
- <item> falloff_angle </item>
- <item> filter </item>
- <item> fisheye </item>
- <item> flatness </item>
- <item> flip </item>
- <item> focal_point </item>
- <item> fog_alt </item>
- <item> fog_offset </item>
- <item> fog_type </item>
- <item> form </item>
- <item> frequency </item>
- <item> fresnel </item>
- <item> function </item>
-
- <item> gather </item>
- <item> global_lights </item>
- <item> gray </item>
- <item> gray_threshold </item>
- <item> green </item>
-
- <item> hierarchy </item>
- <item> hypercomplex </item>
- <item> hollow </item>
-
- <item> inside_vector </item>
- <item> interpolate </item>
- <item> intervals </item>
- <item> inverse </item>
- <item> ior </item>
- <item> irid </item>
- <item> irid_wavelength </item>
-
- <item> jitter </item>
-
- <item> lambda </item>
- <item> linear_spline </item>
- <item> linear_sweep </item>
- <item> load_file </item>
- <item> location </item>
- <item> look_at </item>
- <item> low_error_factor </item>
-
- <item> magnet </item>
- <item> major_radius </item>
- <item> map_type </item>
- <item> max_extent </item>
- <item> max_gradient </item>
- <item> max_intersections </item>
- <item> max_iterations </item>
- <item> max_sample </item>
- <item> max_trace </item>
- <item> max_trace_level </item>
- <item> media_attenuation </item>
- <item> media_interaction </item>
- <item> metallic </item>
- <item> method </item>
- <item> metric </item>
- <item> min_extent </item>
- <item> min_reuse </item>
- <item> mortar </item>
-
- <item> natural_spline </item>
- <item> nearest_count </item>
- <item> no_bump_scale </item>
- <item> no_image </item>
- <item> no_reflection </item>
- <item> no_shadow </item>
- <item> noise_generator </item>
- <item> normal_indices </item>
- <item> normal_vector </item>
- <item> number_of_waves </item>
-
- <item> octaves </item>
- <item> offset </item>
- <item> omega </item>
- <item> omnimax </item>
- <item> once </item>
- <item> open </item>
- <item> orient </item>
- <item> orientation </item>
- <item> orthographic </item>
-
- <item> panoramic </item>
- <item> parallel </item>
- <item> pass_through </item>
- <item> pattern </item>
- <item> perspective </item>
- <item> phase </item>
- <item> phong </item>
- <item> phong_size </item>
- <item> point_at </item>
- <item> poly_wave </item>
- <item> precision </item>
- <item> precompute </item>
- <item> pretrace_end </item>
- <item> pretrace_start </item>
-
- <item> quadratic_spline </item>
- <item> quaternion </item>
-
- <item> radius </item>
- <item> ramp_wave </item>
- <item> ratio </item>
- <item> reciprocal </item>
- <item> recursion_limit </item>
- <item> red </item>
- <item> reflection </item>
- <item> reflection_exponent </item>
- <item> refraction </item>
- <item> repeat </item>
- <item> rgb </item>
- <item> rgbf </item>
- <item> rgbft </item>
- <item> rgbt </item>
- <item> right </item>
- <item> roughness </item>
-
- <item> samples </item>
- <item> save_file </item>
- <item> scallop_wave </item>
- <item> scattering </item>
- <item> shadowless </item>
- <item> sine_wave </item>
- <item> size </item>
- <item> sky </item>
- <item> slice </item>
- <item> smooth </item>
- <item> solid </item>
- <item> spacing </item>
- <item> specular </item>
- <item> split_union </item>
- <item> spotlight </item>
- <item> sqr </item>
- <item> strength </item>
- <item> sturm </item>
- <item> sys </item>
-
- <item> target </item>
- <item> thickness </item>
- <item> threshold </item>
- <item> tightness </item>
- <item> tiles </item>
- <item> tile2 </item>
- <item> tolerance </item>
- <item> toroidal </item>
- <item> transform </item>
- <item> transmit </item>
- <item> triangle_wave </item>
- <item> turb_depth </item>
- <item> turbulence </item>
- <item> type </item>
-
- <item> u_steps </item>
- <item> ultra_wide_angle </item>
- <item> up </item>
- <item> use_alpha </item>
- <item> use_color </item>
- <item> use_colour </item>
- <item> use_index </item>
- <item> utf8 </item>
- <item> uv_indices </item>
- <item> uv_mapping </item>
- <item> uv_vectors </item>
-
- <item> v_steps </item>
- <item> variance </item>
- <item> vertex_vectors </item>
-
- <item> water_level </item>
- </list>
-
- <list name="objects">
- <item> b_spline </item>
- <item> background </item>
- <item> beizer_spline </item>
- <item> bicubic_patch </item>
- <item> blob </item>
- <item> box </item>
- <item> brick </item>
- <item> camera </item>
- <item> cone </item>
- <item> cubic </item>
- <item> cylinder </item>
- <item> difference </item>
- <item> disc </item>
- <item> fog </item>
- <item> global_settings </item>
- <item> height_field</item>
- <item> intersection </item>
- <item> isosurface </item>
- <item> julia_fractal </item>
- <item> lathe </item>
- <item> light_source </item>
- <item> looks_like </item>
- <item> merge </item>
- <item> mesh </item>
- <item> mesh2 </item>
- <item> object </item>
- <item> parametric </item>
- <item> plane </item>
- <item> poly </item>
- <item> polygon </item>
- <item> prism </item>
- <item> projected_through </item>
- <item> quadric </item>
- <item> quartic </item>
- <item> radiosity </item>
- <item> rainbow </item>
- <item> sky_sphere </item>
- <item> smooth_triangle </item>
- <item> sor </item>
- <item> sphere </item>
- <item> sphere_sweep </item>
- <item> spline </item>
- <item> superellipsoid </item>
- <item> text </item>
- <item> torus </item>
- <item> triangle </item>
- <item> union </item>
- </list>
-
- <list name="texturing">
- <item> agate </item>
- <item> agate_turb </item>
- <item> average </item>
- <item> boxed </item>
- <item> bozo </item>
- <item> bump_map </item>
- <item> bumps </item>
- <item> cells </item>
- <item> checker </item>
- <item> color_map </item>
- <item> color_list </item>
- <item> colour_map </item>
- <item> colour_list </item>
- <item> crackle </item>
- <item> cylindrical </item>
- <item> density </item>
- <item> density_file </item>
- <item> density_map </item>
- <item> density_list </item>
- <item> dents </item>
- <item> facets </item>
- <item> finish </item>
- <item> gradient </item>
- <item> granite </item>
- <item> hexagon </item>
- <item> image_map </item>
- <item> image_pattern </item>
- <item> interior </item>
- <item> interior_texture </item>
- <item> julia </item>
- <item> leopard </item>
- <item> mandel </item>
- <item> marble </item>
- <item> material </item>
- <item> material_map </item>
- <item> media </item>
- <item> normal </item>
- <item> normal_map </item>
- <item> normal_list </item>
- <item> onion </item>
- <item> photons </item>
- <item> pigment </item>
- <item> pigment_map </item>
- <item> pigment_list </item>
- <item> pigment_pattern </item>
- <item> planar </item>
- <item> quick_color </item>
- <item> quick_colour </item>
- <item> quilted </item>
- <item> radial </item>
- <item> ripples </item>
- <item> slope </item>
- <item> slope_map </item>
- <item> spherical </item>
- <item> spiral1 </item>
- <item> spiral2 </item>
- <item> spotted </item>
- <item> texture </item>
- <item> texture_list </item>
- <item> texture_map </item>
- <item> warp </item>
- <item> waves </item>
- <item> wood </item>
- <item> wrinkles </item>
- </list>
-
- <list name="transforms">
- <item> matrix </item>
- <item> rotate </item>
- <item> scale </item>
- <item> translate </item>
- </list>
-
- <list name="filetypes">
- <item> df3 </item>
- <item> gif </item>
- <item> hf_gray_16 </item>
- <item> iff </item>
- <item> jpeg </item>
- <item> pgm </item>
- <item> png </item>
- <item> pot </item>
- <item> ppm </item>
- <item> tga </item>
- <item> tiff </item>
- <item> ttf </item>
- </list>
-
- <list name="identifiers">
- <item> array </item>
- <item> clock </item>
- <item> clock_delta </item>
- <item> clock_on </item>
- <item> final_clock </item>
- <item> final_frame </item>
- <item> frame_number </item>
- <item> image_height </item>
- <item> image_width </item>
- <item> initial_clock </item>
- <item> initial_frame </item>
- <item> t </item>
- <item> u </item>
- <item> v </item>
- <item> x </item>
- <item> y </item>
- <item> z </item>
- </list>
-
- <list name="constants">
- <item> false </item>
- <item> no </item>
- <item> off </item>
- <item> on </item>
- <item> pi </item>
- <item> true </item>
- <item> yes </item>
- </list>
-
- <list name="functions">
- <item> abs </item>
- <item> acos </item>
- <item> acosh </item>
- <item> asc </item>
- <item> asin </item>
- <item> asinh </item>
- <item> atan </item>
- <item> atan2 </item>
- <item> atanh </item>
- <item> ceil </item>
- <item> chr </item>
- <item> concat </item>
- <item> cos </item>
- <item> cosh </item>
- <item> cube </item>
- <item> defined </item>
- <item> degress </item>
- <item> dimension_size </item>
- <item> dimensions </item>
- <item> div </item>
- <item> exp </item>
- <item> file_exists </item>
- <item> floor </item>
- <item> inside </item>
- <item> int </item>
- <item> ln </item>
- <item> log </item>
- <item> max </item>
- <item> min </item>
- <item> mod </item>
- <item> pow </item>
- <item> prod </item>
- <item> pwr </item>
- <item> radians </item>
- <item> rand </item>
- <item> seed </item>
- <item> select </item>
- <item> sin </item>
- <item> sinh </item>
- <item> sqrt </item>
- <item> str </item>
- <item> strcmp </item>
- <item> strlen </item>
- <item> strlwr </item>
- <item> strupr </item>
- <item> substr </item>
- <item> sum </item>
- <item> tan </item>
- <item> tanh </item>
- <item> trace </item>
- <item> val </item>
- <item> vaxis_rotate </item>
- <item> vcross </item>
- <item> vdot </item>
- <item> vlength </item>
- <item> vnormalize </item>
- <item> vrotate </item>
- <item> vstr </item>
- <item> vturbulence </item>
- </list>
-
- <list name="directives">
- <item> #debug </item>
- <item> #declare </item>
- <item> #default </item>
- <item> #else </item>
- <item> #end </item>
- <item> #error </item>
- <item> #fclose </item>
- <item> #fopen </item>
- <item> #if </item>
- <item> #ifdef </item>
- <item> #ifndef </item>
- <item> #include </item>
- <item> #local </item>
- <item> #macro </item>
- <item> #range </item>
- <item> #read </item>
- <item> #render </item>
- <item> #statistics </item>
- <item> #switch </item>
- <item> #indef </item>
- <item> #version </item>
- <item> #warning </item>
- <item> #while </item>
- <item> #write </item>
- </list>
-
- <list name="attention">
- <item> FIXME </item>
- <item> TODO </item>
- <item> ### </item>
- </list>
-
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <RegExpr attribute="Decimal" context="#stay" String="//\s*BEGIN.*$" beginRegion="Region1"/>
- <RegExpr attribute="Decimal" context="#stay" String="//\s*END.*$" endRegion="Region1"/>
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Objects" context="#stay" String="objects" />
- <keyword attribute="Texturing" context="#stay" String="texturing" />
- <keyword attribute="Transforms" context="#stay" String="transforms" />
- <keyword attribute="Data Type" context="#stay" String="filetypes" />
- <keyword attribute="Keyword" context="#stay" String="identifiers" />
- <keyword attribute="Keyword" context="#stay" String="constants" />
- <keyword attribute="Functions" context="#stay" String="functions" />
- <keyword attribute="Directives" context="#stay" String="directives" />
- <Float attribute="Float" context="#stay">
- <AnyChar String="fF" attribute="Float" context="#stay"/>
- </Float>
- <HlCOct attribute="Octal" context="#stay"/>
- <HlCHex attribute="Hex" context="#stay"/>
- <Int attribute="Decimal" context="#stay">
- <StringDetect attribute="Decimal" context="#stay" String="ULL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LUL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LLU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="UL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="U" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="L" insensitive="TRUE"/>
- </Int>
- <HlCChar attribute="Char" context="#stay"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*" beginRegion="Comment"/>
- <DetectChar attribute="Symbol" context="#stay" char="{" beginRegion="Brace1" />
- <DetectChar attribute="Symbol" context="#stay" char="}" endRegion="Brace1" />
- <RegExpr attribute="Function" context="#stay" String="\b[_\w][_\d\w]*(?=[\s]*[(])" />
- <RegExpr attribute="Symbol" context="Member" String="([.]{1,1}|[:]{2,2})" />
- <RegExpr attribute="Vector" context="#stay" String="&lt;.*&gt;"/>
- <AnyChar attribute="Symbol" context="#stay" String=":!%&amp;()+,-/.*&lt;=&gt;?[]{|}~^&#59;"/>
- </context>
-
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
-
- <context attribute="Normal Text" lineEndContext="#pop" name="Member">
- <RegExpr attribute="Function" context="#pop" String="\b[_\w][_\w\d]*(?=[\s]*)" />
- </context>
-
- <context attribute="Comment" lineEndContext="#pop" name="Commentar 1">
- <keyword attribute="Decimal" context="#stay" String="attention" />
- </context>
-
- <context attribute="Comment" lineEndContext="#stay" name="Commentar 2">
- <keyword attribute="Decimal" context="#stay" String="attention" />
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- </context>
-
- <context attribute="Comment" lineEndContext="#stay" name="Commentar">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" />
- </context>
- </contexts>
-
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Objects" defStyleNum="dsKeyword" color="#800000" selColor="#ffffff" bold="1" italic="0"/>
- <itemData name="Texturing" defStyleNum="dsKeyword" color="#008000" selColor="#ffffff" bold="1" italic="0"/>
- <itemData name="Transforms" defStyleNum="dsKeyword" color="#0000ff" selColor="#ffffff" bold="1" italic="0"/>
- <itemData name="Identifiers" defStyleNum="dsKeyword" color="#000000" selColor="#ffffff" bold="1" italic="0"/>
- <itemData name="Function" defStyleNum="dsKeyword" color="#000080" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="Functions" defStyleNum="dsKeyword" color="#000080" selColor="#ffffff" bold="1" italic="0"/>
- <itemData name="Directives" defStyleNum="dsOthers"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Vector" defStyleNum="dsBaseN"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- </itemDatas>
- </highlighting>
-
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!-- By: Rares Stanciulescu <rstanciu@operamail.com> -->
-<language name="progress" version="1.03" kateversion="2.1"
- section="Other" extensions="*.p;*.w;*.i" casesensitive="0"
- author="Rares Stanciulescu (rstanciu@operamail.com)" license="">
-
-<highlighting>
-
-<list name="mytypes">
- <item> CHAR </item>
- <item> CHARACTER </item>
- <item> DECI </item>
- <item> DECIMAL </item>
- <item> DATE </item>
- <item> INTE </item>
- <item> INTEGER </item>
- <item> ROWID </item>
- <item> RECID </item>
- <item> LOGI </item>
- <item> LOGICAL </item>
- <item> HANDLE </item>
- <item> WIDGET-HANDLE </item>
- <item> RAW </item>
- <item> LONG </item>
- <item> SHORT </item>
- <item> BLOB </item>
- <item> CLOB </item>
- <item> LONGCHAR </item>
- <item> DATETIME </item>
- <item> DATETIME-TZ </item>
- <item> TEMP-TABLE </item>
- <item> BUFFER </item>
- <item> STREAM </item>
- <item> MEMPTR </item>
-</list>
-
-<list name="operators">
- <item> + </item>
- <item> - </item>
- <item> * </item>
- <item> / </item>
- <item> = </item>
- <item> &lt; </item>
- <item> &gt; </item>
- <item> &lt;= </item>
- <item> &gt;= </item>
- <item> &lt;&gt; </item>
- <item> AND </item>
- <item> OR </item>
- <item> NOT </item>
- <item> BEGINS </item>
- <item> MATCHES </item>
- <item> MODULO </item>
- <item> EQ </item>
- <item> NE </item>
- <item> LT </item>
- <item> GT </item>
- <item> GE </item>
- <item> LE </item>
- <item> FALSE </item>
- <item> TRUE </item>
- <item> yes </item>
- <item> no </item>
-</list>
-
-
-<list name="preprocvar">
- <item> &amp;OUT </item>
- <item> &amp;BATCH-MODE </item>
- <item> &amp;FILE-NAME </item>
- <item> &amp;GLOBAL-DEFINE </item>
- <item> &amp;LINE-NUMBER </item>
- <item> &amp;MESSAGE </item>
- <item> &amp;OPSYS </item>
- <item> &amp;IF </item>
- <item> &amp;ELSEIF </item>
- <item> &amp;ELSE </item>
- <item> &amp;ENDIF </item>
- <item> &amp;SCOPED-DEFINE </item>
- <item> &amp;SEQUENCE </item>
- <item> &amp;UNDEFINE </item>
- <item> &amp;WINDOW-SYSTEM </item>
-</list>
-
-<list name="phrases">
- <item> AS </item>
- <item> AT </item>
- <item> COLOR </item>
- <item> COMBO-BOX </item>
- <item> EDITING </item>
- <item> EDITOR </item>
- <item> FORMAT </item>
- <item> FRAME </item>
- <item> IMAGE </item>
- <item> ON ENDKEY </item>
- <item> ON ERROR </item>
- <item> ON QUIT </item>
- <item> STOP </item>
- <item> PRESELECT </item>
- <item> QUERY-TUNING </item>
- <item> RADIO-SET </item>
- <item> RECORD </item>
- <item> SELECTION-LIST </item>
- <item> SIZE </item>
- <item> SLIDER </item>
- <item> TRIGGER </item>
- <item> WIDGET </item>
- <item> VIEW-AS </item>
- <item> NO-UNDO </item>
- <item> NO-ERROR </item>
- <item> OUT </item>
- <item> WHERE </item>
- <item> SHARED </item>
- <item> GLOBAL-SHARED </item>
- <item> DEFINED </item>
-</list>
-
-<list name="functions">
- <item> ABSOLUTE </item>
- <item> ACCUM </item>
- <item> ADD-INTERVAL </item>
- <item> ALIAS </item>
- <item> AMBIGUOUS </item>
- <item> ASC </item>
- <item> AVAILABLE </item>
- <item> CAN-DO </item>
- <item> CAN-FIND </item>
- <item> CAN-QUERY </item>
- <item> CAN-SET </item>
- <item> CAPS </item>
- <item> CHR </item>
- <item> CODEPAGE-CONVERT </item>
- <item> COMPARE </item>
- <item> CONNECTED </item>
- <item> COUNT-OF </item>
- <item> CURRENT-CHANGED </item>
- <item> CURRENT-LANGUAGE </item>
- <item> CURRENT-RESULT-ROW </item>
- <item> CURRENT-VALUE </item>
- <item> DATASERVERS </item>
- <item> DATE </item>
- <item> DATETIME </item>
- <item> DATETIME-TZ </item>
- <item> DAY </item>
- <item> DBCODEPAGE </item>
- <item> DBCOLLATION </item>
- <item> DBNAME </item>
- <item> DBPARAM </item>
- <item> DBRESTRICTIONS </item>
- <item> DBTASKID </item>
- <item> DBTYPE </item>
- <item> DBVERSION </item>
- <item> DECIMAL </item>
- <item> DYNAMIC-CURRENT-VALUE </item>
- <item> DYNAMIC-FUNCTION </item>
- <item> DYNAMIC-NEXT-VALUE </item>
- <item> ENCODE </item>
- <item> ENTERED </item>
- <item> ENTRY </item>
- <item> ETIME </item>
- <item> EXP </item>
- <item> EXTENT </item>
- <item> FILL </item>
- <item> FIRST </item>
- <item> FIRST-OF </item>
- <item> FIX-CODEPAGE </item>
- <item> FRAME-COL </item>
- <item> FRAME-DB </item>
- <item> FRAME-DOWN </item>
- <item> FRAME-FIELD </item>
- <item> FRAME-FILE </item>
- <item> FRAME-INDEX </item>
- <item> FRAME-LINE </item>
- <item> FRAME-NAME </item>
- <item> FRAME-ROW </item>
- <item> FRAME-VALUE </item>
- <item> GATEWAYS </item>
- <item> GET-BITS </item>
- <item> GET-BYTE </item>
- <item> GET-BYTE-ORDER </item>
- <item> GET-BYTES </item>
- <item> GET-CODEPAGE </item>
- <item> GET-CODEPAGES </item>
- <item> GET-COLLATION </item>
- <item> GET-COLLATIONS </item>
- <item> GET-DOUBLE </item>
- <item> GET-FLOAT </item>
- <item> GET-LONG </item>
- <item> GET-POINTER-VALUE </item>
- <item> GET-SHORT </item>
- <item> GET-SIZE </item>
- <item> GET-STRING </item>
- <item> GET-UNSIGNED-SHORT </item>
- <item> GO-PENDING </item>
- <item> INDEX </item>
- <item> INPUT </item>
- <item> INTEGER </item>
- <item> INTERVAL </item>
- <item> IS-ATTR-SPACE </item>
- <item> IS-CODEPAGE-FIXED </item>
- <item> IS-COLUMN-CODEPAGE </item>
- <item> IS-LEAD-BYTE </item>
- <item> ISO-DATE </item>
- <item> KBLABEL </item>
- <item> KEYCODE </item>
- <item> KEYFUNCTION </item>
- <item> KEYLABEL </item>
- <item> KEYWORD </item>
- <item> KEYWORD-ALL </item>
- <item> LAST </item>
- <item> LASTKEY </item>
- <item> LAST-OF </item>
- <item> LC </item>
- <item> LDBNAME </item>
- <item> LEFT-TRIM </item>
- <item> LENGTH </item>
- <item> LIBRARY </item>
- <item> LINE-COUNTER </item>
- <item> LIST-EVENTS </item>
- <item> LIST-QUERY-ATTRS </item>
- <item> LIST-SET-ATTRS </item>
- <item> LIST-WIDGETS </item>
- <item> LOCKED </item>
- <item> LOG </item>
- <item> LOOKUP </item>
- <item> MAXIMUM </item>
- <item> MEMBER </item>
- <item> MESSAGE-LINES </item>
- <item> MINIMUM </item>
- <item> MONTH </item>
- <item> MTIME </item>
- <item> NEW </item>
- <item> NEXT-VALUE </item>
- <item> NOT ENTERED </item>
- <item> NOW </item>
- <item> NUM-ALIASES </item>
- <item> NUM-DBS </item>
- <item> NUM-ENTRIES </item>
- <item> NUM-RESULTS </item>
- <item> OPSYS </item>
- <item> OS-DRIVES </item>
- <item> OS-ERROR </item>
- <item> OS-GETENV </item>
- <item> PAGE-NUMBER </item>
- <item> PAGE-SIZE </item>
- <item> PDBNAME </item>
- <item> PROC-HANDLE </item>
- <item> PROC-STATUS </item>
- <item> PROGRAM-NAME </item>
- <item> PROGRESS </item>
- <item> PROMSGS </item>
- <item> PROPATH </item>
- <item> PROVERSION </item>
- <item> QUERY-OFF-END </item>
- <item> Quoter </item>
- <item> RANDOM </item>
- <item> RECID </item>
- <item> RECORD-LENGTH </item>
- <item> REPLACE </item>
- <item> RETRY </item>
- <item> RETURN-VALUE </item>
- <item> RGB-VALUE </item>
- <item> RIGHT-TRIM </item>
- <item> R-INDEX </item>
- <item> ROUND </item>
- <item> ROWID </item>
- <item> SCREEN-LINES </item>
- <item> SDBNAME </item>
- <item> SEARCH </item>
- <item> SEEK </item>
- <item> SETUSERID </item>
- <item> SQRT </item>
- <item> STRING </item>
- <item> SUBSTITUTE </item>
- <item> SUBSTRING </item>
- <item> SUPER </item>
- <item> TERMINAL </item>
- <item> TIME </item>
- <item> TIMEZONE </item>
- <item> TODAY </item>
- <item> TO-ROWID </item>
- <item> TRANSACTION </item>
- <item> TRIM </item>
- <item> TRUNCATE </item>
- <item> USERID </item>
- <item> VALID-EVENT </item>
- <item> VALID-HANDLE </item>
- <item> WEEKDAY </item>
- <item> YEAR </item>
-</list>
-
-<list name="statements">
- <item> ACCUMULATE </item>
- <item> APPLY </item>
- <item> ASSIGN </item>
- <item> BELL </item>
- <item> BUFFER-COMPARE </item>
- <item> BUFFER-COPY </item>
- <item> CASE </item>
- <item> CHOOSE </item>
- <item> CLEAR </item>
- <item> CLOSE QUERY </item>
- <item> CLOSE STORED-PROCEDURE </item>
- <item> COLOR </item>
- <item> COMPILE </item>
- <item> CONNECT </item>
- <item> COPY-LOB </item>
- <item> CREATE </item>
- <item> CREATE ALIAS </item>
- <item> CREATE BROWSE </item>
- <item> CREATE BUFFER </item>
- <item> CREATE CALL </item>
- <item> CREATE DATABASE </item>
- <item> CREATE DATASET </item>
- <item> CREATE DATA-SOURCE </item>
- <item> CREATE QUERY </item>
- <item> CREATE SAX-READER </item>
- <item> CREATE SERVER </item>
- <item> CREATE SERVER-SOCKET </item>
- <item> CREATE SOAP-HEADER </item>
- <item> CREATE SOAP-HEADER-ENTRYREF </item>
- <item> CREATE SOCKET </item>
- <item> CREATE TEMP-TABLE </item>
- <item> CREATE widget </item>
- <item> CREATE WIDGET-POOL </item>
- <item> CREATE X-DOCUMENT </item>
- <item> CREATE X-NODEREF </item>
- <item> CURRENT-LANGUAGE </item>
- <item> CURRENT-VALUE </item>
- <item> DDE ADVISE </item>
- <item> DDE EXECUTE </item>
- <item> DDE GET </item>
- <item> DDE INITIATE </item>
- <item> DDE REQUEST </item>
- <item> DDE SEND </item>
- <item> DDE TERMINATE </item>
- <item> DEF </item>
- <item> DEFINE </item>
- <item> VAR </item>
- <item> VARIABLE </item>
- <item> DEFINE BROWSE </item>
- <item> DEFINE BUFFER </item>
- <item> DEFINE BUTTON </item>
- <item> DEFINE DATASET </item>
- <item> DEFINE DATA-SOURCE </item>
- <item> DEFINE FRAME </item>
- <item> DEFINE IMAGE </item>
- <item> DEFINE MENU </item>
- <item> DEFINE PARAMETER </item>
- <item> DEFINE QUERY </item>
- <item> DEFINE RECTANGLE </item>
- <item> DEFINE STREAM </item>
- <item> DEFINE SUB-MENU </item>
- <item> DEFINE TEMP-TABLE </item>
- <item> DEFINE VARIABLE </item>
- <item> DEFINE WORK-TABLE </item>
- <item> DEFINE WORKFILE </item>
- <item> DELETE </item>
- <item> DELETE ALIAS </item>
- <item> DELETE OBJECT </item>
- <item> DELETE PROCEDURE </item>
- <item> DELETE WIDGET </item>
- <item> DELETE WIDGET-POOL </item>
- <item> DICTIONARY </item>
- <item> DISABLE </item>
- <item> DISABLE TRIGGERS </item>
- <item> DISCONNECT </item>
- <item> DISPLAY </item>
- <item> DO </item>
- <item> DOS </item>
- <item> DOWN </item>
- <item> DYNAMIC-CURRENT-VALUE </item>
- <item> EMPTY TEMP-TABLE </item>
- <item> ENABLE </item>
- <item> END </item>
- <item> ENTRY </item>
- <item> EXPORT </item>
- <item> FIND </item>
- <item> FOR </item>
- <item> FORM </item>
- <item> FRAME-VALUE </item>
- <item> FUNCTION </item>
- <item> GET </item>
- <item> GET-KEY-VALUE </item>
- <item> HIDE </item>
- <item> IF </item>
- <item> THEN </item>
- <item> ELSE </item>
- <item> IMPORT </item>
- <item> INPUT CLEAR </item>
- <item> INPUT CLOSE </item>
- <item> INPUT FROM </item>
- <item> INPUT THROUGH </item>
- <item> INPUT-OUTPUT CLOSE </item>
- <item> INPUT-OUTPUT THROUGH </item>
- <item> INSERT </item>
- <item> LEAVE </item>
- <item> LENGTH </item>
- <item> LOAD </item>
- <item> LOAD-PICTURE </item>
- <item> MESSAGE </item>
- <item> NEXT </item>
- <item> NEXT-PROMPT </item>
- <item> ON </item>
- <item> OPEN QUERY </item>
- <item> OS-APPEND </item>
- <item> OS-COMMAND </item>
- <item> OS-COPY </item>
- <item> OS-CREATE-DIR </item>
- <item> OS-DELETE </item>
- <item> OS-RENAME </item>
- <item> OUTPUT CLOSE </item>
- <item> OUTPUT THROUGH </item>
- <item> OUTPUT TO </item>
- <item> OVERLAY </item>
- <item> PAGE </item>
- <item> PAUSE </item>
- <item> PROCEDURE </item>
- <item> PROCESS EVENTS </item>
- <item> PROMPT-FOR </item>
- <item> PROMSGS </item>
- <item> PROPATH </item>
- <item> PUBLISH </item>
- <item> PUT CURSOR </item>
- <item> PUT SCREEN </item>
- <item> PUT </item>
- <item> PUT-BITS </item>
- <item> PUT-BYTE </item>
- <item> PUT-BYTES </item>
- <item> PUT-DOUBLE </item>
- <item> PUT-FLOAT </item>
- <item> PUT-KEY-VALUE </item>
- <item> PUT-LONG </item>
- <item> PUT-SHORT </item>
- <item> PUT-STRING </item>
- <item> PUT-UNSIGNED-SHORT </item>
- <item> QUIT </item>
- <item> RAW-TRANSFER </item>
- <item> READKEY </item>
- <item> RELEASE </item>
- <item> RELEASE EXTERNAL </item>
- <item> RELEASE OBJECT </item>
- <item> REPEAT </item>
- <item> REPOSITION </item>
- <item> RETURN </item>
- <item> RUN </item>
- <item> RUN STORED-PROCEDURE </item>
- <item> RUN SUPER </item>
- <item> SAVE CACHE </item>
- <item> SEEK </item>
- <item> SET </item>
- <item> SET-BYTE-ORDER </item>
- <item> SET-POINTER-VALUE </item>
- <item> SET-SIZE </item>
- <item> SCROLL </item>
- <item> SHOW-STATS </item>
- <item> STATUS </item>
- <item> STOP </item>
- <item> SUBSCRIBE </item>
- <item> SUBSTRING </item>
- <item> SYSTEM-DIALOG COLOR </item>
- <item> SYSTEM-DIALOG FONT </item>
- <item> SYSTEM-DIALOG GET-DIR </item>
- <item> SYSTEM-DIALOG GET-FILE </item>
- <item> SYSTEM-DIALOG PRINTER-SETUP </item>
- <item> SYSTEM-HELP </item>
- <item> TERMINAL </item>
- <item> TRANSACTION-MODE AUTOMATIC </item>
- <item> TRIGGER PROCEDURE </item>
- <item> UNDERLINE </item>
- <item> UNDO </item>
- <item> UNIX </item>
- <item> UNLOAD </item>
- <item> UNSUBSCRIBE </item>
- <item> UP </item>
- <item> UPDATE </item>
- <item> USE </item>
- <item> VALIDATE </item>
- <item> VIEW </item>
- <item> WAIT-FOR </item>
-</list>
-
-<list name="widgets">
- <item> BROWSE </item>
- <item> BUTTON </item>
- <item> COMBO-BOX </item>
- <item> CONTROL-FRAME </item>
- <item> DIALOG-BOX </item>
- <item> EDITOR </item>
- <item> FIELD-GROUP </item>
- <item> FILL-IN </item>
- <item> FRAME </item>
- <item> IMAGE </item>
- <item> LITERAL </item>
- <item> MENU </item>
- <item> MENU-ITEM </item>
- <item> RADIO-SET </item>
- <item> RECTANGLE </item>
- <item> SELECTION-LIST </item>
- <item> SLIDER </item>
- <item> SUB-MENU </item>
- <item> TEXT </item>
- <item> TOGGLE-BOX </item>
- <item> WINDOW </item>
-</list>
-
-<list name="handles">
- <item> ACTIVE-WINDOW </item>
- <item> Buffer </item>
- <item> Buffer-field </item>
- <item> CALL </item>
- <item> CLIPBOARD </item>
- <item> CODEBASE-LOCATOR </item>
- <item> COLOR-TABLE </item>
- <item> COM-SELF </item>
- <item> COMPILER </item>
- <item> CURRENT-WINDOW </item>
- <item> DATA-RELATION </item>
- <item> DATE-SOURCE </item>
- <item> DEBUGGER </item>
- <item> DEFAULT-WINDOW </item>
- <item> ERROR-STATUS </item>
- <item> FILE-INFO </item>
- <item> FOCUS </item>
- <item> FONT-TABLE </item>
- <item> LAST-EVENT </item>
- <item> LOG-MANAGER </item>
- <item> PRODATASET </item>
- <item> QUERY </item>
- <item> RCODE-INFO </item>
- <item> SAX-ATTRIBUTES </item>
- <item> SAX-READER </item>
- <item> SELF </item>
- <item> SERVER SOCKET </item>
- <item> SESSION </item>
- <item> SOAP-FAULT </item>
- <item> SOAP-FAULT-DETAIL </item>
- <item> SOAP-HEADER </item>
- <item> SOAP-HEADER-ENTRYREF </item>
- <item> SOCKET </item>
- <item> SOURCE-PROCEDURE </item>
- <item> TARGET-PROCEDURE </item>
- <item> TEMP-TABLE </item>
- <item> THIS-PROCEDURE </item>
- <item> TRANSACTION </item>
- <item> WEB-CONTEXT </item>
- <item> X-DOCUMENT </item>
- <item> X-NODEREF </item>
-</list>
-
-<list name="properties">
- <item> Control-Name </item>
- <item> CONTROLS </item>
- <item> Height </item>
- <item> HonorProKeys </item>
- <item> HonorReturnKey </item>
- <item> LEFT </item>
- <item> NAME </item>
- <item> TOP </item>
- <item> WIDTH </item>
- <item> TAG </item>
-</list>
-
-<list name="attributes">
- <item> ACCELERATOR </item>
- <item> ACTIVE </item>
- <item> ACTOR </item>
- <item> ADM-DATA </item>
- <item> AFTER-BUFFER </item>
- <item> AFTER-ROWID </item>
- <item> AFTER-TABLE </item>
- <item> ALLOW-COLUMN-SEARCHING </item>
- <item> ALWAYS-ON-TOP </item>
- <item> AMBIGUOUS </item>
- <item> APPL-ALERT-BOXES </item>
- <item> APPSERVER-INFO </item>
- <item> APPSERVER-PASSWORD </item>
- <item> APPSERVER-USERID </item>
- <item> ASYNCHRONOUS </item>
- <item> ASYNC-REQUEST-COUNT </item>
- <item> ASYNC-REQUEST-HANDLE </item>
- <item> ATTRIBUTE-NAMES </item>
- <item> ATTR-SPACE </item>
- <item> AUTO-COMPLETION </item>
- <item> AUTO-DELETE </item>
- <item> AUTO-END-KEY </item>
- <item> AUTO-GO </item>
- <item> AUTO-INDENT </item>
- <item> AUTO-RESIZE </item>
- <item> AUTO-RETURN </item>
- <item> AUTO-VALIDATE </item>
- <item> AUTO-ZAP </item>
- <item> AVAILABLE </item>
- <item> AVAILABLE-FORMATS </item>
- <item> BACKGROUND </item>
- <item> BASE-ADE </item>
- <item> BASIC-LOGGING </item>
- <item> BATCH-MODE </item>
- <item> BEFORE-BUFFER </item>
- <item> BEFORE-ROWID </item>
- <item> BEFORE-TABLE </item>
- <item> BGCOLOR </item>
- <item> BLANK </item>
- <item> BLOCK-ITERATION-DISPLAY </item>
- <item> BORDER-BOTTOM-CHARS </item>
- <item> BORDER-BOTTOM-PIXELS </item>
- <item> BORDER-LEFT-CHARS </item>
- <item> BORDER-LEFT-PIXELS </item>
- <item> BORDER-RIGHT-CHARS </item>
- <item> BORDER-RIGHT-PIXELS </item>
- <item> BORDER-TOP-CHARS </item>
- <item> BORDER-TOP-PIXELS </item>
- <item> BOX </item>
- <item> BOX-SELECTABLE </item>
- <item> BUFFER-CHARS </item>
- <item> BUFFER-VALUE </item>
- <item> BYTES-READ </item>
- <item> BYTES-WRITTEN </item>
- <item> CACHE </item>
- <item> CALL-NAME </item>
- <item> CALL-TYPE </item>
- <item> BUFFER-FIELD </item>
- <item> BUFFER-HANDLE </item>
- <item> BUFFER-LINES </item>
- <item> BUFFER-NAME </item>
- <item> CANCEL-BUTTON </item>
- <item> CANCELLED </item>
- <item> CAN-CREATE </item>
- <item> CAN-DELETE </item>
- <item> CAN-READ </item>
- <item> CAN-WRITE </item>
- <item> CAREFUL-PAINT </item>
- <item> CASE-SENSITIVE </item>
- <item> CENTERED </item>
- <item> CHARSET </item>
- <item> CHECKED </item>
- <item> CHILD-BUFFER </item>
- <item> CHILD-NUM </item>
- <item> CLIENT-CONNECTION-ID </item>
- <item> CLIENT-TYPE </item>
- <item> CODE </item>
- <item> CODEPAGE </item>
- <item> COLUMN </item>
- <item> COLUMN-BGCOLOR </item>
- <item> COLUMN-DCOLOR </item>
- <item> COLUMN-FGCOLOR </item>
- <item> COLUMN-FONT </item>
- <item> COLUMN-LABEL </item>
- <item> COLUMN-MOVABLE </item>
- <item> COLUMN-PFCOLOR </item>
- <item> COLUMN-READ-ONLY </item>
- <item> COLUMN-RESIZABLE </item>
- <item> COLUMN-SCROLLING </item>
- <item> COM-HANDLE </item>
- <item> COMPLETE </item>
- <item> CONTEXT-HELP </item>
- <item> CONTEXT-HELP-FILE </item>
- <item> CONTEXT-HELP-ID </item>
- <item> CONTROL-BOX </item>
- <item> CONVERT-D-COLORS </item>
- <item> CPCASE </item>
- <item> CPCOLL </item>
- <item> CPINTERNAL </item>
- <item> CPLOG </item>
- <item> CPPRINT </item>
- <item> CPRCODEIN </item>
- <item> CPRCODEOUT </item>
- <item> CPSTREAM </item>
- <item> CPTERM </item>
- <item> CRC-VALUE </item>
- <item> CURRENT-CHANGED </item>
- <item> CURRENT-COLUMN </item>
- <item> CURRENT-ITERATION </item>
- <item> CURRENT-RESULT-ROW </item>
- <item> CURRENT-ROW-MODIFIED </item>
- <item> CURRENT-WINDOW </item>
- <item> CURSOR-CHAR </item>
- <item> CURSOR-LINE </item>
- <item> CURSOR-OFFSET </item>
- <item> DATA-ENTRY-RETURN </item>
- <item> DATA-SOURCE </item>
- <item> DATA-TYPE </item>
- <item> DATASET </item>
- <item> DATE-FORMAT </item>
- <item> DBNAME </item>
- <item> DB-REFERENCES </item>
- <item> DCOLOR </item>
- <item> DDE-ERROR </item>
- <item> DDE-ID </item>
- <item> DDE-ITEM </item>
- <item> DDE-NAME </item>
- <item> DDE-TOPIC </item>
- <item> DEBLANK </item>
- <item> DEBUG-ALERT </item>
- <item> DECIMALS </item>
- <item> DEFAULT </item>
- <item> DEFAULT-BUFFER-HANDLE </item>
- <item> DEFAULT-BUTTON </item>
- <item> DEFAULT-COMMIT </item>
- <item> DELIMITER </item>
- <item> DISABLE-AUTO-ZAP </item>
- <item> DISPLAY-TIMEZONE </item>
- <item> DISPLAY-TYPE </item>
- <item> DOWN </item>
- <item> DRAG-ENABLED </item>
- <item> DROP-TARGET </item>
- <item> DYNAMIC </item>
- <item> EDGE-CHARS </item>
- <item> EDGE-PIXELS </item>
- <item> EDIT-CAN-PASTE </item>
- <item> EDIT-CAN-UNDO </item>
- <item> EMPTY </item>
- <item> ENCODING </item>
- <item> END-USER-PROMPT </item>
- <item> ENTRY-TYPES-LIST </item>
- <item> ERROR </item>
- <item> ERROR-COLUMN </item>
- <item> ERROR-OBJECT-DETAIL </item>
- <item> ERROR-ROW </item>
- <item> ERROR-STRING </item>
- <item> EVENT-PROCEDURE </item>
- <item> EVENT-PROCEDURE-CONTEXT </item>
- <item> EVENT-TYPE </item>
- <item> EXPAND </item>
- <item> EXPANDABLE </item>
- <item> EXTENT </item>
- <item> FGCOLOR </item>
- <item> FILE-CREATE-DATE </item>
- <item> FILE-CREATE-TIME </item>
- <item> FILE-MOD-DATE </item>
- <item> FILE-MOD-TIME </item>
- <item> FILE-NAME </item>
- <item> FILE-OFFSET </item>
- <item> FILE-SIZE </item>
- <item> FILE-TYPE </item>
- <item> FILLED </item>
- <item> FILL-MODE </item>
- <item> FILL-WHERE-STRING </item>
- <item> FIRST-ASYNC-REQUEST </item>
- <item> FIRST-BUFFER </item>
- <item> FIRST-CHILD </item>
- <item> FIRST-COLUMN </item>
- <item> FIRST-DATASET </item>
- <item> FIRST-DATA-SOURCE </item>
- <item> FIRST-PROCEDURE </item>
- <item> FIRST-QUERY </item>
- <item> FIRST-SERVER </item>
- <item> FIRST-SERVER-SOCKET </item>
- <item> FIRST-SOCKET </item>
- <item> FIRST-TAB-ITEM </item>
- <item> FIT-LAST-COLUMN </item>
- <item> FLAT-BUTTON </item>
- <item> FOCUSED-ROW </item>
- <item> FOCUSED-ROW-SELECTED </item>
- <item> FONT </item>
- <item> FOREGROUND </item>
- <item> FORMAT </item>
- <item> FORWARD-ONLY </item>
- <item> FRAME </item>
- <item> FRAME-COL </item>
- <item> FRAME-NAME </item>
- <item> FRAME-ROW </item>
- <item> FRAME-SPACING </item>
- <item> FRAME-X </item>
- <item> FRAME-Y </item>
- <item> FREQUENCY </item>
- <item> FULL-HEIGHT-CHARS </item>
- <item> FULL-HEIGHT-PIXELS </item>
- <item> FULL-PATHNAME </item>
- <item> FULL-WIDTH-CHARS </item>
- <item> FULL-WIDTH-PIXELS </item>
- <item> FUNCTION </item>
- <item> GRAPHIC-EDGE </item>
- <item> GRID-FACTOR-HORIZONTAL </item>
- <item> GRID-FACTOR-VERTICAL </item>
- <item> GRID-SNAP </item>
- <item> GRID-UNIT-HEIGHT-CHARS </item>
- <item> GRID-UNIT-HEIGHT-PIXELS </item>
- <item> GRID-UNIT-WIDTH-CHARS </item>
- <item> GRID-UNIT-WIDTH-PIXELS </item>
- <item> GRID-VISIBLE </item>
- <item> HANDLER </item>
- <item> HAS-LOBS </item>
- <item> HAS-RECORDS </item>
- <item> HEIGHT-CHARS </item>
- <item> HEIGHT-PIXELS </item>
- <item> HELP </item>
- <item> HIDDEN </item>
- <item> HORIZONTAL </item>
- <item> HTML-CHARSET </item>
- <item> HWND </item>
- <item> ICFPARAMETER </item>
- <item> ICON </item>
- <item> IGNORE-CURRENT-MODIFIED </item>
- <item> IMAGE </item>
- <item> IMAGE-DOWN </item>
- <item> IMAGE-INSENSITIVE </item>
- <item> IMAGE-UP </item>
- <item> IMMEDIATE-DISPLAY </item>
- <item> INDEX </item>
- <item> INDEX-INFORMATION </item>
- <item> INITIAL </item>
- <item> INNER-CHARS </item>
- <item> INNER-LINES </item>
- <item> INPUT-VALUE </item>
- <item> INSTANTIATING-PROCEDURE </item>
- <item> INTERNAL-ENTRIES </item>
- <item> IN-HANDLE </item>
- <item> IS-OPEN </item>
- <item> IS-PARAMETER-SET </item>
- <item> ITEMS-PER-ROW </item>
- <item> KEEP-CONNECTION-OPEN </item>
- <item> KEEP-FRAME-Z-ORDER </item>
- <item> KEEP-SECURITY-CACHE </item>
- <item> KEY </item>
- <item> LABEL </item>
- <item> LABEL-BGCOLOR </item>
- <item> LABEL-DCOLOR </item>
- <item> LABEL-FGCOLOR </item>
- <item> LABEL-FONT </item>
- <item> LABELS </item>
- <item> LANGUAGES </item>
- <item> LARGE </item>
- <item> LARGE-TO-SMALL </item>
- <item> LAST-ASYNC-REQUEST </item>
- <item> LAST-CHILD </item>
- <item> LAST-PROCEDURE </item>
- <item> LAST-SERVER </item>
- <item> LAST-SERVER-SOCKET </item>
- <item> LAST-SOCKET </item>
- <item> LAST-TAB-ITEM </item>
- <item> LENGTH </item>
- <item> LINE </item>
- <item> LIST-ITEM-PAIRS </item>
- <item> LIST-ITEMS </item>
- <item> LITERAL-QUESTION </item>
- <item> LOCAL-HOST </item>
- <item> LOCAL-NAME </item>
- <item> LOCAL-PORT </item>
- <item> LOCATOR-COLUMN-NUMBER </item>
- <item> LOCATOR-LINE-NUMBER </item>
- <item> LOCATOR-PUBLIC-ID </item>
- <item> LOCATOR-SYSTEM-ID </item>
- <item> LOCATOR-TYPE </item>
- <item> LOCKED </item>
- <item> LOG-ENTRY-TYPES </item>
- <item> LOG-THRESHOLD </item>
- <item> LOGFILE-NAME </item>
- <item> LOGGING-LEVEL </item>
- <item> MANDATORY </item>
- <item> MANUAL-HIGHLIGHT </item>
- <item> MAX-BUTTON </item>
- <item> MAX-CHARS </item>
- <item> MAX-DATA-GUESS </item>
- <item> MAX-HEIGHT-CHARS </item>
- <item> MAX-HEIGHT-PIXELS </item>
- <item> MAX-VALUE </item>
- <item> MAX-WIDTH-CHARS </item>
- <item> MAX-WIDTH-PIXELS </item>
- <item> MD-VALUE </item>
- <item> MENU-BAR </item>
- <item> MENU-KEY </item>
- <item> MENU-MOUSE </item>
- <item> MESSAGE-AREA </item>
- <item> MESSAGE-AREA-FONT </item>
- <item> MIN-BUTTON </item>
- <item> MIN-COLUMN-WIDTH-CHARS </item>
- <item> MIN-COLUMN-WIDTH-PIXELS </item>
- <item> MIN-HEIGHT-CHARS </item>
- <item> MIN-HEIGHT-PIXELS </item>
- <item> MIN-SCHEMA-MARSHAL </item>
- <item> MIN-VALUE </item>
- <item> MIN-WIDTH-CHARS </item>
- <item> MIN-WIDTH-PIXELS </item>
- <item> MODIFIED </item>
- <item> MOUSE-POINTER </item>
- <item> MOVABLE </item>
- <item> MULTIPLE </item>
- <item> MULTITASKING-INTERVAL </item>
- <item> MUST-UNDERSTAND </item>
- <item> NAME </item>
- <item> NAMESPACE-PREFIX </item>
- <item> NAMESPACE-URI </item>
- <item> NEEDS-APPSERVER-PROMPT </item>
- <item> NEEDS-PROMPT </item>
- <item> NEW </item>
- <item> NEW-ROW </item>
- <item> NEXT-COLUMN </item>
- <item> NEXT-SIBLING </item>
- <item> NEXT-TAB-ITEM </item>
- <item> NO-CURRENT-VALUE </item>
- <item> NO-EMPTY-SPACE </item>
- <item> NO-FOCUS </item>
- <item> NO-SCHEMA-MARSHAL </item>
- <item> NO-VALIDATE </item>
- <item> NODE-VALUE </item>
- <item> NUM-BUFFERS </item>
- <item> NUM-BUTTONS </item>
- <item> NUM-CHILD-RELATIONS </item>
- <item> NUM-CHILDREN </item>
- <item> NUM-COLUMNS </item>
- <item> NUM-DROPPED-FILES </item>
- <item> NUM-ENTRIES </item>
- <item> NUM-FIELDS </item>
- <item> NUM-FORMATS </item>
- <item> NUM-HEADER-ENTRIES </item>
- <item> NUM-ITEMS </item>
- <item> NUM-ITERATIONS </item>
- <item> NUM-LINES </item>
- <item> NUM-LOCKED-COLUMNS </item>
- <item> NUM-LOG-FILES </item>
- <item> NUM-MESSAGES </item>
- <item> NUM-PARAMETERS </item>
- <item> NUM-RELATIONS </item>
- <item> NUM-REPLACED </item>
- <item> NUM-RESULTS </item>
- <item> NUM-SELECTED-ROWS </item>
- <item> NUM-SELECTED-WIDGETS </item>
- <item> NUM-SOURCE-BUFFERS </item>
- <item> NUM-TABS </item>
- <item> NUM-TO-RETAIN </item>
- <item> NUM-TOP-BUFFERS </item>
- <item> NUM-VISIBLE-COLUMNS </item>
- <item> NUMERIC-DECIMAL-POINT </item>
- <item> NUMERIC-FORMAT </item>
- <item> NUMERIC-SEPARATOR </item>
- <item> ON-FRAME-BORDER </item>
- <item> ORIGIN-HANDLE </item>
- <item> ORIGIN-ROWID </item>
- <item> OVERLAY </item>
- <item> OWNER </item>
- <item> OWNER-DOCUMENT </item>
- <item> PAGE-BOTTOM </item>
- <item> PAGE-TOP </item>
- <item> PARAMETER </item>
- <item> PARENT </item>
- <item> PARENT-BUFFER </item>
- <item> PARENT-RELATION </item>
- <item> PARSE-STATUS </item>
- <item> PASSWORD-FIELD </item>
- <item> PATHNAME </item>
- <item> PERSISTENT </item>
- <item> PERSISTENT-CACHE-DISABLED </item>
- <item> PERSISTENT-PROCEDURE </item>
- <item> PFCOLOR </item>
- <item> PIXELS-PER-COLUMN </item>
- <item> PIXELS-PER-ROW </item>
- <item> POPUP-MENU </item>
- <item> POPUP-ONLY </item>
- <item> POSITION </item>
- <item> PREPARED </item>
- <item> PREPARE-STRING </item>
- <item> PREV-COLUMN </item>
- <item> PREV-SIBLING </item>
- <item> PREV-TAB-ITEM </item>
- <item> PRIMARY </item>
- <item> PRINTER-CONTROL-HANDLE </item>
- <item> PRINTER-HDC </item>
- <item> PRINTER-NAME </item>
- <item> PRINTER-PORT </item>
- <item> PRIVATE-DATA </item>
- <item> PROCEDURE-NAME </item>
- <item> PROGRESS-SOURCE </item>
- <item> PROXY </item>
- <item> PROXY-PASSWORD </item>
- <item> PROXY-USERID </item>
- <item> PUBLIC-ID </item>
- <item> PUBLISHED-EVENTS </item>
- <item> QUERY </item>
- <item> QUERY-OFF-END </item>
- <item> QUIT </item>
- <item> RADIO-BUTTONS </item>
- <item> READ-ONLY </item>
- <item> RECID </item>
- <item> RECORD-LENGTH </item>
- <item> REFRESHABLE </item>
- <item> REJECTED </item>
- <item> RELATION-FIELDS </item>
- <item> RELATIONS-ACTIVE </item>
- <item> REMOTE </item>
- <item> REMOTE-HOST </item>
- <item> REMOTE-PORT </item>
- <item> REPOSITION </item>
- <item> RESIZABLE </item>
- <item> RESIZE </item>
- <item> RETAIN-SHAPE </item>
- <item> RETURN-INSERTED </item>
- <item> RETURN-VALUE </item>
- <item> RETURN-VALUE-DATA-TYPE </item>
- <item> ROW </item>
- <item> ROW-HEIGHT-CHARS </item>
- <item> ROW-HEIGHT-PIXELS </item>
- <item> ROW-STATE </item>
- <item> ROWID </item>
- <item> ROW-MARKERS </item>
- <item> ROW-RESIZABLE </item>
- <item> SAVE-WHERE-STRING </item>
- <item> SCHEMA-CHANGE </item>
- <item> SCHEMA-PATH </item>
- <item> SCREEN-LINES </item>
- <item> SCREEN-VALUE </item>
- <item> SCROLL-BARS </item>
- <item> SCROLLABLE </item>
- <item> SCROLLBAR-HORIZONTAL </item>
- <item> SCROLLBAR-VERTICAL </item>
- <item> SELECTABLE </item>
- <item> SELECTED </item>
- <item> SELECTION-END </item>
- <item> SELECTION-START </item>
- <item> SELECTION-TEXT </item>
- <item> SENSITIVE </item>
- <item> SEPARATORS </item>
- <item> SEPARATOR-FGCOLOR </item>
- <item> SERVER </item>
- <item> SERVER-CONNECTION-BOUND </item>
- <item> SERVER-CONNECTION-BOUND-REQUEST </item>
- <item> SERVER-CONNECTION-CONTEXT </item>
- <item> SERVER-CONNECTION-ID </item>
- <item> SERVER-OPERATING-MODE </item>
- <item> SHOW-IN-TASKBAR </item>
- <item> SIDE-LABEL-HANDLE </item>
- <item> SIDE-LABELS </item>
- <item> SKIP-DELETED-RECORD </item>
- <item> SMALL-ICON </item>
- <item> SMALL-TITLE </item>
- <item> SOAP-FAULT-ACTOR </item>
- <item> SOAP-FAULT-CODE </item>
- <item> SOAP-FAULT-DETAIL </item>
- <item> SOAP-FAULT-STRING </item>
- <item> SORT </item>
- <item> STARTUP-PARAMETERS </item>
- <item> STATUS-AREA </item>
- <item> STATUS-AREA-FONT </item>
- <item> STOP </item>
- <item> STOPPED </item>
- <item> STREAM </item>
- <item> STRETCH-TO-FIT </item>
- <item> STRING-VALUE </item>
- <item> SUBTYPE </item>
- <item> SUPER-PROCEDURES </item>
- <item> SUPPRESS-NAMESPACE-PROCESSING </item>
- <item> SUPPRESS-WARNINGS </item>
- <item> SYSTEM-ALERT-BOXES </item>
- <item> SYSTEM-ID </item>
- <item> TAB-POSITION </item>
- <item> TAB-STOP </item>
- <item> TABLE </item>
- <item> TABLE-CRC-LIST </item>
- <item> TABLE-HANDLE </item>
- <item> TABLE-LIST </item>
- <item> TABLE-NUMBER </item>
- <item> TEMP-DIRECTORY </item>
- <item> TEXT-SELECTED </item>
- <item> THREE-D </item>
- <item> TIC-MARKS </item>
- <item> TIME-SOURCE </item>
- <item> TITLE </item>
- <item> TITLE-BGCOLOR </item>
- <item> TITLE-DCOLOR </item>
- <item> TITLE-FGCOLOR </item>
- <item> TITLE-FONT </item>
- <item> TOGGLE-BOX </item>
- <item> TOOLTIP </item>
- <item> TOOLTIPS </item>
- <item> TOP-ONLY </item>
- <item> TRACKING-CHANGES </item>
- <item> TRANSACTION </item>
- <item> TRANSPARENT </item>
- <item> TRANS-INIT-PROCEDURE </item>
- <item> TYPE </item>
- <item> UNDO </item>
- <item> UNIQUE-ID </item>
- <item> UNIQUE-MATCH </item>
- <item> URL </item>
- <item> URL-PASSWORD </item>
- <item> URL-USERID </item>
- <item> DISPLAY </item>
- <item> VALIDATE-EXPRESSION </item>
- <item> VALIDATE-MESSAGE </item>
- <item> VALIDATION-ENABLED </item>
- <item> VALUE </item>
- <item> VIEW-FIRST-COLUMN-ON-REOPEN </item>
- <item> VIRTUAL-HEIGHT-CHARS </item>
- <item> VIRTUAL-HEIGHT-PIXELS </item>
- <item> VIRTUAL-WIDTH-CHARS </item>
- <item> VIRTUAL-WIDTH-PIXELS </item>
- <item> VISIBLE </item>
- <item> WARNING </item>
- <item> WHERE-STRING </item>
- <item> WIDGET-ENTER </item>
- <item> WIDGET-LEAVE </item>
- <item> WIDTH-CHARS </item>
- <item> WIDTH-PIXELS </item>
- <item> WINDOW </item>
- <item> WINDOW-STATE </item>
- <item> WINDOW-SYSTEM </item>
- <item> WORD-WRAP </item>
- <item> WORK-AREA-HEIGHT-PIXELS </item>
- <item> WORK-AREA-WIDTH-PIXELS </item>
- <item> WORK-AREA-X </item>
- <item> WORK-AREA-Y </item>
- <item> X </item>
- <item> XML-SCHEMA-PATH </item>
- <item> XML-SUPPRESS-NAMESPACE-PROCESSING </item>
- <item> Y </item>
- <item> YEAR-OFFSET </item>
-</list>
-
-<list name="methods">
- <item> ACCEPT-CHANGES </item>
- <item> ACCEPT-ROW-CHANGES </item>
- <item> ADD-BUFFER </item>
- <item> ADD-CALC-COLUMN </item>
- <item> ADD-COLUMNS-FROM </item>
- <item> ADD-EVENTS-PROCEDURE </item>
- <item> ADD-FIELDS-FROM </item>
- <item> ADD-FIRST </item>
- <item> ADD-HEADER-ENTRY </item>
- <item> ADD-INDEX-FIELD </item>
- <item> ADD-LAST </item>
- <item> ADD-LIKE-COLUMN </item>
- <item> ADD-LIKE-FIELD </item>
- <item> ADD-LIKE-INDEX </item>
- <item> ADD-NEW-FIELD </item>
- <item> ADD-NEW-INDEX </item>
- <item> ADD-RELATION </item>
- <item> ADD-SOURCE-BUFFER </item>
- <item> ADD-SUPER-PROCEDURE </item>
- <item> APPEND-CHILD </item>
- <item> APPLY-CALLBACK </item>
- <item> ATTACH-DATA-SOURCE </item>
- <item> BUFFER-COMPARE </item>
- <item> BUFFER-COPY </item>
- <item> BUFFER-CREATE </item>
- <item> BUFFER-DELETE </item>
- <item> BUFFER-FIELD </item>
- <item> BUFFER-RELEASE </item>
- <item> BUFFER-VALIDATE </item>
- <item> CANCEL-BREAK </item>
- <item> CANCEL-REQUESTS </item>
- <item> CLEAR </item>
- <item> CLEAR-SELECTION </item>
- <item> CLONE-NODE </item>
- <item> CONNECT </item>
- <item> CONNECTED </item>
- <item> CONVERT-TO-OFFSET </item>
- <item> CREATE-LIKE </item>
- <item> CREATE-NODE </item>
- <item> CREATE-NODE-NAMESPACE </item>
- <item> CREATE-RESULT-LIST-ENTRY </item>
- <item> DEBUG </item>
- <item> DELETE </item>
- <item> DELETE-CHAR </item>
- <item> DELETE-CURRENT-ROW </item>
- <item> DELETE-HEADER-ENTRY </item>
- <item> DELETE-LINE </item>
- <item> DELETE-NODE </item>
- <item> DELETE-RESULT-LIST-ENTRY </item>
- <item> DELETE-SELECTED-ROW </item>
- <item> DELETE-SELECTED-ROWS </item>
- <item> DESELECT-FOCUSED-ROW </item>
- <item> DESELECT-ROWS </item>
- <item> DESELECT-SELECTED-ROW </item>
- <item> DETACH-DATA-SOURCE </item>
- <item> DISABLE </item>
- <item> DISABLE-CONNECTIONS </item>
- <item> DISABLE-DUMP-TRIGGERS </item>
- <item> DISABLE-LOAD-TRIGGERS </item>
- <item> DISCONNECT </item>
- <item> DISPLAY-MESSAGE </item>
- <item> DUMP-LOGGING-NOW </item>
- <item> EDIT-CLEAR </item>
- <item> EDIT-COPY </item>
- <item> EDIT-CUT </item>
- <item> EDIT-PASTE </item>
- <item> EDIT-UNDO </item>
- <item> EMPTY-DATASET </item>
- <item> EMPTY-TEMP-TABLE </item>
- <item> ENABLE </item>
- <item> ENABLE-CONNECTIONS </item>
- <item> ENABLE-EVENTS </item>
- <item> END-FILE-DROP </item>
- <item> ENTRY </item>
- <item> EXPORT </item>
- <item> FETCH-SELECTED-ROW </item>
- <item> FILL </item>
- <item> FIND-BY-ROWID </item>
- <item> FIND-CURRENT </item>
- <item> FIND-FIRST </item>
- <item> FIND-LAST </item>
- <item> FIND-UNIQUE </item>
- <item> GET-ATTRIBUTE </item>
- <item> GET-ATTRIBUTE-NODE </item>
- <item> GET-BLUE-VALUE </item>
- <item> GET-BROWSE-COLUMN </item>
- <item> GET-BUFFER-HANDLE </item>
- <item> GET-BYTES-AVAILABLE </item>
- <item> GET-CHANGES </item>
- <item> GET-CHILD </item>
- <item> GET-CHILD-RELATION </item>
- <item> GET-CURRENT </item>
- <item> GET-DATASET-BUFFER </item>
- <item> GET-DOCUMENT-ELEMENT </item>
- <item> GET-DROPPED-FILE </item>
- <item> GET-DYNAMIC </item>
- <item> GET-FIRST </item>
- <item> GET-GREEN-VALUE </item>
- <item> GET-HEADER-ENTRY </item>
- <item> GET-INDEX-BY-NAMESPACE-NAME </item>
- <item> GET-INDEX-BY-QNAME </item>
- <item> GET-ITERATION </item>
- <item> GET-LAST </item>
- <item> GET-LOCALNAME-BY-INDEX </item>
- <item> GET-MESSAGE </item>
- <item> GET-NEXT </item>
- <item> GET-NODE </item>
- <item> GET-NUMBER </item>
- <item> GET-PARENT </item>
- <item> GET-PREV </item>
- <item> GET-PRINTERS </item>
- <item> GET-QNAME-BY-INDEX </item>
- <item> GET-RED-VALUE </item>
- <item> GET-RELATION </item>
- <item> GET-REPOSITIONED-ROW </item>
- <item> GET-RGB-VALUE </item>
- <item> GET-SELECTED-WIDGET </item>
- <item> GET-SERIALIZED </item>
- <item> GET-SIGNATURE </item>
- <item> GET-SOCKET-OPTION </item>
- <item> GET-SOURCE-BUFFER </item>
- <item> GET-TAB-ITEM </item>
- <item> GET-TEXT-HEIGHT-CHARS </item>
- <item> GET-TEXT-HEIGHT-PIXELS </item>
- <item> GET-TEXT-WIDTH-CHARS </item>
- <item> GET-TEXT-WIDTH-PIXELS </item>
- <item> GET-TOP-BUFFER </item>
- <item> GET-TYPE-BY-INDEX </item>
- <item> GET-TYPE-BY-NAMESPACE-NAME </item>
- <item> GET-TYPE-BY-QNAME </item>
- <item> GET-URI-BY-INDEX </item>
- <item> GET-VALUE-BY-INDEX </item>
- <item> GET-VALUE-BY-NAMESPACE-NAME </item>
- <item> GET-VALUE-BY-QNAME </item>
- <item> GET-WAIT-STATE </item>
- <item> IMPORT-NODE </item>
- <item> INDEX-INFORMATION </item>
- <item> INITIALIZE-DOCUMENT-TYPE </item>
- <item> INITIATE </item>
- <item> INSERT </item>
- <item> INSERT-BACKTAB </item>
- <item> INSERT-BEFORE </item>
- <item> INSERT-FILE </item>
- <item> INSERT-ROW </item>
- <item> INSERT-STRING </item>
- <item> INSERT-TAB </item>
- <item> INVOKE </item>
- <item> IS-ROW-SELECTED </item>
- <item> IS-SELECTED </item>
- <item> LOAD </item>
- <item> LoadControls </item>
- <item> LOAD-ICON </item>
- <item> LOAD-IMAGE </item>
- <item> LOAD-IMAGE-DOWN </item>
- <item> LOAD-IMAGE-INSENSITIVE </item>
- <item> LOAD-IMAGE-UP </item>
- <item> LOAD-MOUSE-POINTER </item>
- <item> LOAD-SMALL-ICON </item>
- <item> LONGCHAR-TO-NODE-VALUE </item>
- <item> LOOKUP </item>
- <item> MEMPTR-TO-NODE-VALUE </item>
- <item> MERGE-CHANGES </item>
- <item> MERGE-ROW-CHANGES </item>
- <item> MOVE-AFTER-TAB-ITEM </item>
- <item> MOVE-BEFORE-TAB-ITEM </item>
- <item> MOVE-COLUMN </item>
- <item> MOVE-TO-BOTTOM </item>
- <item> MOVE-TO-EOF </item>
- <item> MOVE-TO-TOP </item>
- <item> NODE-VALUE-TO-LONGCHAR </item>
- <item> NODE-VALUE-TO-MEMPTR </item>
- <item> NORMALIZE </item>
- <item> QUERY-CLOSE </item>
- <item> QUERY-OPEN </item>
- <item> QUERY-PREPARE </item>
- <item> RAW-TRANSFER </item>
- <item> READ </item>
- <item> READ-FILE </item>
- <item> REFRESH </item>
- <item> REJECT-CHANGES </item>
- <item> REJECT-ROW-CHANGES </item>
- <item> REMOVE-ATTRIBUTE </item>
- <item> REMOVE-CHILD </item>
- <item> REMOVE-EVENTS-PROCEDURE </item>
- <item> REMOVE-SUPER-PROCEDURE </item>
- <item> REPLACE </item>
- <item> REPLACE-CHILD </item>
- <item> REPLACE-SELECTION-TEXT </item>
- <item> REPOSITION-BACKWARD </item>
- <item> REPOSITION-FORWARD </item>
- <item> REPOSITION-TO-ROW </item>
- <item> REPOSITION-TO-ROWID </item>
- <item> SAVE </item>
- <item> SAVE-FILE </item>
- <item> SAVE-ROW-CHANGES </item>
- <item> SAX-PARSE </item>
- <item> SAX-PARSE-FIRST </item>
- <item> SAX-PARSE-NEXT </item>
- <item> SCROLL-TO-CURRENT-ROW </item>
- <item> SCROLL-TO-ITEM </item>
- <item> SCROLL-TO-SELECTED-ROW </item>
- <item> SEARCH </item>
- <item> SELECT-ALL </item>
- <item> SELECT-FOCUSED-ROW </item>
- <item> SELECT-NEXT-ROW </item>
- <item> SELECT-PREV-ROW </item>
- <item> SELECT-ROW </item>
- <item> SET-ACTOR </item>
- <item> SET-ATTRIBUTE </item>
- <item> SET-ATTRIBUTE-NODE </item>
- <item> SET-BLUE-VALUE </item>
- <item> SET-BREAK </item>
- <item> SET-BUFFERS </item>
- <item> SET-CALLBACK-PROCEDURE </item>
- <item> SET-COMMIT </item>
- <item> SET-CONNECT-PROCEDURE </item>
- <item> SET-DYNAMIC </item>
- <item> SET-GREEN-VALUE </item>
- <item> SET-INPUT-SOURCE </item>
- <item> SET-MUST-UNDERSTAND </item>
- <item> SET-NODE </item>
- <item> SET-NUMERIC-FORMAT </item>
- <item> SET-PARAMETER </item>
- <item> SET-READ-RESPONSE-PROCEDURE </item>
- <item> SET-RED-VALUE </item>
- <item> SET-REPOSITIONED-ROW </item>
- <item> SET-RGB-VALUE </item>
- <item> SET-ROLLBACK </item>
- <item> SET-SELECTION </item>
- <item> SET-SERIALIZED </item>
- <item> SET-SOCKET-OPTION </item>
- <item> SET-WAIT-STATE </item>
- <item> STOP-PARSING </item>
- <item> SYNCHRONIZE </item>
- <item> TEMP-TABLE-PREPARE </item>
- <item> VALIDATE </item>
- <item> WRITE </item>
-</list>
-
-
- <contexts>
-
- <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
-
- <keyword attribute="Data_Type" context="#stay" String="mytypes"/>
- <keyword attribute="Operators" context="#stay" String="operators"/>
- <keyword attribute="Preprocvar" context="#stay" String="preprocvar"/>
- <keyword attribute="Phrases" context="#stay" String="phrases"/>
- <keyword attribute="Functions" context="#stay" String="functions"/>
- <keyword attribute="Statements" context="#stay" String="statements"/>
- <keyword attribute="Widgets" context="#stay" String="widgets"/>
- <keyword attribute="Handles" context="#stay" String="handles"/>
- <keyword attribute="Properties" context="#stay" String="properties"/>
- <keyword attribute="Attributes" context="#stay" String="attributes"/>
- <keyword attribute="Methods" context="#stay" String="methods"/>
-
- <Int attribute="Integer" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- <DetectChar attribute="String" context="String" char="'"/>
- <Detect2Chars attribute="Comment" context="MultiLineComment" char="/" char1="*" beginRegion="Comment"/>
- <RegExpr attribute="Comment" context="SingleLineComment" String="^[Rr][Ee][Mm]\b"/>
- <DetectChar attribute="Comment" context="Identifier" char="&quot;"/>
- <AnyChar attribute="Symbol" context="#stay" String=":&#38;"/>
- <RegExpr attribute="Symbol" context="#stay" String="^/$"/>
- <DetectChar attribute="String" context="#stay" char="&quot;"/>
- <DetectChar attribute="String" context="#stay" char="'"/>
- <DetectChar attribute="Symbol" context="#stay" char="{"/>
- <DetectChar attribute="Symbol" context="#stay" char="}"/>
-
- </context>
-
- <context name="String" attribute="String" lineEndContext="#stay">
-
- <LineContinue attribute="String" context="#pop"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="Symbol" context="#stay" char="&#38;"/>
- <DetectChar attribute="String" context="#pop" char="'"/>
-
- </context>
- <context name="SingleLineComment" attribute="Comment" lineEndContext="#pop"/>
- <context name="MultiLineComment" attribute="Comment" lineEndContext="#stay">
- <LineContinue attribute="Comment" context="#pop"/>
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- </context>
- <context name="Identifier" attribute="Identifier" lineEndContext="#pop">
- <DetectChar attribute="Identifier" context="#pop" char="&quot;"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Phrases" defStyleNum="dsKeyword" />
- <itemData name="Statements" defStyleNum="dsKeyword"/>
- <itemData name="Widgets" defStyleNum="dsKeyword"/>
- <itemData name="Handles" defStyleNum="dsDecVal"/>
- <itemData name="Properties" defStyleNum="dsOthers"/>
- <itemData name="Attributes" defStyleNum="dsDataType"/>
- <itemData name="Methods" defStyleNum="dsOthers"/>
- <itemData name="Functions" defStyleNum="dsKeyword"/>
-
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Integer" defStyleNum="dsBaseN"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Identifier" defStyleNum="dsOthers"/>
- <itemData name="Symbol" defStyleNum="dsChar"/>
- <itemData name="Data_Type" defStyleNum="dsDataType"/>
- <itemData name="Preprocvar" defStyleNum="dsChar"/>
- <itemData name="Operators" defStyleNum="dsString"/>
- </itemDatas>
-
-</highlighting>
-
- <general>
- <comments>
- <comment name="singleLine" start="/*" end="*/"/>
- <comment name="multiLine" start="/*" end="*/"/>
- </comments>
-
- <keywords casesensitive="1" weakDeliminator="-" />
- <mytypes casesensitive="1" weakDeliminator="-" />
- <phrases casesensitive="1" weakDeliminator="-" />
- <functions casesensitive="1" weakDeliminator="-" />
- <statements casesensitive="1" weakDeliminator="-" />
- <widgets casesensitive="1" weakDeliminator="-" />
- <handles casesensitive="1" weakDeliminator="-" />
- <properties casesensitive="1" weakDeliminator="-" />
- <attributes casesensitive="1" weakDeliminator="-" />
- <methods casesensitive="1" weakDeliminator="-" />
- <preprocvar casesensitive="1" weakDeliminator="-" />
-
- </general>
-
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Prolog" version="1.04" kateversion="2.1" section="Sources" extensions="*.prolog" mimetype="text/x-prolog">
- <highlighting>
- <list name="keywordl">
- <item> abstract </item>
- <item> align </item>
- <item> as </item>
- <item> and </item>
- <item> class </item>
- <item> clauses </item>
- <item> constants </item>
- <item> database </item>
- <item> determ </item>
- <item> domains </item>
- <item> elsedef </item>
- <item> endclass </item>
- <item> enddef </item>
- <item> erroneous </item>
- <item> facts </item>
- <item> failure </item>
- <item> global </item>
- <item> goal </item>
- <item> if </item>
- <item> ifdef </item>
- <item> ifndef </item>
- <item> implement </item>
- <item> include </item>
- <item> language </item>
- <item> multi </item>
- <item> nocopy </item>
- <item> nondeterm </item>
- <item> object </item>
- <item> or </item>
- <item> procedure </item>
- <item> protected </item>
- <item> predicates </item>
- <item> reference </item>
- <item> single </item>
- <item> static </item>
- <item> struct </item>
- <item> this </item>
- </list>
-
- <list name="keywordu">
- <item> ABSTRACT </item>
- <item> ALIGN </item>
- <item> AS </item>
- <item> AND </item>
- <item> CLASS </item>
- <item> CLAUSES </item>
- <item> CONSTANTS </item>
- <item> DATABASE </item>
- <item> DETERM </item>
- <item> DOMAINS </item>
- <item> ELSEDEF </item>
- <item> ENDCLASS </item>
- <item> ENDDEF </item>
- <item> ERRONEOUS </item>
- <item> FACTS </item>
- <item> FAILURE </item>
- <item> GLOBAL </item>
- <item> GOAL </item>
- <item> IF </item>
- <item> IFDEF </item>
- <item> IFNDEF </item>
- <item> IMPLEMENT </item>
- <item> INCLUDE </item>
- <item> LANGUAGE </item>
- <item> MULTI </item>
- <item> NOCOPY </item>
- <item> NONDETERM </item>
- <item> OBJECT </item>
- <item> OR </item>
- <item> PROCEDURE </item>
- <item> PROTECTED </item>
- <item> PREDICATES </item>
- <item> REFERENCE </item>
- <item> SINGLE </item>
- <item> STATIC </item>
- <item> STRUCT </item>
- <item> THIS </item>
- </list>
-
-
- <list name="special">
- <item> assert </item>
- <item> asserta </item>
- <item> assertz </item>
- <item> bound </item>
- <item> chain_inserta </item>
- <item> chain_insertafter </item>
- <item> chain_insertz </item>
- <item> chain_terms </item>
- <item> consult </item>
- <item> db_btrees </item>
- <item> db_chains </item>
- <item> fail </item>
- <item> findall </item>
- <item> format </item>
- <item> free </item>
- <item> msgrecv </item>
- <item> msgsend </item>
- <item> nl </item>
- <item> not </item>
- <item> readterm </item>
- <item> ref_term </item>
- <item> retract </item>
- <item> retractall </item>
- <item> save </item>
- <item> term_bin </item>
- <item> term_replace </item>
- <item> term_str </item>
- <item> trap </item>
- <item> write </item>
- <item> writef </item>
- </list>
-
- <list name="compiler">
- <item> bgidriver </item>
- <item> bgifont </item>
- <item> check_determ </item>
- <item> code </item>
- <item> config </item>
- <item> diagnostics </item>
- <item> error </item>
- <item> errorlevel </item>
- <item> heap </item>
- <item> gstacksize </item>
- <item> nobreak </item>
- <item> nowarnings </item>
- <item> printermenu </item>
- <item> project </item>
- </list>
-
- <list name="arith">
- <item> mod </item>
- <item> div </item>
- <item> abs </item>
- <item> exp </item>
- <item> ln </item>
- <item> log </item>
- <item> sqrt </item>
- <item> round </item>
- <item> trunc </item>
- <item> val </item>
- <item> cos </item>
- <item> sin </item>
- <item> tan </item>
- <item> arctan </item>
- <item> random </item>
- <item> randominit </item>
- </list>
-
- <list name="basetype">
- <item> char </item>
- <item> real </item>
- <item> string </item>
- <item> symbol </item>
- <item> byte </item>
- <item> sbyte </item>
- <item> short </item>
- <item> ushort </item>
- <item> word </item>
- <item> integer </item>
- <item> unsigned </item>
- <item> dword </item>
- <item> long </item>
- <item> ulong </item>
- <item> binary </item>
- <item> ref </item>
- </list>
-
- <list name="keywords">
- <item> true </item>
- <item> false </item>
- </list>
-
- <contexts>
- <context name="normal" attribute="Symbol" lineEndContext="#stay">
- <keyword attribute="Keyword" context="#stay" String="keywordl"/>
- <keyword attribute="Keyword" context="#stay" String="keywordu"/>
- <keyword attribute="Arithmetic" context="#stay" String="arith"/>
- <keyword attribute="Keyword" context="#stay" String="compiler"/>
- <keyword attribute="Keyword" context="#stay" String="special"/>
- <keyword attribute="Data Type" context="#stay" String="basetype"/>
- <RegExpr String = "[A-Z_][A-Za-z0-9_]*" attribute = "Variable" context="#stay"/>
- <RegExpr String = "[a-z][A-Za-z0-9_]*" attribute = "Identifier" context="#stay"/>
- <DetectChar attribute="Comment" context="comment" char="%"/>
- <Detect2Chars attribute="Comment" context="comment region" char="/" char1="*"/>
- <Int attribute="Integer" context="#stay" />
- <DetectChar attribute="String" context="string" char="&quot;" />
- <DetectChar attribute="String" context="string2" char="'" />
- <AnyChar attribute="Symbol" context="#stay" String="~!^*()-+=[]|\:;,./?&amp;&lt;&gt;" />
- </context>
- <context name="comment" attribute="Comment" lineEndContext="#pop" />
- <context name="string" attribute="String" lineEndContext="#stay" >
- <DetectChar attribute="String" context="#pop" char="&quot;" />
- </context>
- <context name="string2" attribute="String" lineEndContext="#stay">
- <DetectChar attribute="String" context="#pop" char="'" />
- </context>
- <context name="comment region" attribute="Comment" lineEndContext="#stay">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="Data Type" defStyleNum="dsDataType" />
- <itemData name="Comment" defStyleNum="dsComment" />
- <itemData name="Integer" defStyleNum="dsDecVal" />
- <itemData name="Symbol" defStyleNum="dsNormal" />
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Identifier" defStyleNum="dsNormal"/>
- <itemData name="Variable" defStyleNum="dsOthers"/>
- <itemData name="Arithmetic" defStyleNum="dsKeyword" />
-
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="1" />
- <comments>
- <comment name="singleLine" start="%" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
-
- </general>
-</language>
-
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language>
-<!-- Python syntax highlightning v0.9 by Per Wigren -->
-<language name="Python" version="1.21" kateversion="2.1" section="Scripts"
- extensions="*.py;*.pyw" mimetype="application/x-python;text/x-python" casesensitive="1"
- author="Per Wigren" license="">
- <highlighting>
- <list name="prep">
- <item> import </item>
- <item> from </item>
- <item> as </item>
- </list>
-
- <list name="statements">
- <item> and </item>
- <item> assert </item>
- <item> break </item>
- <item> class </item>
- <item> continue </item>
- <item> def </item>
- <item> del </item>
- <item> elif </item>
- <item> else </item>
- <item> except </item>
- <item> exec </item>
- <item> finally </item>
- <item> for </item>
- <item> global </item>
- <item> if </item>
- <item> in </item>
- <item> is </item>
- <item> lambda </item>
- <item> not </item>
- <item> or </item>
- <item> pass </item>
- <item> print </item>
- <item> raise </item>
- <item> return </item>
- <item> try </item>
- <item> while </item>
- <item> yield </item>
- </list>
-
- <list name="builtinfuncs">
- <item> abs </item>
- <item> apply </item>
- <item> buffer </item>
- <item> callable </item>
- <item> chr </item>
- <item> cmp </item>
- <item> coerce </item>
- <item> compile </item>
- <item> complex </item>
- <item> copyright </item>
- <item> credits </item>
- <item> delattr </item>
- <item> dir </item>
- <item> divmod </item>
- <item> eval </item>
- <item> execfile </item>
- <item> exit </item>
- <item> filter </item>
- <item> float </item>
- <item> getattr </item>
- <item> globals </item>
- <item> hasattr </item>
- <item> hash </item>
- <item> hex </item>
- <item> id </item>
- <item> input </item>
- <item> int </item>
- <item> intern </item>
- <item> isinstance </item>
- <item> issubclass </item>
- <item> iter </item>
- <item> len </item>
- <item> license </item>
- <item> list </item>
- <item> locals </item>
- <item> long </item>
- <item> map </item>
- <item> max </item>
- <item> min </item>
- <item> oct </item>
- <item> open </item>
- <item> ord </item>
- <item> pow </item>
- <item> quit </item>
- <item> range </item>
- <item> raw_input </item>
- <item> reduce </item>
- <item> reload </item>
- <item> repr </item>
- <item> round </item>
- <item> setattr </item>
- <item> slice </item>
- <item> str </item>
- <item> tuple </item>
- <item> type </item>
- <item> unichr </item>
- <item> unicode </item>
- <item> vars </item>
- <item> xrange </item>
- <item> zip </item>
- </list>
-
- <list name="specialvars">
- <item> None </item>
- <item> self </item>
- </list>
-
- <contexts>
- <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
- <keyword attribute="Preprocessor" String="prep" context="#stay"/>
- <keyword attribute="Keyword" String="statements" context="#stay"/>
- <keyword attribute="Builtin Function" String="builtinfuncs" context="#stay"/>
- <keyword attribute="Special Variable" String="specialvars" context="#stay"/>
- <RegExpr attribute="Normal" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/>
-
- <RegExpr attribute="Complex" String=" ((([0-9]*\.[0-9]+|[0-9]+\.)|([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.))[eE](\+|-)?[0-9]+)|[0-9]+)[jJ]" context="#stay"/>
- <RegExpr attribute="Float" String="([0-9]+\.[0-9]*|\.[0-9]+)([eE][0-9]+)?" context="#stay"/>
- <RegExpr attribute="Int" String="([1-9][0-9]*([eE][0-9]+)?|0)" context="#stay"/>
- <RegExpr attribute="Long" String="[1-9][0-9]*([eE][0-9.]+)?[Ll]" context="#stay"/>
- <RegExpr attribute="Hex" String="0[Xx][0-9a-fA-F]+" context="#stay"/>
- <RegExpr attribute="Octal" String="0[1-9][0-9]*" context="#stay"/>
-
- <RegExpr attribute="Raw String" String="[rR]'" context="Raw A-string"/>
- <RegExpr attribute="Raw String" String="[rR]&quot;" context="Raw Q-string"/>
-
- <RegExpr attribute="Comment" String="#.*$" context="#stay"/>
- <RegExpr attribute="Comment" String="^\s*'''" context="Tripple A-comment"/>
- <RegExpr attribute="Comment" String="^\s*&quot;&quot;&quot;" context="Tripple Q-comment"/>
-
- <StringDetect attribute="String" String="'''" context="Tripple A-string"/>
- <StringDetect attribute="String" String="&quot;&quot;&quot;" context="Tripple Q-string"/>
- <DetectChar attribute="String" char="'" context="Single A-string"/>
- <DetectChar attribute="String" char="&quot;" context="Single Q-string"/>
-
- <RegExpr attribute="Operator" String="[+*/\(\)%\|\[\]\{\}:=;\!&lt;&gt;!^&amp;~-]" context="#stay"/>
-
- </context>
-
- <context name="Tripple A-comment" attribute="Comment" lineEndContext="#stay">
- <HlCChar attribute="Comment" context="#stay"/>
- <RegExpr attribute="Comment" String="'''" context="#pop"/>
- </context>
-
- <context name="Tripple Q-comment" attribute="Comment" lineEndContext="#stay">
- <HlCChar attribute="Comment" context="#stay"/>
- <RegExpr attribute="Comment" String="&quot;&quot;&quot;" context="#pop"/>
- </context>
-
- <context name="Tripple A-string" attribute="String" lineEndContext="#stay">
- <HlCChar attribute="String" context="#stay"/>
- <RegExpr attribute="Operator" String="%[a-zA-Z]" context="#stay"/>
- <RegExpr attribute="String" String="'''" context="#pop"/>
- </context>
-
- <context name="Tripple Q-string" attribute="String" lineEndContext="#stay">
- <HlCStringChar attribute="String" context="#stay"/>
- <RegExpr attribute="Operator" String="%[a-zA-Z]" context="#stay"/>
- <RegExpr attribute="String" String="&quot;&quot;&quot;" context="#pop"/>
- </context>
-
- <context name="Single A-comment" attribute="Comment" lineEndContext="#stay">
- <HlCStringChar attribute="Comment" context="#stay"/>
- <DetectChar attribute="Comment" char="'" context="#pop"/>
- </context>
-
- <context name="Single Q-comment" attribute="Comment" lineEndContext="#stay">
- <HlCStringChar attribute="Comment" context="#stay"/>
- <DetectChar attribute="Comment" char="&quot;" context="#pop"/>
- </context>
-
- <context name="Single A-string" attribute="String" lineEndContext="#stay">
- <HlCStringChar attribute="String" context="#stay"/>
- <RegExpr attribute="Operator" String="%[a-zA-Z]" context="#stay"/>
- <DetectChar attribute="String" char="'" context="#pop"/>
- </context>
-
- <context name="Single Q-string" attribute="String" lineEndContext="#stay">
- <HlCStringChar attribute="String" context="#stay"/>
- <RegExpr attribute="Operator" String="%[a-zA-Z]" context="#stay"/>
- <DetectChar attribute="String" char="&quot;" context="#pop"/>
- </context>
-
- <context name="Raw A-string" attribute="Raw String" lineEndContext="#stay">
- <HlCStringChar attribute="Raw String" context="#stay"/>
- <DetectChar attribute="Raw String" char="'" context="#pop"/>
- </context>
-
- <context name="Raw Q-string" attribute="Raw String" lineEndContext="#stay">
- <HlCStringChar attribute="Raw String" context="#stay"/>
- <DetectChar attribute="Raw String" char="&quot;" context="#pop"/>
- </context>
-
-
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Operator" defStyleNum="dsChar"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Builtin Function" defStyleNum="dsDataType"/>
- <itemData name="Special Variable" defStyleNum="dsOthers"/>
- <itemData name="Preprocessor" defStyleNum="dsChar"/>
- <itemData name="Long" defStyleNum="dsOthers"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Int" defStyleNum="dsDecVal"/>
- <itemData name="Hex" defStyleNum="dsOthers"/>
- <itemData name="Octal" defStyleNum="dsOthers"/>
- <itemData name="Complex" defStyleNum="dsOthers"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Raw String" defStyleNum="dsString"/>
- </itemDatas>
- </highlighting>
- <general>
- <folding indentationsensitive="1" />
- <comments>
- <comment name="singleLine" start="#" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
- <!-- Kate 2.0 (KDE 3.0) highlighting module for R
- version 0.2: (c) 2002 E.L. Willighagen, GPL v2 license
-
- info: http://www-sigma.sci.kun.nl/Persoonlijk/egonw/r-kate/
- Kate: http://www.kde.org/kate
- R : http://www.r-project.org/
- -->
-<language version="1.02" kateversion="2.1" name="R Script" section="Scripts"
- extensions="*.R" mimetype=""
- author="E.L. Willighagen" license="GPL">
- <highlighting>
- <list name="keywords">
- <item> for </item>
- <item> in </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="ctx0">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <DetectChar attribute="String" context="ctx2" char="&quot;"/>
- <RegExpr attribute="Keyword" context="ctx1" String="[a-zA-Z_]+\("/>
- <DetectChar attribute="Comment" context="ctx3" char="#"/>
- </context>
-
- <context attribute="Normal Text" lineEndContext="#stay" name="ctx1">
- <LineContinue attribute="Normal Text" context="#stay"/>
- <DetectChar attribute="Keyword" context="#pop" char=")"/>
- <DetectChar attribute="String" context="ctx2" char="&quot;"/>
- <RegExpr attribute="Identifier" context="#stay" String="[a-zA-Z_]+="/>
- <RegExpr attribute="Keyword" context="#stay" String="[a-zA-Z_]+\("/>
- </context>
-
- <context attribute="String" lineEndContext="#stay" name="ctx2">
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
-
- <context attribute="Comment" lineEndContext="ctx0" name="ctx3"/>
-
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Identifier" defStyleNum="dsOthers"/>
- <itemData name="Types" defStyleNum="dsDataType"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="#" end=""/>
- </comments>
- <keywords casesensitive="0" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="REXX" version="1.0" kateversion="2.1" section="Sources" extensions="*.rex" mimetype="">
- <highlighting>
- <list name="instructions">
- <item> arg </item>
- <item> drop </item>
- <item> else </item>
- <item> end </item>
- <item> exit </item>
- <item> forever </item>
- <item> if </item>
- <item> interpret </item>
- <item> iterate </item>
- <item> leave </item>
- <item> nop </item>
- <item> options </item>
- <item> otherwise </item>
- <item> pull </item>
- <item> push </item>
- <item> queue </item>
- <item> return </item>
- <item> say </item>
- <item> select </item>
- <item> syntax </item>
- <item> then </item>
- </list>
- <list name="builtin">
- <item> abbrev </item>
- <item> abs </item>
- <item> address </item>
- <item> bitand </item>
- <item> bitor </item>
- <item> bitxor </item>
- <item> b2x </item>
- <item> center </item>
- <item> charin </item>
- <item> charout </item>
- <item> chars </item>
- <item> c2d </item>
- <item> c2x </item>
- <item> compare </item>
- <item> condition </item>
- <item> copies </item>
- <item> datatype </item>
- <item> date </item>
- <item> delstr </item>
- <item> delword </item>
- <item> digits </item>
- <item> d2c </item>
- <item> d2x </item>
- <item> errortext </item>
- <item> form </item>
- <item> format </item>
- <item> fuzz </item>
- <item> insert </item>
- <item> lastpos </item>
- <item> left </item>
- <item> linein </item>
- <item> lineout </item>
- <item> lines </item>
- <item> max </item>
- <item> min </item>
- <item> overlay </item>
- <item> pos </item>
- <item> queued </item>
- <item> random </item>
- <item> reverse </item>
- <item> right </item>
- <item> sign </item>
- <item> sourceline </item>
- <item> space </item>
- <item> stream </item>
- <item> strip </item>
- <item> substr </item>
- <item> subword </item>
- <item> symbol </item>
- <item> time </item>
- <item> trace </item>
- <item> translate </item>
- <item> trunc </item>
- <item> value </item>
- <item> verify </item>
- <item> word </item>
- <item> wordindex </item>
- <item> wordlength </item>
- <item> wordpos </item>
- <item> words </item>
- <item> xrange </item>
- <item> x2b </item>
- <item> x2c </item>
- <item> x2d </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Instructions" context="#stay" String="instructions" />
- <keyword attribute="Built In" context="#stay" String="builtin" />
- <RegExpr attribute="Instructions" context="#stay" insensitive="true" String="\bsignal([\s]*(on|off)[\s]*(error|failure|halt|notready|novalue|syntax|lostdigits))*"/>
- <RegExpr attribute="Instructions" context="#stay" insensitive="true" String="\bcall([\s]*(on|off)[\s]*(error|failure|halt|notready))*"/>
- <RegExpr attribute="Instructions" context="#stay" insensitive="true" String="\b(trace|address)\s*[_\w\d]"/>
- <RegExpr attribute="Instructions" context="#stay" insensitive="true" String="\bprocedure([\s]*expose)?"/>
- <RegExpr attribute="Instructions" context="#stay" insensitive="true" String="\bdo([\s]*forever)?"/>
- <DetectChar attribute="String" context="String" char="&apos;"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="*" beginRegion="Comment"/>
- <AnyChar attribute="Symbol" context="#stay" String=":!%&amp;()+,-/.*&lt;=&gt;?[]{|}~^&#59;"/>
- <RegExpr attribute="Function" context="#stay" String="\b[_\w][_\w\d]*(?=[\s]*[(:])" />
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&apos;"/>
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar 1">
- <RegExpr attribute="Decimal" context="#stay" String="(FIXME|TODO)" />
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Instructions" defStyleNum="dsKeyword"/>
- <itemData name="Built In" defStyleNum="dsNormal" color="#000090"/>
- <itemData name="Function" defStyleNum="dsNormal" color="#26537B"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="0" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="RPM Spec" version="1.03" kateversion="2.1" section="Other" extensions="*.spec" mimetype="">
- <highlighting>
- <list name="keywords">
- <item> Name </item>
- <item> Summary </item>
- <item> Version </item>
- <item> Release </item>
- <item> Source </item>
- <item> Group </item>
- <item> BuildRoot </item>
- <item> Copyright </item>
- <item> Packager </item>
- <item> Url </item>
- <item> URL </item>
- <item> Prefix </item>
- <item> Provides </item>
- <item> Requires </item>
- <item> BuildRequires </item>
- <item> Serial </item>
- <item> Vendor </item>
- <item> License </item>
- </list>
- <list name="types">
- <item> GPL </item>
- <item> LGPL </item>
- <item> Artistic </item>
- </list>
- <contexts>
-
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data" context="#stay" String="types"/>
- <RegExpr attribute="Red" context="#stay" String="%[a-zA-Z0-9_]*" />
- <DetectChar attribute="Comment" context="Comment" char="#" />
- <RegExpr attribute="Keyword" context="Some Context" String="\{[a-zA-Z0-9_]*" />
- <RegExpr attribute="Blue" context="Some Context2" String="&lt;\s*[a-zA-Z0-9_@\.]*" />
- <RegExpr attribute="Data" context="#stay" String="\$[a-zA-Z0-9_]*" />
- <RegExpr attribute="Keyword" context="#stay" String="(Source|Patch)[0-9]*" />
- <RegExpr attribute="Keyword" context="#stay" String="^\*.*" /> <!-- ChangeLog -->
- <Int attribute="Blue" context="#stay" />
- </context>
-
- <context attribute="Comment" lineEndContext="#pop" name="Comment"/>
-
- <context attribute="Keyword" lineEndContext="#pop" name="Some Context">
- <DetectChar attribute="Keyword" char="}" context="#pop"/>
- </context>
-
- <context attribute="Blue" lineEndContext="#pop" name="Some Context2">
- <DetectChar attribute="Blue" char="&gt;" context="#pop"/>
- </context>
-
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Red" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Blue" defStyleNum="dsDecVal"/>
- <itemData name="Data" defStyleNum="dsDataType"/>
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?> <!-- KATE Syntax Highlighting for RSI IDL -->
-<!DOCTYPE language SYSTEM "language.dtd"><!-- Created by Markus Fraenz,fraenz@linmpi.mpg.de Aug 2002 -->
-<language name="RSI_IDL" version="1.04" kateversion="2.1" section="Sources"
- extensions="*.pro" mimetype="text/x-rsiidl-src"
- author="Markus Fraenz (fraenz@linmpi.mpg.de)" license="">
- <highlighting>
- <list name="reserved words">
- <item> For </item>
- <item> Do </item>
- <item> Endfor </item>
- <item> Repeat </item>
- <item> Endrep </item>
- <item> While </item>
- <item> Endwhile </item>
- <item> Until </item>
- <item> Case </item>
- <item> Endcase </item>
- <item> If </item>
- <item> Endif </item>
- <item> Else </item>
- <item> Endelse </item>
- <item> Then </item>
- <item> Begin </item>
- <item> End </item>
- <item> Function </item>
- <item> Goto </item>
- <item> Pro </item>
- <item> Eq </item>
- <item> Ge </item>
- <item> Gt </item>
- <item> Le </item>
- <item> Lt </item>
- <item> Ne </item>
- <item> Mod </item>
- <item> Or </item>
- <item> Xor </item>
- <item> Not </item>
- <item> And </item>
- <item> Then </item>
- <item> Return </item>
- <item> Common </item>
- <item> Of </item>
- <item> On_ioerror </item>
- </list>
- <list name="system variables">
- <item>dpi</item>
- <item>dtor</item>
- <item>map</item>
- <item>pi</item>
- <item>radeg</item>
- <item>values</item>
- <item>err</item>
- <item>error_state</item>
- <item>error</item>
- <item>err_string</item>
- <item>except</item>
- <item>mouse</item>
- <item>msg_prefix</item>
- <item>syserror</item>
- <item>syserr_string</item>
- <item>warn</item>
- <item>dir</item>
- <item>dlm_path</item>
- <item>edit_input</item>
- <item>help_path</item>
- <item>journal</item>
- <item>more</item>
- <item>path</item>
- <item>prompt</item>
- <item>quiet</item>
- <item>version</item>
- <item>c</item>
- <item>d</item>
- <item>order</item>
- <item>p</item>
- <item>x</item>
- <item>y</item>
- <item>z</item>
- <item>stime</item>
- </list>
- <list name="types"><!-- IDL5 Data types and variable creation -->
- <item>Fix </item>
- <item>Long </item>
- <item>Long64 </item>
- <item>uint </item>
- <item>Byte </item>
- <item>Float </item>
- <item>Double </item>
- <item>complex </item>
- <item>dcomplex </item>
- <item>complexarr </item>
- <item>dcomplexarr </item>
- <item>String </item>
- <item>Intarr </item>
- <item>lonarr </item>
- <item>lon64arr </item>
- <item>uintarr </item>
- <item>ulong </item>
- <item>ulonarr </item>
- <item>ulon64arr </item>
- <item>Bytarr </item>
- <item>Bytscl </item>
- <item>Fltarr </item>
- <item>Dblarr </item>
- <item>Strarr </item>
- <item>Objarr </item>
- <item>Indgen </item>
- <item>Findgen </item>
- <item>Dindgen </item>
- <item>Dcindgen </item>
- <item>cindgen </item>
- <item>lindgen </item>
- <item>bindgen </item>
- <item>sindgen </item>
- <item>uindgen </item>
- <item>ul64indgen </item>
- <item>l64indgen </item>
- <item>ulindgen </item>
- <item>Replicate </item>
- <item>Ptrarr </item>
- </list>
- <list name="commands"><!-- IDL5.3 build in routines, excluding lib functions and io functions -->
- <item>ABS </item>
- <item>ACOS </item>
- <item>ADAPT_HIST_EQUAL </item>
- <item>ALOG </item>
- <item>ALOG10 </item>
- <item>ARG_PRESENT </item>
- <item>ASIN </item>
- <item>ASSOC </item>
- <item>ATAN </item>
- <item>AXIS </item>
- <item>BESELI </item>
- <item>BESELJ </item>
- <item>BESELY </item>
- <item>BLAS_AXPY </item>
- <item>BREAKPOINT </item>
- <item>BROYDEN </item>
- <item>BYTEORDER </item>
- <item>CALL_EXTERNAL </item>
- <item>CALL_FUNCTION </item>
- <item>CALL_METHOD </item>
- <item>CALL_PROCEDURE </item>
- <item>CATCH </item>
- <item>CEIL </item>
- <item>CHECK_MATH </item>
- <item>CHOLDC </item>
- <item>CHOLSOL </item>
- <item>COLOR_CONVERT </item>
- <item>COLOR_QUAN </item>
- <item>COMPILE_OPT </item>
- <item>COMPUTE_MESH_NORMALS </item>
- <item>CONJ </item>
- <item>CONSTRAINED_MIN </item>
- <item>CONTOUR </item>
- <item>CONVERT_COORD </item>
- <item>CONVOL </item>
- <item>CORRELATE </item>
- <item>COS </item>
- <item>COSH </item>
- <item>CREATE_STRUCT </item>
- <item>CURSOR </item>
- <item>DEFINE_KEY </item>
- <item>DEFSYSV </item>
- <item>DELVAR </item>
- <item>DEVICE </item>
- <item>DFPMIN </item>
- <item>DIALOG_MESSAGE </item>
- <item>DIALOG_PICKFILE </item>
- <item>DIALOG_PRINTERSETUP </item>
- <item>DIALOG_PRINTJOB </item>
- <item>DILATE </item>
- <item>DLM_LOAD </item>
- <item>DRAW_ROI </item>
- <item>ELMHES </item>
- <item>EMPTY </item>
- <item>ENABLE_SYSRTN </item>
- <item>ERASE </item>
- <item>ERODE </item>
- <item>ERRORF </item>
- <item>EXECUTE </item>
- <item>EXIT </item>
- <item>EXP </item>
- <item>EXPAND_PATH </item>
- <item>EXPINT </item>
- <item>FINDFILE </item>
- <item>FINITE </item>
- <item>FLOOR </item>
- <item>FORMAT_AXIS_VALUES </item>
- <item>FORWARD_FUNCTION </item>
- <item>FSTAT </item>
- <item>FULSTR </item>
- <item>FZ_ROOTS </item>
- <item>GAUSSINT </item>
- <item>GET_KBRD </item>
- <item>GETENV </item>
- <item>GRID_TPS </item>
- <item>GRID3 </item>
- <item>HEAP_GC </item>
- <item>HELP </item>
- <item>HISTOGRAM </item>
- <item>HQR </item>
- <item>IMAGE_STATISTICS </item>
- <item>IMAGINARY </item>
- <item>INTERPOLATE </item>
- <item>INVERT </item>
- <item>ISHFT </item>
- <item>ISOCONTOUR </item>
- <item>ISOSURFACE </item>
- <item>JOURNAL </item>
- <item>KEYWORD_SET </item>
- <item>LABEL_REGION </item>
- <item>LINBCG </item>
- <item>LINKIMAGE </item>
- <item>LMGR </item>
- <item>LNGAMMA </item>
- <item>LNP_TEST </item>
- <item>LOADCT </item>
- <item>LOCALE_GET </item>
- <item>LSODE </item>
- <item>LUDC </item>
- <item>LUMPROVE </item>
- <item>LUSOL </item>
- <item>MACHAR </item>
- <item>MAKE_ARRAY </item>
- <item>MAP_PROJ_INFO </item>
- <item>MAX </item>
- <item>MEDIAN </item>
- <item>MESH_CLIP </item>
- <item>MESH_DECIMATE </item>
- <item>MESH_ISSOLID </item>
- <item>MESH_MERGE </item>
- <item>MESH_NUMTRIANGLES </item>
- <item>MESH_SMOOTH </item>
- <item>MESH_SURFACEAREA </item>
- <item>MESH_VALIDATE </item>
- <item>MESH_VOLUME </item>
- <item>MESSAGE </item>
- <item>MIN </item>
- <item>N_ELEMENTS </item>
- <item>N_PARAMS </item>
- <item>N_TAGS </item>
- <item>NEWTON </item>
- <item>OBJ_CLASS </item>
- <item>OBJ_DESTROY </item>
- <item>OBJ_ISA </item>
- <item>OBJ_NEW </item>
- <item>OBJ_VALID </item>
- <item>ON_ERROR </item>
- <item>OPLOT </item>
- <item>PARTICLE_TRACE </item>
- <item>PLOT </item>
- <item>PLOTS </item>
- <item>POLY_2D </item>
- <item>POLYFILL </item>
- <item>POLYFILLV </item>
- <item>POLYSHADE </item>
- <item>POWELL </item>
- <item>PROFILER </item>
- <item>PTR_FREE </item>
- <item>PTR_NEW </item>
- <item>PTR_VALID </item>
- <item>QROMB </item>
- <item>QROMO </item>
- <item>QSIMP </item>
- <item>RANDOMN </item>
- <item>RANDOMU </item>
- <item>REBIN </item>
- <item>REFORM </item>
- <item>RETALL </item>
- <item>RETURN </item>
- <item>RIEMANN </item>
- <item>RK4 </item>
- <item>ROBERTS </item>
- <item>ROTATE </item>
- <item>ROUND </item>
- <item>SET_PLOT </item>
- <item>SET_SHADING </item>
- <item>SETENV </item>
- <item>SHADE_SURF </item>
- <item>SHADE_VOLUME </item>
- <item>SHIFT </item>
- <item>SIN </item>
- <item>SINH </item>
- <item>SIZE </item>
- <item>SMOOTH </item>
- <item>SOBEL </item>
- <item>SORT </item>
- <item>SPL_INIT </item>
- <item>SPL_INTERP </item>
- <item>SPRSAB </item>
- <item>SPRSAX </item>
- <item>SPRSIN </item>
- <item>SQRT </item>
- <item>STOP </item>
- <item>STRCMP </item>
- <item>STRCOMPRESS </item>
- <item>STREGEX </item>
- <item>STRJOIN </item>
- <item>STRLEN </item>
- <item>STRLOWCASE </item>
- <item>STRMATCH </item>
- <item>STRMESSAGE </item>
- <item>STRMID </item>
- <item>STRPOS </item>
- <item>STRPUT </item>
- <item>STRTRIM </item>
- <item>STRUCT_ASSIGN </item>
- <item>STRUCT_HIDE </item>
- <item>STRUPCASE </item>
- <item>SURFACE </item>
- <item>SVDC </item>
- <item>SVSOL </item>
- <item>SYSTIME </item>
- <item>TAG_NAMES </item>
- <item>TAN </item>
- <item>TANH </item>
- <item>TEMPORARY </item>
- <item>TETRA_CLIP </item>
- <item>TETRA_SURFACE </item>
- <item>TETRA_VOLUME </item>
- <item>THIN </item>
- <item>THREED </item>
- <item>TOTAL </item>
- <item>TRANSPOSE </item>
- <item>TRIANGULATE </item>
- <item>TRIGRID </item>
- <item>TRIQL </item>
- <item>TRIRED </item>
- <item>TRISOL </item>
- <item>TV </item>
- <item>TVCRS </item>
- <item>TVLCT </item>
- <item>TVRD </item>
- <item>TVSCLU </item>
- <item>USERSYM </item>
- <item>VALUE_LOCATE </item>
- <item>VOIGT </item>
- <item>VOXEL_PROJ </item>
- <item>WAIT </item>
- <item>WATERSHED </item>
- <item>WDELETE </item>
- <item>WHERE </item>
- <item>WIDGET_BASE </item>
- <item>WIDGET_BUTTON </item>
- <item>WIDGET_CONTROL </item>
- <item>WIDGET_DRAW </item>
- <item>WIDGET_DROPLIST </item>
- <item>WIDGET_EVENT </item>
- <item>WIDGET_INFO </item>
- <item>WIDGET_LABEL </item>
- <item>WIDGET_LIST </item>
- <item>WIDGET_SLIDER </item>
- <item>WIDGET_TABLE </item>
- <item>WIDGET_TEXT </item>
- <item>WINDOW </item>
- <item>WSET </item>
- <item>WSHOW </item>
- <item>WTN </item>
- <item>XYOUTS </item>
- </list>
- <list name="io commands"><!-- IDL5.3 build in I/O routines -->
- <item>Open </item>
- <item>FLUSH </item>
- <item>IOCTL </item>
- <item>RESTORE </item>
- <item>SAVE </item>
- <item>POINT_LUN </item>
- <item>Openr </item>
- <item>Openw </item>
- <item>Openu </item>
- <item>Close </item>
- <item>Free_lun </item>
- <item>get_lun </item>
- <item>assoc </item>
- <item>catch </item>
- <item>cd </item>
- <item>spawn </item>
- <item>eof </item>
- <item>print </item>
- <item>printf </item>
- <item>prints </item>
- <item>read </item>
- <item>readf </item>
- <item>reads </item>
- <item>writu </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="reserved words"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <keyword attribute="Command" context="#stay" String="commands"/>
- <keyword attribute="IOCommand" context="#stay" String="io commands"/>
- <Float attribute="Octal" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- <RangeDetect attribute="String" context="#stay" char="'" char1="'"/>
- <RangeDetect attribute="String" context="#stay" char="&quot;" char1="&quot;"/>
- <DetectChar attribute="Hex" context="#stay" char="(" />
- <DetectChar attribute="Hex" context="#stay" char=")" />
- <DetectChar attribute="Char" context="#stay" char="[" />
- <DetectChar attribute="Char" context="#stay" char="]" />
- <DetectChar attribute="Float" context="#stay" char="{" />
- <DetectChar attribute="Float" context="#stay" char="}" />
- <DetectChar attribute="Char" context="#stay" char="$" />
- <DetectChar attribute="Char" context="#stay" char="@" />
- <DetectChar attribute="Char" context="#stay" char=":" />
- <DetectChar attribute="Char" context="Comment" char="&#59;"/>
- <DetectChar attribute="Char" context="systemvarcontext" char="!" />
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Comment">
- </context>
- <context attribute="Char" lineEndContext="#pop" name="systemvarcontext">
- <DetectChar attribute="Hex" context="#pop" char="(" />
- <DetectChar attribute="Char" context="#pop" char="." />
- <DetectChar attribute="Hex" context="#pop" char=" " />
- <keyword attribute="Float" context="#pop" String="system variables"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword" color="#1414e4" selColor="#ffd60b" bold="1"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal" color="#000000" selColor="#ffffff"/>
- <itemData name="Octal" defStyleNum="dsDecVal"/>
- <itemData name="Hex" defStyleNum="dsDecVal"/>
- <itemData name="Float" defStyleNum="dsDecVal" color="#000000" selColor="#ffffff"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString" color="#ff0000" selColor="#ff0000"/>
- <itemData name="String Char" defStyleNum="dsChar" color="#ff0000" selColor="#ff0000"/>
- <itemData name="Comment" defStyleNum="dsComment" color="#2b7805" selColor="#945ca4"/>
- <itemData name="Command" defStyleNum="dsBaseN" color="#050505" selColor="#ffffff" bold="1"/>
- <itemData name="IOCommand" defStyleNum="dsDataType" color="#050505" selColor="#ffffff" bold="1"/>
- <itemData name="bracketed" defStyleNum="dsFloat" />
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="&#59;" />
- </comments>
- <keywords casesensitive="0" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Ruby" version="1.04" kateversion="2.1" section="Scripts" extensions="*.rb" mimetype="application/x-ruby">
- <highlighting>
-
- <list name = "keywords">
- <item> BEGIN </item>
- <item> END </item>
- <item> and </item>
- <item> begin </item>
- <item> break </item>
- <item> case </item>
- <item> catch </item>
- <item> defined? </item>
- <item> do </item>
- <item> else </item>
- <item> elsif </item>
- <item> end </item>
- <item> ensure </item>
- <item> for </item>
- <item> if </item>
- <item> in </item>
- <item> include </item>
- <item> next </item>
- <item> not </item>
- <item> or </item>
- <item> private </item>
- <item> protected </item>
- <item> public </item>
- <item> redo </item>
- <item> require </item>
- <item> rescue </item>
- <item> retry </item>
- <item> return </item>
- <item> super </item>
- <item> then </item>
- <item> throw </item>
- <item> unless </item>
- <item> until </item>
- <item> when </item>
- <item> while </item>
- <item> yield </item>
- </list>
-
- <list name = "attribute-definitions">
- <item> attr </item>
- <item> attr_reader </item>
- <item> attr_writer </item>
- <item> attr_accessor </item>
- </list>
-
- <list name = "definitions">
- <item> alias </item>
- <item> module </item>
- <item> class </item>
- <item> def </item>
- <item> undef </item>
- </list>
-
- <list name = "pseudo-varibles">
- <item> self </item>
- <item> nil </item>
- <item> false </item>
- <item> true </item>
- <item> __FILE__ </item>
- <item> __LINE__ </item>
- </list>
-
- <contexts>
- <context name = "Normal" attribute = "Normal Text" lineEndContext="#stay">
- <keyword attribute = "Keyword" String = "keywords" context="#stay"/>
- <keyword attribute = "Attribute Definition" String = "attribute-definitions" context="#stay"/>
- <keyword attribute = "Definition" String = "definitions" context="#stay" />
- <keyword attribute = "Pseudo variable" String = "pseudo-varibles" context="#stay"/>
-
- <RegExpr attribute = "Hex" String = "\s0[xX][0-9a-fA-F]+" context="#stay"/>
- <RegExpr attribute = "Bin" String = "\s0[bB][01]+" context="#stay"/>
- <RegExpr attribute = "Octal" String = "\s0[1-7][0-7]*" context="#stay"/>
- <RegExpr attribute = "Float" String="([1-9][0-9]*)?\.[0-9]*([eE]\-*[1-9][0-9]*(\.[0-9]*)?)?" context="#stay"/>
- <RegExpr attribute = "Dec" String = "\s+\-*[1-9][0-9_]*\s*$" context="#stay"/>
- <HlCChar attribute = "Char" context="#stay"/>
-
- <DetectChar attribute = "Operator" char = "." context="#stay"/>
- <StringDetect attribute = "Operator" String = "&amp;&amp;" context="#stay" insensitive="FALSE"/>
- <StringDetect attribute = "Operator" String = "||" context="#stay" insensitive="FALSE"/>
- <RegExpr attribute = "Operator" String = "\s\?\s" context="#stay"/>
- <RegExpr attribute = "Operator" String = "\s:\s" context="#stay"/>
- <RegExpr attribute = "Operator" String = "&#61;*[&lt;&gt;!^&#37;+*~/-]+&#61;*" context="#stay"/>
-
- <RegExpr attribute = "Symbol" String = ":[^\s]+" context="#stay"/>
- <RegExpr attribute = "Delimiter" String = "/[^\s]+/" context="#stay"/>
-
- <DetectChar attribute = "String" char = "&quot;" context = "Quoted String"/>
- <DetectChar attribute = "String" char= "'" context="Apostrophed String"/>
- <StringDetect attribute="Normal Text" String="?#" context="#stay"/>
-
- <RegExpr attribute = "Comment" String = "#.*$" context="#stay"/>
- <RegExpr attribute = "EmbDoc" String = "=begin.*$" context="Embedded documentation"/>
- <RegExpr attribute = "Delimiter" String = "[\[\]\{\}|]+" context="#stay"/>
-
- <RegExpr attribute = "Global Constant" String = "\s+[A-Z_0-9]+\s+" context="#stay"/>
- <RegExpr attribute = "Global Variable" String = "$[a-zA-Z_0-9]+" context="#stay"/>
- <RegExpr attribute = "Instance Variable" String = "@[a-zA-Z_0-9]+" context="#stay"/>
- <RegExpr attribute = "Class Variable" String = "@@[a-zA-Z_0-9]+" context="#stay"/>
- </context>
-
- <context name = "Main Comment" attribute = "Main Comment" lineEndContext="#pop">
- <RegExpr attribute = "Main Comment" String = "^##$" context = "#pop"/>
- <RegExpr attribute = "Main Comment" String = "^#$" context = "#pop"/>
- </context>
-
- <context name = "Quoted String" attribute = "String" lineEndContext="#pop">
- <RegExpr attribute = "Expression" String = "#{[^}]+}" context = "#pop"/>
- <HlCChar attribute = "Char" context = "#pop"/>
- <DetectChar char = '"' attribute = "String" context = "#pop"/>
- </context>
-
- <context name = "Apostrophed String" attribute = "String" lineEndContext="#pop">
- <RegExpr attribute = "Expression" String = "#{[^}]+}" context = "#pop"/>
- <HlCChar attribute = "Char" context = "#pop"/>
- <DetectChar char = "'" attribute = "String" context = "#pop"/>
- </context>
-
- <context name = "Embedded documentation" attribute = "Comment" lineEndContext="#stay">
- <RegExpr attribute = "Comment" String = "^\s*=end" context="#pop"/>
- </context>
- </contexts>
-
- <itemDatas>
- <itemData name = "Normal Text" defStyleNum ="dsNormal"/>
-
- <itemData name = "Keyword" defStyleNum ="dsKeyword"/>
- <itemData name = "Attribute Definition" defStyleNum ="dsOthers"/>
- <itemData name = "Definition" defStyleNum ="dsKeyword"/>
- <itemData name = "Pseudo variable" defStyleNum ="dsDecVal"/>
-
- <itemData name = "Dec" defStyleNum ="dsDecVal"/>
- <itemData name = "Float" defStyleNum ="dsFloat"/>
- <itemData name = "Char" defStyleNum ="dsChar"/>
- <itemData name = "Octal" defStyleNum ="dsBaseN"/>
- <itemData name = "Hex" defStyleNum ="dsBaseN"/>
- <itemData name = "Bin" defStyleNum ="dsBaseN"/>
-
- <itemData name = "Symbol" defStyleNum ="dsString"/>
- <itemData name = "String" defStyleNum ="dsString"/>
-
- <itemData name = "Main Comment" defStyleNum ="dsComment" />
- <itemData name = "Comment" defStyleNum ="dsComment"/>
- <itemData name = "EmbDoc" defStyleNum ="dsComment"/>
-
- <itemData name = "Delimiter" defStyleNum ="dsChar"/>
- <itemData name = "Global Constant" defStyleNum ="dsDecVal"/>
- <itemData name = "Global Variable" defStyleNum ="dsOthers"/>
- <itemData name = "Instance Variable" defStyleNum ="dsOthers"/>
- <itemData name = "Class Variable" defStyleNum ="dsOthers"/>
- <itemData name = "Expression" defStyleNum ="dsOthers"/>
- <itemData name = "Operator" defStyleNum ="dsChar"/>
-
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="#" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Sather" version="1.02" kateversion="2.1" section="Sources" extensions="*.sa" mimetype="text/x-sather-src" casesensitive="1">
- <highlighting>
- <list name="keywords">
- <item> and </item>
- <item> assert </item>
- <item> attr </item>
- <item> break! </item>
- <item> case </item>
- <item> class </item>
- <item> const </item>
- <item> else </item>
- <item> elsif </item>
- <item> end </item>
- <item> exception </item>
- <item> external </item>
- <item> false </item>
- <item> if </item>
- <item> include </item>
- <item> initial </item>
- <item> is </item>
- <item> ITER </item>
- <item> loop </item>
- <item> new </item>
- <item> or </item>
- <item> post </item>
- <item> pre </item>
- <item> private </item>
- <item> protect </item>
- <item> quit </item>
- <item> raise </item>
- <item> readonly </item>
- <item> result </item>
- <item> return </item>
- <item> ROUT </item>
- <item> SAME </item>
- <item> self </item>
- <item> shared </item>
- <item> then </item>
- <item> true </item>
- <item> typecase </item>
- <item> type </item>
- <item> until! </item>
- <item> value </item>
- <item> void </item>
- <item> when </item>
- <item> while! </item>
- <item> yield </item>
- <item> abstract </item>
- <item> any </item>
- <item> bind </item>
- <item> fork </item>
- <item> guard </item>
- <item> immutable </item>
- <item> inout </item>
- <item> in </item>
- <item> lock </item>
- <item> once </item>
- <item> out </item>
- <item> parloop </item>
- <item> partial </item>
- <item> par </item>
- <item> spread </item>
- <item> stub </item>
- </list>
- <list name="types">
- <item> $OB </item>
- <item> ARRAY </item>
- <item> AREF </item>
- <item> AVAL </item>
- <item> BOOL </item>
- <item> CHAR </item>
- <item> EXT_OB </item>
- <item> FLTDX </item>
- <item> FLTD </item>
- <item> FLTX </item>
- <item> FLTI </item>
- <item> FLT </item>
- <item> INTI </item>
- <item> INT </item>
- <item> $REHASH </item>
- <item> STR </item>
- <item> SYS </item>
- </list>
- <list name="features">
- <item> create </item>
- <item> invariant </item>
- <item> main </item>
- <item> aget </item>
- <item> aset </item>
- <item> div </item>
- <item> is_eq </item>
- <item> is_geq </item>
- <item> is_gt </item>
- <item> is_leq </item>
- <item> is_lt </item>
- <item> is_neq </item>
- <item> minus </item>
- <item> mod </item>
- <item> negate </item>
- <item> not </item>
- <item> plus </item>
- <item> pow </item>
- <item> times </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <keyword attribute="Features" context="#stay" String="features"/>
- <Float attribute="Float" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- <RegExpr attribute="Char" context="#stay" String="'.'"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="Comment" char="-" char1="-"/>
- </context>
- <context attribute="String" lineEndContext="#stay" name="String">
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Comment"/>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Features" defStyleNum="dsOthers" />
- <itemData name="Decimal" defStyleNum="dsDecVal" />
- <itemData name="Float" defStyleNum="dsFloat" />
- <itemData name="Char" defStyleNum="dsChar" />
- <itemData name="String" defStyleNum="dsString" />
- <itemData name="Comment" defStyleNum="dsComment" />
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="--" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!--
- This file is part of KDE's kate project.
-
- copyright : (C) 2004 by Dominik Haumann
- email : dhdev at gmx dot de
-
- last change : 2004-03-15
-
- ***************************************************************************
- * *
- * This file 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. *
- * *
- ***************************************************************************
- NOTE:
- This file defines highlighting rules for both Scheme AND Guile.
- Scheme usually has no block comments. Guile has block comments: #! !#
- I support these block comments: "Good design means good compromises" :)
- Singleline comments are introduced through ';'. In reality EVERY
- scheme/guile developer use ';;'. It is indented in emacs in a special way.
- That's why I set <comment singleLine=";;">.
-
- As a guile guru tole me it would not make sense to highlight all scheme and
- guile procedures (cause then almost everything would be highlighted) I
- removed some to have a rather small but "senseful" list of highlighted words.
--->
-<language version="1.07" kateversion="2.3" name="Scheme" section="Scripts" extensions="*.scm;*.ss;*.scheme;*.guile" mimetype="text/x-scheme" author="Dominik Haumann">
- <highlighting>
- <list name="operators">
- <item> &lt;= </item>
- <item> &lt; </item>
- <item> = </item>
- <item> =&gt; </item>
- <item> &gt;= </item>
- <item> &gt; </item>
- <item> - </item>
- <item> / </item>
- <item> *,* </item>
- <item> *) </item>
- <item> + </item>
- </list>
- <list name="characters">
- <item> #\nul </item>
- <item> #\soh </item>
- <item> #\stx </item>
- <item> #\etx </item>
- <item> #\eot </item>
- <item> #\enq </item>
- <item> #\ack </item>
- <item> #\bel </item>
- <item> #\bs </item>
- <item> #\ht </item>
- <item> #\nl </item>
- <item> #\vt </item>
- <item> #\np </item>
- <item> #\cr </item>
- <item> #\so </item>
- <item> #\si </item>
- <item> #\dle </item>
- <item> #\dc1 </item>
- <item> #\dc2 </item>
- <item> #\dc3 </item>
- <item> #\dc4 </item>
- <item> #\nak </item>
- <item> #\syn </item>
- <item> #\etb </item>
- <item> #\can </item>
- <item> #\em </item>
- <item> #\sub </item>
- <item> #\esc </item>
- <item> #\fs </item>
- <item> #\gs </item>
- <item> #\rs </item>
- <item> #\us </item>
- <item> #\space </item>
- <item> #\sp </item>
- <item> #\newline </item>
- <item> #\nl </item>
- <item> #\tab </item>
- <item> #\ht </item>
- <item> #\backspace </item>
- <item> #\bs </item>
- <item> #\return </item>
- <item> #\cr </item>
- <item> #\page </item>
- <item> #\np </item>
- <item> #\null </item>
- <item> #\nul </item>
- </list>
- <list name="defines">
- <item> define </item>
- <item> define* </item>
- <item> define-accessor </item>
- <item> define-class </item>
- <item> defined? </item>
- <item> define-generic </item>
- <item> define-macro </item>
- <item> define-method </item>
- <item> define-module </item>
- <item> define-private </item>
- <item> define-public </item>
- <item> define*-public </item>
- <item> define-reader-ctor </item>
- <item> define-syntax </item>
- <item> define-syntax-macro </item>
- <item> defmacro </item>
- <item> defmacro* </item>
- <item> defmacro*-public </item>
- </list>
- <list name="keywords">
- <item> abs </item>
- <item> acos </item>
- <item> and </item>
- <item> angle </item>
- <item> append </item>
- <item> applymap </item>
- <item> asin </item>
- <item> assoc </item>
- <item> assq </item>
- <item> assv </item>
- <item> atan </item>
- <item> begin </item>
- <item> boolean? </item>
- <item> break </item>
- <item> caaaar </item>
- <item> caaadr </item>
- <item> caaar </item>
- <item> caadar </item>
- <item> caaddr </item>
- <item> caadr </item>
- <item> caar </item>
- <item> cadaar </item>
- <item> cadadr </item>
- <item> cadar </item>
- <item> caddar </item>
- <item> cadddr </item>
- <item> caddr </item>
- <item> cadr </item>
- <item> call/cc </item>
- <item> call-with-current-continuation </item>
- <item> call-with-input-file </item>
- <item> call-with-output-file </item>
- <item> call-with-values </item>
- <item> car </item>
- <item> case </item>
- <item> catch </item>
- <item> cdaaar </item>
- <item> cdaadr </item>
- <item> cdaar </item>
- <item> cdadar </item>
- <item> cdaddr </item>
- <item> cdadr </item>
- <item> cdar </item>
- <item> cddaar </item>
- <item> cddadr </item>
- <item> cddar </item>
- <item> cdddar </item>
- <item> cddddr </item>
- <item> cdddr </item>
- <item> cddr </item>
- <item> cdr </item>
- <item> ceiling </item>
- <item> char-alphabetic? </item>
- <item> char-ci&gt;=? </item>
- <item> char-ci&gt;? </item>
- <item> char-ci=? </item>
- <item> char-ci&lt;=? </item>
- <item> char-downcase </item>
- <item> char-&gt;integer </item>
- <item> char&gt;=? </item>
- <item> char&gt;? </item>
- <item> char=? </item>
- <item> char? </item>
- <item> char-lower-case? </item>
- <item> char&lt;?c </item>
- <item> char&lt;=? </item>
- <item> char-numeric? </item>
- <item> char-ready? </item>
- <item> char-upcase </item>
- <item> char-upper-case? </item>
- <item> char-whitespace? </item>
- <item> close-input-port </item>
- <item> close-output-port </item>
- <item> complex? </item>
- <item> cond </item>
- <item> cons </item>
- <item> continue </item>
- <item> cos </item>
- <item> current-input-port </item>
- <item> current-output-port </item>
- <item> denominator </item>
- <item> display </item>
- <item> do </item>
- <item> dynamic-wind </item>
- <item> else </item>
- <item> eof-object? </item>
- <item> eq? </item>
- <item> equal? </item>
- <item> eqv? </item>
- <item> eval </item>
- <item> even? </item>
- <item> exact->inexact </item>
- <item> exact? </item>
- <item> exp </item>
- <item> expt </item>
- <item> floor </item>
- <item> force </item>
- <item> for-each </item>
- <item> gcd </item>
- <item> har-ci&lt;? </item>
- <item> if </item>
- <item> imag-part </item>
- <item> inexact-&gt;exact </item>
- <item> inexact? </item>
- <item> input-port? </item>
- <item> integer-&gt;char </item>
- <item> integer? </item>
- <item> interaction-environment </item>
- <item> lambda </item>
- <item> lcm </item>
- <item> length </item>
- <item> let </item>
- <item> let* </item>
- <item> letrec </item>
- <item> letrec-syntax </item>
- <item> let-syntax </item>
- <item> list-&gt;string </item>
- <item> list </item>
- <item> list? </item>
- <item> list-ref </item>
- <item> list-tail </item>
- <item> load </item>
- <item> log </item>
- <item> magnitude </item>
- <item> make-polar </item>
- <item> make-rectangular </item>
- <item> make-string </item>
- <item> make-vector </item>
- <item> max </item>
- <item> member </item>
- <item> memq </item>
- <item> memv </item>
- <item> min </item>
- <item> modulo </item>
- <item> negative? </item>
- <item> newline </item>
- <item> not </item>
- <item> null-environment </item>
- <item> null? </item>
- <item> number? </item>
- <item> number->string </item>
- <item> numerator </item>
- <item> odd? </item>
- <item> open-input-file </item>
- <item> open-output-file </item>
- <item> or </item>
- <item> output-port? </item>
- <item> pair? </item>
- <item> peek-char </item>
- <item> port? </item>
- <item> positive? </item>
- <item> procedure? </item>
- <item> quotient </item>
- <item> rational? </item>
- <item> rationalize </item>
- <item> read-char </item>
- <item> read </item>
- <item> real? </item>
- <item> real-part </item>
- <item> remainder </item>
- <item> reverse </item>
- <item> round </item>
- <item> scheme-report-environment </item>
- <item> set-car! </item>
- <item> set-cdr! </item>
- <item> sin </item>
- <item> sqrt </item>
- <item> string-append </item>
- <item> string-ci&gt;=? </item>
- <item> string-ci&gt;? </item>
- <item> string-ci=? </item>
- <item> string-ci&lt;=? </item>
- <item> string-ci&lt;? </item>
- <item> string-copy </item>
- <item> string-fill! </item>
- <item> string&gt;=? </item>
- <item> string&gt;? </item>
- <item> string-&gt;list </item>
- <item> string-&gt;number </item>
- <item> string-&gt;symbol </item>
- <item> string=? </item>
- <item> string </item>
- <item> string? </item>
- <item> string-length </item>
- <item> string&lt;=? </item>
- <item> string&lt;? </item>
- <item> string-ref </item>
- <item> string-set! </item>
- <item> substring </item>
- <item> symbol-&gt;string </item>
- <item> symbol? </item>
- <item> syntax-rules </item>
- <item> tan </item>
- <item> transcript-off </item>
- <item> transcript-on </item>
- <item> truncate </item>
- <item> values </item>
- <item> vector-fill! </item>
- <item> vector-&gt;listlist->vector </item>
- <item> vector </item>
- <item> vector? </item>
- <item> vector-length </item>
- <item> vector-ref </item>
- <item> vector-set! </item>
- <item> while </item>
- <item> with-input-from-file </item>
- <item> with-output-to-file </item>
- <item> write-char </item>
- <item> write </item>
- <item> zero? </item>
- </list>
- <contexts>
- <context name="Normal" attribute="Normal" lineEndContext="#stay">
- <RegExpr attribute="Region Marker" context="#stay" String=";+\s*BEGIN.*$" beginRegion="region"/>
- <RegExpr attribute="Region Marker" context="#stay" String=";+\s*END.*$" endRegion="region"/>
- <RegExpr attribute="Comment" context="#stay" String=";.*$"/>
- <Detect2Chars attribute="Comment" context="MultiLineComment" char="#" char1="!" beginRegion="region"/>
- <DetectChar attribute="Brackets" context="#stay" char="("/>
- <DetectChar attribute="Brackets" context="#stay" char=")"/>
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Operator" context="#stay" String="operators"/>
- <keyword attribute="Definition" context="function_decl" String="defines"/>
- <keyword attribute="Char" context="#stay" String="characters"/>
- <RegExpr attribute="Char" context="#stay" String="#\\."/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <RegExpr attribute="Char" context="SpecialNumber" String="#[bodxei]"/>
- <RegExpr attribute="Decimal" context="#stay" String="#[tf]"/>
- <Float attribute="Float" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- </context>
- <context name="MultiLineComment" attribute="Comment" lineEndContext="#stay">
- <RegExpr attribute="Comment" context="#pop" String="^!#\s*$" endRegion="region"/>
- </context>
- <context name="SpecialNumber" attribute="Normal" lineEndContext="#pop">
- <Float attribute="Float" context="#pop"/>
- <Int attribute="Decimal" context="#pop"/>
- <HlCOct attribute="BaseN" context="#pop"/>
- <HlCHex attribute="Float" context="#pop"/>
- </context>
- <context name="String" attribute="String" lineEndContext="#stay">
- <keyword attribute="Char" context="#stay" String="characters"/>
- <RegExpr attribute="Char" context="#stay" String="#\\."/>
- <Detect2Chars attribute="Char" context="#stay" char="\" char1="&quot;"/>
- <Detect2Chars attribute="Char" context="#stay" char="\" char1="\"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context name="function_decl" attribute="Function" lineEndContext="#stay">
- <RegExpr attribute="Function" context="#pop" String="\s*[A-Za-z0-9-+\&lt;\&gt;//\*]*\s*" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Definition" defStyleNum="dsKeyword" color="#d22811"/>
- <itemData name="Operator" defStyleNum="dsKeyword" color="#d22811"/>
- <itemData name="Function" defStyleNum="dsFunction"/>
- <itemData name="Data" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="BaseN" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Region Marker" defStyleNum="dsRegionMarker"/>
- <itemData name="Brackets" defStyleNum="dsNormal" color="#0000ff" selColor="#00ff00" bold="1" italic="0"/>
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="1" weakDeliminator="-+*?!&lt;&gt;=/:#\"/>
- <comments>
- <comment name="singleLine" start=";;" />
- <comment name="multiLine" start="#!" end="!#" />
- </comments>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="scilab" version="1.01" kateversion="2.0/2.1" section="Sources" extensions="*.sci;*.sce" mimetype="text/x-sci">
- <highlighting>
- <list name="Structure-keywords">
- <item> do </item>
- <item> else </item>
- <item> for </item>
- <item> if </item>
- <item> elseif </item>
- <item> end </item>
- <item> select </item>
- <item> then </item>
- <item> while </item>
- </list>
- <list name="Control-keywords">
- <item> abort </item>
- <item> break </item>
- <item> quit </item>
- <item> return </item>
- <item> resume </item>
- <item> pause </item>
- </list>
- <list name="Function-keywords">
- <item> function </item>
- <item> endfunction </item>
- </list>
- <list name="Warning-keywords">
- <item> error </item>
- <item> warning </item>
- </list>
- <list name="Constants-keyword">
- <item> %F </item>
- <item> %f </item>
- <item> %T </item>
- <item> %t </item>
- <item> %e </item>
- <item> %pi </item>
- <item> %inf </item>
- <item> %i </item>
- <item> %z </item>
- <item> %io </item>
- <item> %s </item>
- <item> %nan </item>
- <item> $ </item>
- <item> %eps </item>
- <item> MSDOS </item>
- </list>
- <list name="functions">
- <item> zpell </item>
- <item> zpch2 </item>
- <item> zpch1 </item>
- <item> zpbutt </item>
- <item> zgrid </item>
- <item> zeros </item>
- <item> zeropen </item>
- <item> ZCROSS_f </item>
- <item> yulewalk </item>
- <item> xtitle </item>
- <item> xtape </item>
- <item> xstringl </item>
- <item> xstringb </item>
- <item> xstring </item>
- <item> xsetm </item>
- <item> xsetech </item>
- <item> xset </item>
- <item> xselect </item>
- <item> xsegs </item>
- <item> xsave </item>
- <item> xs2fig </item>
- <item> xrpoly </item>
- <item> xrects </item>
- <item> xrect </item>
- <item> xpolys </item>
- <item> xpoly </item>
- <item> xpause </item>
- <item> xnumb </item>
- <item> xname </item>
- <item> x_message_modeless </item>
- <item> x_message </item>
- <item> x_mdialog </item>
- <item> x_matrix </item>
- <item> xload </item>
- <item> xlfont </item>
- <item> xinit </item>
- <item> xinfo </item>
- <item> xgrid </item>
- <item> xgraduate </item>
- <item> xgetmouse </item>
- <item> xgetfile </item>
- <item> xgetech </item>
- <item> xget </item>
- <item> xfrect </item>
- <item> xfpolys </item>
- <item> xfpoly </item>
- <item> xfarcs </item>
- <item> xfarc </item>
- <item> xend </item>
- <item> x_dialog </item>
- <item> xdel </item>
- <item> xclip </item>
- <item> xclick </item>
- <item> xclear </item>
- <item> xclea </item>
- <item> x_choose </item>
- <item> x_choices </item>
- <item> xchange </item>
- <item> xbasr </item>
- <item> xbasimp </item>
- <item> xbasc </item>
- <item> xaxis </item>
- <item> xarrows </item>
- <item> xarcs </item>
- <item> xarc </item>
- <item> WRITEC_f </item>
- <item> write4b </item>
- <item> write </item>
- <item> writb </item>
- <item> winsid </item>
- <item> window </item>
- <item> wigner </item>
- <item> wiener </item>
- <item> whos </item>
- <item> who </item>
- <item> whereis </item>
- <item> whereami </item>
- <item> where </item>
- <item> what </item>
- <item> wfir </item>
- <item> WFILE_f </item>
- <item> wavwrite </item>
- <item> wavread </item>
- <item> warning </item>
- <item> WaitMsg </item>
- <item> varn </item>
- <item> varargout </item>
- <item> varargin </item>
- <item> user </item>
- <item> unsetmenu </item>
- <item> unobs </item>
- <item> unix_x </item>
- <item> unix_w </item>
- <item> unix_s </item>
- <item> unix_g </item>
- <item> unix </item>
- <item> unique </item>
- <item> union </item>
- <item> ulink </item>
- <item> ui_observer </item>
- <item> uint8 </item>
- <item> uint32 </item>
- <item> uint16 </item>
- <item> uimenu </item>
- <item> uicontrol </item>
- <item> typeof </item>
- <item> typename </item>
- <item> type </item>
- <item> trzeros </item>
- <item> triu </item>
- <item> trisolve </item>
- <item> tril </item>
- <item> trianfml </item>
- <item> trfmod </item>
- <item> TRASH_f </item>
- <item> translatepaths </item>
- <item> trans_closure </item>
- <item> trans </item>
- <item> trace </item>
- <item> toeplitz </item>
- <item> tlist </item>
- <item> TK_SetVar </item>
- <item> TK_GetVar </item>
- <item> TK_EvalStr </item>
- <item> TK_EvalFile </item>
- <item> titlepage </item>
- <item> timer </item>
- <item> time_id </item>
- <item> TIME_f </item>
- <item> tilda </item>
- <item> tf2ss </item>
- <item> tf2des </item>
- <item> TEXT_f </item>
- <item> texprint </item>
- <item> testmatrix </item>
- <item> tdinit </item>
- <item> TCLSS_f </item>
- <item> tanm </item>
- <item> tanhm </item>
- <item> tanh </item>
- <item> tangent </item>
- <item> TANBLK_f </item>
- <item> tan </item>
- <item> systmat </item>
- <item> systems </item>
- <item> system </item>
- <item> syssize </item>
- <item> syslin </item>
- <item> sysfact- </item>
- <item> sysdiag </item>
- <item> sysconv </item>
- <item> symbols </item>
- <item> sylv </item>
- <item> sylm </item>
- <item> svplot </item>
- <item> svd </item>
- <item> sva </item>
- <item> supernode </item>
- <item> SUPER_f </item>
- <item> sum </item>
- <item> successors </item>
- <item> subplot </item>
- <item> subgraph </item>
- <item> subf </item>
- <item> strsubst </item>
- <item> strong_con_nodes </item>
- <item> strong_connex </item>
- <item> stripblanks </item>
- <item> strings </item>
- <item> string </item>
- <item> strindex </item>
- <item> strcat </item>
- <item> str2code </item>
- <item> STOP_f </item>
- <item> st_ility </item>
- <item> st_deviation </item>
- <item> startup </item>
- <item> star </item>
- <item> standard_output </item>
- <item> standard_origin </item>
- <item> standard_input </item>
- <item> standard_draw </item>
- <item> standard_define </item>
- <item> stacksize </item>
- <item> stabil </item>
- <item> ssrand </item>
- <item> ssprint </item>
- <item> sskf </item>
- <item> sscanf </item>
- <item> ss2tf </item>
- <item> ss2ss </item>
- <item> ss2des </item>
- <item> srkf </item>
- <item> srfaur </item>
- <item> squarewave </item>
- <item> square </item>
- <item> sqrtm </item>
- <item> sqrt </item>
- <item> sqroot </item>
- <item> spzeros </item>
- <item> sprintf </item>
- <item> sprand </item>
- <item> spones </item>
- <item> SPLIT_f </item>
- <item> split_edge </item>
- <item> splin </item>
- <item> spget </item>
- <item> speye </item>
- <item> specfact </item>
- <item> spec </item>
- <item> spcompack </item>
- <item> spchol </item>
- <item> sparse </item>
- <item> spantwo </item>
- <item> spanplus </item>
- <item> spaninter </item>
- <item> sp2adj </item>
- <item> sound </item>
- <item> sort </item>
- <item> SOM_f </item>
- <item> solve </item>
- <item> %sn </item>
- <item> smooth </item>
- <item> sm2ss </item>
- <item> sm2des </item>
- <item> slash </item>
- <item> size </item>
- <item> sinm </item>
- <item> sinhm </item>
- <item> sinh </item>
- <item> sincd </item>
- <item> sinc </item>
- <item> SINBLK_f </item>
- <item> sin </item>
- <item> simp_mode </item>
- <item> simp </item>
- <item> signm </item>
- <item> sign </item>
- <item> showprofile </item>
- <item> show_nodes </item>
- <item> show_graph </item>
- <item> show_arcs </item>
- <item> shortest_path </item>
- <item> sgrid </item>
- <item> Sgrayplot </item>
- <item> Sfgrayplot </item>
- <item> sfact </item>
- <item> setscicosvars </item>
- <item> setmenu </item>
- <item> setfield </item>
- <item> setbpt </item>
- <item> set </item>
- <item> sensi </item>
- <item> SendMsg </item>
- <item> semidef </item>
- <item> semicolumn </item>
- <item> semi </item>
- <item> SELECT_f </item>
- <item> secto3d </item>
- <item> sd2sci </item>
- <item> SCOPXY_f </item>
- <item> SCOPE_f </item>
- <item> scilink </item>
- <item> ScilabEval </item>
- <item> scilab </item>
- <item> scifunc_block </item>
- <item> scicos_model </item>
- <item> scicos_menus </item>
- <item> scicos_main </item>
- <item> scicos_link </item>
- <item> scicosim </item>
- <item> scicos_graphics </item>
- <item> scicos_cpr </item>
- <item> scicos_block </item>
- <item> scicos </item>
- <item> sciargs </item>
- <item> sci2map </item>
- <item> sci2for </item>
- <item> sci2exp </item>
- <item> schur </item>
- <item> scanf_conversion </item>
- <item> scanf </item>
- <item> scaling </item>
- <item> SAWTOOTH_f </item>
- <item> savewave </item>
- <item> save_graph </item>
- <item> save </item>
- <item> SAT_f </item>
- <item> SAMPLEHOLD_f </item>
- <item> salesman </item>
- <item> rtitr </item>
- <item> rref </item>
- <item> rpem </item>
- <item> rowshuff </item>
- <item> rowregul </item>
- <item> rowinout </item>
- <item> rowcompr </item>
- <item> rowcomp </item>
- <item> routh_t </item>
- <item> round </item>
- <item> rotate </item>
- <item> roots </item>
- <item> rlist </item>
- <item> ric_desc </item>
- <item> riccati </item>
- <item> ricc </item>
- <item> RFILE_f </item>
- <item> residu </item>
- <item> replot </item>
- <item> repfreq </item>
- <item> remezb </item>
- <item> remez </item>
- <item> RELAY_f </item>
- <item> reglin </item>
- <item> REGISTER_f </item>
- <item> recur </item>
- <item> real </item>
- <item> readmps </item>
- <item> READC_f </item>
- <item> readc_ </item>
- <item> readb </item>
- <item> read4b </item>
- <item> read </item>
- <item> rdivf </item>
- <item> rcond </item>
- <item> rational </item>
- <item> rat </item>
- <item> rank </item>
- <item> range </item>
- <item> randpencil </item>
- <item> RAND_f </item>
- <item> rand </item>
- <item> quote </item>
- <item> quit </item>
- <item> quaskro </item>
- <item> quapro </item>
- <item> QUANT_f </item>
- <item> qr </item>
- <item> qassign </item>
- <item> pwd </item>
- <item> pvm_tidtohost </item>
- <item> pvm_start </item>
- <item> pvm_spawn_independent </item>
- <item> pvm_spawn </item>
- <item> pvm_set_timer </item>
- <item> pvm_send </item>
- <item> pvm_sci2f77 </item>
- <item> pvm_reduce </item>
- <item> pvm_recv </item>
- <item> pvm_probe </item>
- <item> pvm_mytid </item>
- <item> pvm_lvgroup </item>
- <item> pvm_kill </item>
- <item> pvm_joingroup </item>
- <item> pvm_halt </item>
- <item> pvm_gsize </item>
- <item> pvm_get_timer </item>
- <item> pvm_getinst </item>
- <item> pvm_exit </item>
- <item> pvm_error </item>
- <item> pvm_delhosts </item>
- <item> pvmd3 </item>
- <item> pvm_config </item>
- <item> pvm_bufinfo </item>
- <item> pvm_bcast </item>
- <item> pvm_addhosts </item>
- <item> pvm </item>
- <item> pspect </item>
- <item> psmall </item>
- <item> projspec </item>
- <item> projsl </item>
- <item> proj </item>
- <item> profile </item>
- <item> PROD_f </item>
- <item> prod </item>
- <item> printing </item>
- <item> printf_conversion </item>
- <item> printf </item>
- <item> print </item>
- <item> predef </item>
- <item> predecessors </item>
- <item> prbs_a </item>
- <item> ppol </item>
- <item> power </item>
- <item> POWBLK_f </item>
- <item> POSTONEG_f </item>
- <item> portrait </item>
- <item> portr3d </item>
- <item> poly </item>
- <item> polfact </item>
- <item> polarplot </item>
- <item> polar </item>
- <item> pol2tex </item>
- <item> pol2str </item>
- <item> pol2des </item>
- <item> pmodulo </item>
- <item> p_margin </item>
- <item> plzr </item>
- <item> plus </item>
- <item> plotprofile </item>
- <item> plot_graph </item>
- <item> plotframe </item>
- <item> plot3d3 </item>
- <item> plot3d2 </item>
- <item> plot3d1 </item>
- <item> plot3d </item>
- <item> plot2d4 </item>
- <item> plot2d3 </item>
- <item> plot2d2 </item>
- <item> plot2d1 </item>
- <item> plot2d </item>
- <item> plot </item>
- <item> playsnd </item>
- <item> pipe_network </item>
- <item> pinv </item>
- <item> phc </item>
- <item> phasemag </item>
- <item> pfss </item>
- <item> pertrans </item>
- <item> perfect_match </item>
- <item> percent </item>
- <item> penlaur </item>
- <item> pencan </item>
- <item> pen2ea </item>
- <item> pdiv </item>
- <item> pbig </item>
- <item> path_2_nodes </item>
- <item> part </item>
- <item> parrot </item>
- <item> parents </item>
- <item> paramfplot2d </item>
- <item> param3d1 </item>
- <item> param3d </item>
- <item> overloading </item>
- <item> OUT_f </item>
- <item> orth </item>
- <item> or </item>
- <item> optim </item>
- <item> ones </item>
- <item> oldsave </item>
- <item> oldload </item>
- <item> ode_root </item>
- <item> odeoptions </item>
- <item> ode_discrete </item>
- <item> odedi </item>
- <item> odedc </item>
- <item> ode </item>
- <item> obsvss </item>
- <item> obsv_mat </item>
- <item> obs_gram </item>
- <item> observer </item>
- <item> obscont1 </item>
- <item> obscont </item>
- <item> nyquist </item>
- <item> numer </item>
- <item> null </item>
- <item> not </item>
- <item> norm </item>
- <item> noisegen </item>
- <item> nodes_degrees </item>
- <item> nodes_2_path </item>
- <item> node_number </item>
- <item> nnz </item>
- <item> nlev </item>
- <item> nf3d </item>
- <item> newfun </item>
- <item> newest </item>
- <item> netwindows </item>
- <item> netwindow </item>
- <item> netclose </item>
- <item> neighbors </item>
- <item> nehari </item>
- <item> NEGTOPOS_f </item>
- <item> narsimul </item>
- <item> names </item>
- <item> MUX_f </item>
- <item> mulf </item>
- <item> mu2lin </item>
- <item> mtlb_sparse </item>
- <item> mtlb_save </item>
- <item> mtlb_mode </item>
- <item> mtlb_load </item>
- <item> mtell </item>
- <item> msscanf </item>
- <item> msprintf </item>
- <item> mseek </item>
- <item> mscanf </item>
- <item> mrfit </item>
- <item> mputstr </item>
- <item> mputl </item>
- <item> mput </item>
- <item> mps2linpro </item>
- <item> mprintf </item>
- <item> mopen </item>
- <item> modulo </item>
- <item> mode </item>
- <item> mlist </item>
- <item> min_weight_tree </item>
- <item> minus </item>
- <item> minss </item>
- <item> minreal </item>
- <item> min_qcost_flow </item>
- <item> min_lcost_flow2 </item>
- <item> min_lcost_flow1 </item>
- <item> min_lcost_cflow </item>
- <item> mini </item>
- <item> MIN_f </item>
- <item> mine </item>
- <item> min </item>
- <item> milk_drop </item>
- <item> mgetstr </item>
- <item> mgetl </item>
- <item> mgeti </item>
- <item> mget </item>
- <item> mfscanf </item>
- <item> mfprintf </item>
- <item> mfile2sci </item>
- <item> mfft </item>
- <item> MFCLCK_f </item>
- <item> metanet_sync </item>
- <item> metanet </item>
- <item> mesh2d </item>
- <item> mese </item>
- <item> meof </item>
- <item> median </item>
- <item> mean </item>
- <item> mclose </item>
- <item> MCLOCK_f </item>
- <item> mclearerr </item>
- <item> m_circle </item>
- <item> maxi </item>
- <item> max_flow </item>
- <item> MAX_f </item>
- <item> max_clique </item>
- <item> max_cap_path </item>
- <item> max </item>
- <item> matrix </item>
- <item> matrices </item>
- <item> Matplot1 </item>
- <item> Matplot </item>
- <item> mat_2_graph </item>
- <item> markp2ss </item>
- <item> mapsound </item>
- <item> manedit </item>
- <item> man </item>
- <item> make_graph </item>
- <item> macrovar </item>
- <item> macro </item>
- <item> macr2lst </item>
- <item> macglov </item>
- <item> lyap </item>
- <item> lusolve </item>
- <item> luget </item>
- <item> lufact </item>
- <item> ludel </item>
- <item> lu </item>
- <item> ltitr </item>
- <item> lstcat </item>
- <item> lsslist </item>
- <item> lqr </item>
- <item> lqg_ltr </item>
- <item> lqg2stan </item>
- <item> lqg </item>
- <item> lqe </item>
- <item> lotest </item>
- <item> LOOKUP_f </item>
- <item> logspace </item>
- <item> logm </item>
- <item> LOGBLK_f </item>
- <item> log2 </item>
- <item> log10 </item>
- <item> log </item>
- <item> locate </item>
- <item> loadwave </item>
- <item> load_graph </item>
- <item> load </item>
- <item> lmitool </item>
- <item> lmisolver </item>
- <item> list </item>
- <item> linspace </item>
- <item> linsolve </item>
- <item> linpro </item>
- <item> link </item>
- <item> linfn </item>
- <item> linf </item>
- <item> lines </item>
- <item> line_graph </item>
- <item> lindquist </item>
- <item> lin2mu </item>
- <item> lin </item>
- <item> lib </item>
- <item> lgfft </item>
- <item> lft </item>
- <item> lex_sort </item>
- <item> levin </item>
- <item> lev </item>
- <item> less </item>
- <item> leqr </item>
- <item> length </item>
- <item> legends </item>
- <item> left </item>
- <item> leastsq </item>
- <item> ldivf </item>
- <item> ldiv </item>
- <item> lcmdiag </item>
- <item> lcm </item>
- <item> lcf </item>
- <item> lattp </item>
- <item> lattn </item>
- <item> lasterror </item>
- <item> kroneck </item>
- <item> kron </item>
- <item> krac2 </item>
- <item> kpure </item>
- <item> knapsack </item>
- <item> keyboard </item>
- <item> kernel </item>
- <item> karmarkar </item>
- <item> kalm </item>
- <item> %k </item>
- <item> jmat </item>
- <item> isreal </item>
- <item> isoview </item>
- <item> isnan </item>
- <item> isinf </item>
- <item> isglobal </item>
- <item> iserror </item>
- <item> isdef </item>
- <item> is_connex </item>
- <item> invsyslin </item>
- <item> invr </item>
- <item> inv_coeff </item>
- <item> INVBLK_f </item>
- <item> inv </item>
- <item> inttype </item>
- <item> inttrap </item>
- <item> intsplin </item>
- <item> INTRPLBLK_f </item>
- <item> INTRP2BLK_f </item>
- <item> intppty </item>
- <item> intl </item>
- <item> intg </item>
- <item> intersect </item>
- <item> intersci </item>
- <item> interpln </item>
- <item> interp </item>
- <item> integrate </item>
- <item> INTEGRAL_f </item>
- <item> intdec </item>
- <item> intc </item>
- <item> int8 </item>
- <item> int3d </item>
- <item> int32 </item>
- <item> int2d </item>
- <item> int16 </item>
- <item> int </item>
- <item> insertion </item>
- <item> input </item>
- <item> IN_f </item>
- <item> imrep2ss </item>
- <item> impl </item>
- <item> im_inv </item>
- <item> imag </item>
- <item> ilib_gen_Make </item>
- <item> ilib_gen_loader </item>
- <item> ilib_gen_gateway </item>
- <item> ilib_for_link </item>
- <item> ilib_compile </item>
- <item> ilib_build </item>
- <item> iirlp </item>
- <item> iirgroup </item>
- <item> iir </item>
- <item> IFTHEL_f </item>
- <item> ieee </item>
- <item> iconvert </item>
- <item> hypermatrices </item>
- <item> hypermat </item>
- <item> htrianr </item>
- <item> hrmt </item>
- <item> householder </item>
- <item> hotcolormap </item>
- <item> host </item>
- <item> horner </item>
- <item> h_norm </item>
- <item> histplot </item>
- <item> hist3d </item>
- <item> h_inf_st </item>
- <item> h_inf </item>
- <item> hilb </item>
- <item> hex2dec </item>
- <item> hess </item>
- <item> hermit </item>
- <item> %helps </item>
- <item> help </item>
- <item> h_cl </item>
- <item> havewindow </item>
- <item> hat </item>
- <item> hankelsv </item>
- <item> hank </item>
- <item> hamilton </item>
- <item> HALT_f </item>
- <item> halt </item>
- <item> h2norm </item>
- <item> gtild </item>
- <item> gstacksize </item>
- <item> gspec </item>
- <item> gsort </item>
- <item> gschur </item>
- <item> group </item>
- <item> gr_menu </item>
- <item> grep </item>
- <item> graypolarplot </item>
- <item> grayplot </item>
- <item> graycolormap </item>
- <item> graph_union </item>
- <item> graph_sum </item>
- <item> graph_simp </item>
- <item> graph_power </item>
- <item> graph-list </item>
- <item> Graphics </item>
- <item> graph_diameter </item>
- <item> graph_complement </item>
- <item> graph_center </item>
- <item> graph_2_mat </item>
- <item> grand </item>
- <item> graduate </item>
- <item> gpeche </item>
- <item> g_margin </item>
- <item> G_make </item>
- <item> global </item>
- <item> glist </item>
- <item> glever </item>
- <item> givens </item>
- <item> girth </item>
- <item> gfrancis </item>
- <item> gfare </item>
- <item> getversion </item>
- <item> getvalue </item>
- <item> getsymbol </item>
- <item> getscicosvars </item>
- <item> getpid </item>
- <item> GetMsg </item>
- <item> getmark </item>
- <item> getlinestyle </item>
- <item> getio </item>
- <item> get_function_path </item>
- <item> getfont </item>
- <item> getfield </item>
- <item> getf </item>
- <item> getenv </item>
- <item> getdate </item>
- <item> getd </item>
- <item> getcwd </item>
- <item> getcolor </item>
- <item> getblocklabel </item>
- <item> get </item>
- <item> geom3d </item>
- <item> GENSQR_f </item>
- <item> GENSIN_f </item>
- <item> gen_net </item>
- <item> genmarkov </item>
- <item> genlib </item>
- <item> genfac3d </item>
- <item> GENERIC_f </item>
- <item> GENERAL_f </item>
- <item> gcf </item>
- <item> gcd </item>
- <item> gcare </item>
- <item> gammaln </item>
- <item> gamma </item>
- <item> gamitg </item>
- <item> gainplot </item>
- <item> GAIN_f </item>
- <item> GAINBLK_f </item>
- <item> fusee </item>
- <item> funptr </item>
- <item> funcprot </item>
- <item> fun2string </item>
- <item> fullrfk </item>
- <item> fullrf </item>
- <item> full </item>
- <item> fstair </item>
- <item> fstabst </item>
- <item> fspecg </item>
- <item> fsolve </item>
- <item> fsfirlin </item>
- <item> fscanfMat </item>
- <item> fscanf </item>
- <item> frmag </item>
- <item> frfit </item>
- <item> frexp </item>
- <item> freson </item>
- <item> freq </item>
- <item> frep2tf </item>
- <item> fprintfMat </item>
- <item> fprintf </item>
- <item> fplot3d1 </item>
- <item> fplot3d </item>
- <item> fplot2d </item>
- <item> fourplan </item>
- <item> fort </item>
- <item> formatman </item>
- <item> format </item>
- <item> flts </item>
- <item> floor </item>
- <item> fix </item>
- <item> fit_dat </item>
- <item> find_path </item>
- <item> findobj </item>
- <item> findm </item>
- <item> find_freq </item>
- <item> find </item>
- <item> filter </item>
- <item> fileinfo </item>
- <item> file </item>
- <item> figure </item>
- <item> fgrayplot </item>
- <item> fft </item>
- <item> ffilt </item>
- <item> feval </item>
- <item> feedback </item>
- <item> fec </item>
- <item> fcontour2d </item>
- <item> fcontour </item>
- <item> fchamp </item>
- <item> faurre </item>
- <item> factors </item>
- <item> fac3d </item>
- <item> eye </item>
- <item> extraction </item>
- <item> external </item>
- <item> expm </item>
- <item> EXPBLK_f </item>
- <item> exp </item>
- <item> exit </item>
- <item> exists </item>
- <item> execstr </item>
- <item> ExecScilab </item>
- <item> ExeclScilab </item>
- <item> ExecAppli </item>
- <item> exec </item>
- <item> excel2sci </item>
- <item> Example </item>
- <item> EVTGEN_f </item>
- <item> EVTDLY_f </item>
- <item> evstr </item>
- <item> EVENTSCOPE_f </item>
- <item> evans </item>
- <item> eval3dp </item>
- <item> eval3d </item>
- <item> eval </item>
- <item> error </item>
- <item> errclear </item>
- <item> errcatch </item>
- <item> errbar </item>
- <item> erfcx </item>
- <item> erfc </item>
- <item> erf </item>
- <item> ereduc </item>
- <item> equil1 </item>
- <item> equil </item>
- <item> equal </item>
- <item> eqiir </item>
- <item> eqfir </item>
- <item> emptystr </item>
- <item> empty </item>
- <item> ell1mag </item>
- <item> eigenmarkov </item>
- <item> edit_curv </item>
- <item> edit </item>
- <item> edge_number </item>
- <item> dtsi </item>
- <item> dt_ility </item>
- <item> dsimul </item>
- <item> dscr </item>
- <item> driver </item>
- <item> drawaxis </item>
- <item> dragrect </item>
- <item> double </item>
- <item> dot </item>
- <item> DLSS_f </item>
- <item> DLR_f </item>
- <item> DLRADAPT_f </item>
- <item> dlgamma </item>
- <item> dispfile </item>
- <item> dispbpt </item>
- <item> disp </item>
- <item> diophant </item>
- <item> diary </item>
- <item> diag </item>
- <item> dhnorm </item>
- <item> dft </item>
- <item> detr </item>
- <item> determ </item>
- <item> det </item>
- <item> DestroyLink </item>
- <item> des2tf </item>
- <item> des2ss </item>
- <item> derivative- </item>
- <item> derivat </item>
- <item> denom </item>
- <item> DEMUX_f </item>
- <item> demos </item>
- <item> delmenu </item>
- <item> delip </item>
- <item> delete_nodes </item>
- <item> delete_arcs </item>
- <item> delbpt </item>
- <item> DELAYV_f </item>
- <item> DELAY_f </item>
- <item> degree </item>
- <item> deff </item>
- <item> dec2hex </item>
- <item> debug </item>
- <item> ddp </item>
- <item> dcf </item>
- <item> dbphi </item>
- <item> date </item>
- <item> datafit </item>
- <item> dassl </item>
- <item> dasrt </item>
- <item> czt </item>
- <item> cycle_basis </item>
- <item> CURV_f </item>
- <item> curblock </item>
- <item> cumsum </item>
- <item> cumprod </item>
- <item> ctr_gram </item>
- <item> cspect </item>
- <item> csim </item>
- <item> CreateLink </item>
- <item> cothm </item>
- <item> coth </item>
- <item> cotg </item>
- <item> cosm </item>
- <item> coshm </item>
- <item> cosh </item>
- <item> COSBLK_f </item>
- <item> cos </item>
- <item> corr </item>
- <item> copfac </item>
- <item> convstr </item>
- <item> convol </item>
- <item> convex_hull </item>
- <item> contrss </item>
- <item> contract_edge </item>
- <item> contr </item>
- <item> contourf </item>
- <item> contour2di </item>
- <item> contour2d </item>
- <item> contour </item>
- <item> cont_mat </item>
- <item> cont_frm </item>
- <item> CONST_f </item>
- <item> con_nodes </item>
- <item> connex </item>
- <item> conj </item>
- <item> cond </item>
- <item> companion </item>
- <item> comp </item>
- <item> Communications </item>
- <item> colregul </item>
- <item> colormap </item>
- <item> colon </item>
- <item> colnew </item>
- <item> colinout </item>
- <item> colcompr </item>
- <item> colcomp </item>
- <item> coffg </item>
- <item> coff </item>
- <item> coeff </item>
- <item> code2str </item>
- <item> cmndred </item>
- <item> cmb_lin </item>
- <item> CLSS_f </item>
- <item> cls2dls </item>
- <item> CLR_f </item>
- <item> close </item>
- <item> CLOCK_f </item>
- <item> CLKSPLIT_f </item>
- <item> CLKSOMV_f </item>
- <item> CLKSOM_f </item>
- <item> CLKOUTV_f </item>
- <item> CLKOUT_f </item>
- <item> CLKINV_f </item>
- <item> CLKIN_f </item>
- <item> c_link </item>
- <item> CLINDUMMY_f </item>
- <item> clearglobal </item>
- <item> clearfun </item>
- <item> clear </item>
- <item> clean </item>
- <item> classmarkov </item>
- <item> circuit </item>
- <item> chsolve </item>
- <item> chol </item>
- <item> chfact </item>
- <item> chepol </item>
- <item> check_graph </item>
- <item> cheb2mag </item>
- <item> cheb1mag </item>
- <item> chdir </item>
- <item> chart </item>
- <item> champ1 </item>
- <item> champ </item>
- <item> chaintest </item>
- <item> chain_struct </item>
- <item> cepstrum </item>
- <item> ceil </item>
- <item> cdft </item>
- <item> cdfpoi </item>
- <item> cdfnor </item>
- <item> cdfnbn </item>
- <item> cdfgam </item>
- <item> cdffnc </item>
- <item> cdff </item>
- <item> cdfchn </item>
- <item> cdfchi </item>
- <item> cdfbin </item>
- <item> cdfbet </item>
- <item> ccontrg </item>
- <item> casc </item>
- <item> canon </item>
- <item> call </item>
- <item> calfrq </item>
- <item> calerf </item>
- <item> cainv </item>
- <item> bvode </item>
- <item> buttmag </item>
- <item> bstap </item>
- <item> boucle </item>
- <item> boolean </item>
- <item> bool2s </item>
- <item> bode </item>
- <item> bloc2ss </item>
- <item> bloc2exp </item>
- <item> black </item>
- <item> binomial </item>
- <item> bilin </item>
- <item> BIGSOM_f </item>
- <item> bifish </item>
- <item> bezout </item>
- <item> best_match </item>
- <item> bessely </item>
- <item> besselk </item>
- <item> besselj </item>
- <item> besseli </item>
- <item> bdiag </item>
- <item> bandwr </item>
- <item> balreal </item>
- <item> balanc </item>
- <item> backslash </item>
- <item> auwrite </item>
- <item> auread </item>
- <item> augment </item>
- <item> atanm </item>
- <item> atanhm </item>
- <item> atanh </item>
- <item> atan </item>
- <item> %asn </item>
- <item> asinm </item>
- <item> asinhm </item>
- <item> asinh </item>
- <item> asin </item>
- <item> ascii </item>
- <item> articul </item>
- <item> artest </item>
- <item> arsimul </item>
- <item> armax1 </item>
- <item> armax </item>
- <item> armac </item>
- <item> arma2p </item>
- <item> arma </item>
- <item> arl2 </item>
- <item> arhnk </item>
- <item> argn </item>
- <item> arc_number </item>
- <item> arc_graph </item>
- <item> apropos </item>
- <item> ans </item>
- <item> ANIMXY_f </item>
- <item> ANDLOG_f </item>
- <item> and </item>
- <item> analyze </item>
- <item> analpf </item>
- <item> amell </item>
- <item> alufunctions </item>
- <item> AFFICH_f </item>
- <item> aff2ab </item>
- <item> adj_lists </item>
- <item> adj2sp </item>
- <item> add_node </item>
- <item> addmenu </item>
- <item> addinter </item>
- <item> addf </item>
- <item> add_edge </item>
- <item> addcolor </item>
- <item> AdCommunications </item>
- <item> acosm </item>
- <item> acoshm </item>
- <item> acosh </item>
- <item> acos </item>
- <item> ABSBLK_f </item>
- <item> abs </item>
- <item> abinv </item>
- <item> abcd </item>
- </list>
- <contexts>
- <context name="main" attribute="Normal Text" lineEndContext="#stay">
- <keyword attribute="Structure-keywords" context="#stay" String="Structure-keywords"/>
- <keyword attribute="Control-keywords" context="#stay" String="Control-keywords"/>
- <keyword attribute="Function-keywords" context="#stay" String="Function-keywords"/>
- <keyword attribute="Warning-keywords" context="#stay" String="Warning-keywords"/>
- <keyword attribute="Constants-keyword" context="#stay" String="Constants-keyword"/>
- <keyword attribute="functions" context="#stay" String="functions"/>
- <Float attribute = "Flo" context="#stay"/>
- <Int attribute = "Decimal" context="#stay"/>
- <RegExpr String= "//.*$" attribute = "Comment" context="#stay"/>
- <RangeDetect char = "&quot;" char1 = "&quot;" attribute = "String" context="#stay"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Structure-keywords" defStyleNum="dsNormal" color="#000080" selColor="#ffff00" bold="1" italic="0"/>
- <itemData name="Control-keywords" defStyleNum="dsNormal" color="#800000" selColor="#ff0000" bold="1" italic="0"/>
- <itemData name="Function-keywords" defStyleNum="dsNormal" color="#008000" selColor="#ffff00" bold="1" italic="0"/>
- <itemData name="Warning-keywords" defStyleNum="dsNormal" color="#ff0000" selColor="#ff0000" bold="1" italic="0"/>
- <itemData name="Constants-keyword" defStyleNum="dsNormal" color="#008080" selColor="#00ffff" bold="1" italic="0"/>
- <itemData name="functions" defStyleNum="dsNormal" color="#0000ff" selColor="#00ff00" bold="1" italic="1"/>
- <itemData name="Decimal" defStyleNum = "dsDecVal"/>
- <itemData name="Float" defStyleNum = "dsFloat"/>
- <itemData name="Comment" defStyleNum = "dsComment"/>
- <itemData name="String" defStyleNum = "dsString"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- </comments>
- <keywords casesensitive="1" weakDeliminator="%" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="SGML" version="1.02" kateversion="2.1" section="Markup" extensions="*.sgml" mimetype="text/sgml">
- <highlighting>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal Text" >
- <StringDetect attribute="Comment" context="Comment" String="&lt;!--"/>
- <RegExpr attribute="Tag" context="Attribute" String="&lt;\s*\/?\s*[a-zA-Z_:][a-zA-Z0-9._:-]*" />
- </context>
-
- <context attribute="Attribute Name" lineEndContext="#stay" name="Attribute" >
- <Detect2Chars attribute="Tag" context="#pop" char="/" char1="&gt;" />
- <DetectChar attribute="Tag" context="#pop" char="&gt;" />
- <RegExpr attribute="Normal Text" context="Value" String="\s*=\s*" />
- </context>
-
- <context attribute="Attribute Value" lineEndContext="#stay" name="Value" >
- <Detect2Chars attribute="Tag" context="#pop#pop" char="/" char1="&gt;" />
- <DetectChar attribute="Tag" context="#pop#pop" char="&gt;" />
- <DetectChar attribute="Attribute Value" context="Value 2" char="&quot;" />
- </context>
-
- <context attribute="Attribute Value" lineEndContext="#stay" name="Value 2" >
- <DetectChar attribute="Attribute Value" context="#pop#pop" char="&quot;" />
- </context>
-
- <context attribute="Comment" lineEndContext="#stay" name="Comment" >
- <StringDetect attribute="Comment" context="#pop" String="--&gt;"/>
- </context>
-
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Tag" defStyleNum="dsKeyword"/>
- <itemData name="Attribute Name" defStyleNum="dsOthers"/>
- <itemData name="Attribute Value" defStyleNum="dsDataType"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="multiLine" start="&lt;!--" end="//--&gt;" />
- </comments>
- <keywords casesensitive="0" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!-- Highlighting for Sieve scripts (RFC 3028) written by Petter E. Stokke -->
-<language name="Sieve" version="1.01" kateversion="2.1" section="Scripts"
- extensions="*.siv" mimetype="application/sieve" priority="5"
- author="Petter E. Stokke" license="">
- <highlighting>
- <list name="keywords">
- <item> require </item>
- <item> if </item>
- <item> elsif </item>
- <item> else </item>
- <item> discard </item>
- <item> stop </item>
- <item> fileinto </item>
- <item> keep </item>
- <item> reject </item>
- <item> redirect </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <DetectChar attribute="Symbol" context="#stay" char="{" beginRegion="Brace1" />
- <DetectChar attribute="Symbol" context="#stay" char="}" endRegion="Brace1" />
- <RegExpr attribute="Decimal" context="#stay" String="[0-9]+[KMG]?" />
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <RegExpr attribute="String" context="MultilineString" String="text:$" beginRegion="String" />
- <Detect2Chars attribute="Comment" context="Comment" char="/" char1="*" beginRegion="Comment"/>
- <RegExpr attribute="Comment" String="#.*$" context="#stay"/>
- <RegExpr attribute="Tagged Argument" context="#stay" String=":\w+"/>
- <RegExpr attribute="Symbol" context="Member" String="[.]{1,1}" />
- <AnyChar attribute="Symbol" context="#stay" String=":!%&amp;()+,-/.*&lt;=&gt;?[]|~^&#59;"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="String" name="MultilineString">
- <RegExpr attribute="String" context="#pop" String="^\.$" />
- <HlCStringChar attribute="String Char" context="#stay" />
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Member">
- <RegExpr attribute="Function" context="#pop" String="\b[_\w][_\w\d]*(?=[\s]*)" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Comment">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Tagged Argument" defStyleNum="dsOthers"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="multiLine" start="/*" end="*/" />
- <comment name="singleLine" start="#" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="SML" version="1.05" kateversion="2.1" section="Scripts"
- extensions="*.sml;*.ml" mimetype=""
- author="Christoph Cullmann (cullmann@kde.org)" license="LGPL">
- <highlighting>
- <list name="keywords">
- <item> abstype </item>
- <item> and </item>
- <item> andalso </item>
- <item> as </item>
- <item> case </item>
- <item> do </item>
- <item> datatype </item>
- <item> else </item>
- <item> end </item>
- <item> eqtype </item>
- <item> exception </item>
- <item> false </item>
- <item> fn </item>
- <item> fun </item>
- <item> functor </item>
- <item> handle </item>
- <item> if </item>
- <item> in </item>
- <item> include </item>
- <item> infix </item>
- <item> infixr </item>
- <item> let </item>
- <item> local </item>
- <item> nonfix </item>
- <item> of </item>
- <item> op </item>
- <item> open </item>
- <item> orelse </item>
- <item> raise </item>
- <item> rec </item>
- <item> sharing </item>
- <item> sig </item>
- <item> signature </item>
- <item> struct </item>
- <item> structure </item>
- <item> then </item>
- <item> true </item>
- <item> type </item>
- <item> val </item>
- <item> where </item>
- <item> with </item>
- <item> withtype </item>
- <item> while </item>
- </list>
- <list name="types">
- <item> unit </item>
- <item> int </item>
- <item> real </item>
- <item> char </item>
- <item> string </item>
- <item> substring </item>
- <item> word </item>
- <item> ref </item>
- <item> array </item>
- <item> vector </item>
- <item> bool </item>
- <item> list </item>
- <item> option </item>
- <item> order </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <Detect2Chars attribute="Comment" context="Multiline/Inline Comment" char="(" char1="*" />
- <DetectChar attribute="String" context="String" char="&quot;" />
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Data Type" context="#stay" String="types" />
- <Float attribute="Float" context="#stay">
- <AnyChar String="fF" attribute="Float" context="#stay"/>
- </Float>
- <HlCHex attribute="Decimal" context="#stay"/>
- <Int attribute="Decimal" context="#stay" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Multiline/Inline Comment">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1=")" />
- </context>
- <context attribute="String" lineEndContext="#stay" name="String">
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsComment" />
- <itemData name="Notice" defStyleNum="dsString" />
- <itemData name="String Char" defStyleNum="dsChar" />
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="1" />
- <comments>
- <comment name="multiLine" start="(*" end="*)" />
- </comments>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!-- mySQL SQL, syntax definition based on sql.xml by Yury Lebedev -->
-<language name="SQL-MySQL" version="1.05" kateversion="2.1" section="Other"
- extensions="*.sql;*.SQL" mimetype="text/x-sql" casesensitive="0"
- author="Shane Wright (me@shanewright.co.uk)" license="">
- <highlighting>
- <list name="keywords">
- <item> ACCESS </item>
- <item> ADD </item>
- <item> ALL </item>
- <item> ALTER </item>
- <item> ANALYZE </item>
- <item> AND </item>
- <item> AS </item>
- <item> ASC </item>
- <item> AUTO_INCREMENT </item>
- <item> BDB </item>
- <item> BERKELEYDB </item>
- <item> BETWEEN </item>
- <item> BOTH </item>
- <item> BY </item>
- <item> CASCADE </item>
- <item> CASE </item>
- <item> CHANGE </item>
- <item> COLUMN </item>
- <item> COLUMNS </item>
- <item> CONSTRAINT </item>
- <item> CREATE </item>
- <item> CROSS </item>
- <item> CURRENT_DATE </item>
- <item> CURRENT_TIME </item>
- <item> CURRENT_TIMESTAMP </item>
- <item> DATABASE </item>
- <item> DATABASES </item>
- <item> DAY_HOUR </item>
- <item> DAY_MINUTE </item>
- <item> DAY_SECOND </item>
- <item> DEC </item>
- <item> DEFAULT </item>
- <item> DELAYED </item>
- <item> DELETE </item>
- <item> DESC </item>
- <item> DESCRIBE </item>
- <item> DISTINCT </item>
- <item> DISTINCTROW </item>
- <item> DROP </item>
- <item> ELSE </item>
- <item> ENCLOSED </item>
- <item> ESCAPED </item>
- <item> EXISTS </item>
- <item> EXPLAIN </item>
- <item> FIELDS </item>
- <item> FOR </item>
- <item> FOREIGN </item>
- <item> FROM </item>
- <item> FULLTEXT </item>
- <item> FUNCTION </item>
- <item> GRANT </item>
- <item> GROUP </item>
- <item> HAVING </item>
- <item> HIGH_PRIORITY </item>
- <item> IF </item>
- <item> IGNORE </item>
- <item> IN </item>
- <item> INDEX </item>
- <item> INFILE </item>
- <item> INNER </item>
- <item> INNODB </item>
- <item> INSERT </item>
- <item> INTERVAL </item>
- <item> INTO </item>
- <item> IS </item>
- <item> JOIN </item>
- <item> KEY </item>
- <item> KEYS </item>
- <item> KILL </item>
- <item> LEADING </item>
- <item> LEFT </item>
- <item> LIKE </item>
- <item> LIMIT </item>
- <item> LINES </item>
- <item> LOAD </item>
- <item> LOCK </item>
- <item> LOW_PRIORITY </item>
- <item> MASTER_SERVER_ID </item>
- <item> MATCH </item>
- <item> MRG_MYISAM </item>
- <item> NATURAL </item>
- <item> NOT </item>
- <item> NULL </item>
- <item> NUMERIC </item>
- <item> ON </item>
- <item> OPTIMIZE </item>
- <item> OPTION </item>
- <item> OPTIONALLY </item>
- <item> OR </item>
- <item> ORDER </item>
- <item> OUTER </item>
- <item> OUTFILE </item>
- <item> PARTIAL </item>
- <item> PRECISION </item>
- <item> PRIMARY </item>
- <item> PRIVILEGES </item>
- <item> PROCEDURE </item>
- <item> PURGE </item>
- <item> READ </item>
- <item> REFERENCES </item>
- <item> REGEXP </item>
- <item> RENAME </item>
- <item> REPLACE </item>
- <item> REQUIRE </item>
- <item> RESTRICT </item>
- <item> RETURNS </item>
- <item> REVOKE </item>
- <item> RIGHT </item>
- <item> RLIKE </item>
- <item> SELECT </item>
- <item> SET </item>
- <item> SHOW </item>
- <item> SONAME </item>
- <item> SQL_BIG_RESULT </item>
- <item> SQL_CALC_FOUND_ROWS </item>
- <item> SQL_SMALL_RESULT </item>
- <item> SSL </item>
- <item> STARTING </item>
- <item> STRAIGHT_JOIN </item>
- <item> STRIPED </item>
- <item> TABLE </item>
- <item> TABLES </item>
- <item> TERMINATED </item>
- <item> THEN </item>
- <item> TO </item>
- <item> TRAILING </item>
- <item> UNION </item>
- <item> UNIQUE </item>
- <item> UNLOCK </item>
- <item> UNSIGNED </item>
- <item> UPDATE </item>
- <item> USAGE </item>
- <item> USE </item>
- <item> USER_RESOURCES </item>
- <item> USING </item>
- <item> VALUES </item>
- <item> VARYING </item>
- <item> WHEN </item>
- <item> WHERE </item>
- <item> WITH </item>
- <item> WRITE </item>
- <item> XOR </item>
- <item> YEAR_MONTH </item>
- <item> ZEROFILL </item>
- </list>
- <list name="operators">
- <item> + </item>
- <item> - </item>
- <item> * </item>
- <item> / </item>
- <item> || </item>
- <item> = </item>
- <item> != </item>
- <item> &lt;&gt; </item>
- <item> &lt; </item>
- <item> &lt;= </item>
- <item> &gt; </item>
- <item> &gt;= </item>
- <item> ~= </item>
- <item> ^= </item>
- <item> := </item>
- <item> =&gt; </item>
- <item> ** </item>
- <item> .. </item>
- </list>
- <list name="functions">
- <!-- string functions -->
- <item> ASCII </item>
- <item> ORD </item>
- <item> CONV </item>
- <item> BIN </item>
- <item> OCT </item>
- <item> HEX </item>
- <item> CHAR </item>
- <item> CONCAT </item>
- <item> CONCAT_WS </item>
- <item> LENGTH </item>
- <item> OCTET_LENGTH </item>
- <item> CHAR_LENGTH </item>
- <item> CHARACTER_LENGTH </item>
- <item> BIT_LENGTH </item>
- <item> LOCATE </item>
- <item> POSITION </item>
- <item> INSTR </item>
- <item> LPAD </item>
- <item> RPAD </item>
- <item> LEFT </item>
- <item> RIGHT </item>
- <item> SUBSTRING </item>
- <item> SUBSTRING_INDEX </item>
- <item> MID </item>
- <item> LTRIM </item>
- <item> RTRIM </item>
- <item> TRIM </item>
- <item> SOUNDEX </item>
- <item> SPACE </item>
- <item> REPLACE </item>
- <item> REPEAT </item>
- <item> REVERSE </item>
- <item> INSERT </item>
- <item> ELT </item>
- <item> FIELD </item>
- <item> FIND_IN_SET </item>
- <item> MAKE_SET </item>
- <item> EXPORT_SET </item>
- <item> LCASE </item>
- <item> LOWER </item>
- <item> UCASE </item>
- <item> UPPER </item>
- <item> LOAD_FILE </item>
- <item> QUOTE </item>
- <!-- math functions -->
- <item> ABS </item>
- <item> SIGN </item>
- <item> MOD </item>
- <item> FLOOR </item>
- <item> CEILING </item>
- <item> ROUND </item>
- <item> EXP </item>
- <item> LN </item>
- <item> LOG </item>
- <item> LOG2 </item>
- <item> LOG10 </item>
- <item> POW </item>
- <item> POWER </item>
- <item> SQRT </item>
- <item> PI </item>
- <item> COS </item>
- <item> SIN </item>
- <item> TAN </item>
- <item> ACOS </item>
- <item> ASIN </item>
- <item> ATAN </item>
- <item> ATAN2 </item>
- <item> COT </item>
- <item> RAND </item>
- <item> LEAST </item>
- <item> GREATEST </item>
- <item> DEGREES </item>
- <item> RADIANS </item>
- <item> TRUNCATE </item>
- <!-- date/time functions -->
- <item> DAYOFWEEK </item>
- <item> WEEKDAY </item>
- <item> DAYOFMONTH </item>
- <item> DAYOFYEAR </item>
- <item> MONTH </item>
- <item> DAYNAME </item>
- <item> MONTHNAME </item>
- <item> QUARTER </item>
- <item> WEEK </item>
- <item> YEAR </item>
- <item> YEARWEEK </item>
- <item> HOUR </item>
- <item> MINUTE </item>
- <item> SECOND </item>
- <item> PERIOD_ADD </item>
- <item> PERIOD_DIFF </item>
- <item> DATE_ADD </item>
- <item> DATE_SUB </item>
- <item> ADDDATE </item>
- <item> SUBDATE </item>
- <item> EXTRACT </item>
- <item> TO_DAYS </item>
- <item> FROM_DAYS </item>
- <item> DATE_FORMAT </item>
- <item> TIME_FORMAT </item>
- <item> CURDATE </item>
- <item> CURRENT_DATE </item>
- <item> CURTIME </item>
- <item> CURRENT_TIME </item>
- <item> NOW </item>
- <item> SYSDATE </item>
- <item> CURRENT_TIMESTAMP </item>
- <item> UNIX_TIMESTAMP </item>
- <item> FROM_UNIXTIME </item>
- <item> SEC_TO_TIME </item>
- <item> TIME_TO_SEC </item>
- <!-- cast functions -->
- <item> CAST </item>
- <item> CONVERT </item>
- <!-- misc -->
- <item> BIT_COUNT </item>
- <item> DATABASE </item>
- <item> USER </item>
- <item> SYSTEM_USER </item>
- <item> SESSION_USER </item>
- <item> PASSWORD </item>
- <item> ENCRYPT </item>
- <item> ENCODE </item>
- <item> DECODE </item>
- <item> MD5 </item>
- <item> SHA1 </item>
- <item> SHA </item>
- <item> AES_ENCRYPT </item>
- <item> AES_DECRYPT </item>
- <item> DES_ENCRYPT </item>
- <item> DES_DECRYPT </item>
- <item> LAST_INSERT_ID </item>
- <item> FORMAT </item>
- <item> VERSION </item>
- <item> CONNECTION_ID </item>
- <item> GET_LOCK </item>
- <item> RELEASE_LOCK </item>
- <item> IS_FREE_LOCK </item>
- <item> BENCHMARK </item>
- <item> INET_NTOA </item>
- <item> INET_ATON </item>
- <item> MASTER_POS_WAIT </item>
- <item> FOUND_ROWS </item>
- <!-- GROUP BY -->
- <item> COUNT </item>
- <item> AVG </item>
- <item> MIN </item>
- <item> MAX </item>
- <item> SUM </item>
- <item> STD </item>
- <item> STDDEV </item>
- <item> BIT_OR </item>
- <item> BIT_AND </item>
- </list>
- <list name="types">
- <item> BIGINT </item>
- <item> BINARY </item>
- <item> BLOB </item>
- <item> CHAR </item>
- <item> CHARACTER </item>
- <item> DECIMAL </item>
- <item> DOUBLE </item>
- <item> FLOAT </item>
- <item> INT </item>
- <item> INTEGER </item>
- <item> LONG </item>
- <item> LONGBLOB </item>
- <item> LONGTEXT </item>
- <item> MEDIUMBLOB </item>
- <item> MEDIUMINT </item>
- <item> MEDIUMTEXT </item>
- <item> MIDDLEINT </item>
- <item> REAL </item>
- <item> SMALLINT </item>
- <item> TEXT </item>
- <item> TINYBLOB </item>
- <item> TINYINT </item>
- <item> TINYTEXT </item>
- <item> VARBINARY </item>
- <item> VARCHAR </item>
- <item> HOUR_MINUTE </item>
- <item> HOUR_SECOND </item>
- <item> MINUTE_SECOND </item>
- </list>
- <contexts>
- <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Operator" context="#stay" String="operators"/>
- <keyword attribute="Function" context="#stay" String="functions"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Bb][Uu][Ll][Kk]_[Ee][Xx][Cc][Ee][Pp][Tt][Ii][Oo][Nn][Ss]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Bb][Uu][Ll][Kk]_[Rr][Oo][Ww][Cc][Oo][Uu][Nn][Tt]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Ff][Oo][Uu][Nn][Dd]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Ii][Ss][Oo][Pp][Ee][Nn]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Nn][Oo][Tt][Ff][Oo][Uu][Nn][Dd]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Rr][Oo][Ww][Cc][Oo][Uu][Nn][Tt]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Rr][Oo][Ww][Tt][Yy][Pp][Ee]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Tt][Yy][Pp][Ee]\b"/>
- <Float attribute="Float" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- <DetectChar attribute="String" context="String" char="'"/>
- <DetectChar attribute="Comment" context="SingleLineComment" char="#"/>
- <Detect2Chars attribute="Comment" context="SingleLineComment" char="-" char1="-"/>
- <Detect2Chars attribute="Comment" context="MultiLineComment" char="/" char1="*" beginRegion="Comment"/>
- <RegExpr attribute="Comment" context="SingleLineComment" String="^[Rr][Ee][Mm]\b"/>
- <DetectChar attribute="Comment" context="Identifier" char="&quot;"/>
- <AnyChar attribute="Symbol" context="#stay" String=":&#38;"/>
- <RegExpr attribute="Symbol" context="#stay" String="^/$"/>
- <RegExpr attribute="Preprocessor" context="Preprocessor" String="^@@?[^@ \t\r\n]"/>
- </context>
- <context name="String" attribute="String" lineEndContext="#stay">
- <LineContinue attribute="String" context="#pop"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="Symbol" context="#stay" char="&#38;"/>
- <DetectChar attribute="String" context="#pop" char="'"/>
- </context>
- <context name="SingleLineComment" attribute="Comment" lineEndContext="#pop"/>
- <context name="MultiLineComment" attribute="Comment" lineEndContext="#stay">
- <LineContinue attribute="Comment" context="#pop"/>
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- </context>
- <context name="Identifier" attribute="Identifier" lineEndContext="#pop">
- <DetectChar attribute="Identifier" context="#pop" char="&quot;"/>
- </context>
- <context name="Preprocessor" attribute="Preprocessor" lineEndContext="#pop"/>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Operator" defStyleNum="dsNormal"/>
- <itemData name="Function" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Identifier" defStyleNum="dsOthers"/>
- <itemData name="Symbol" defStyleNum="dsChar"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="--"/>
- <comment name="multiLine" start="/*" end="*/"/>
- </comments>
- <keywords casesensitive="0"/>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!-- PostgreSQL SQL, syntax definition based on sql.xml by Yury Lebedev -->
-<language name="SQL-PostgreSQL" version="1.04" kateversion="2.1" section="Other"
- extensions="*.sql;*.SQL" mimetype="text/x-sql" casesensitive="0"
- author="Shane Wright (me@shanewright.co.uk)" license="">
- <highlighting>
- <list name="keywords">
- <item> ABORT </item>
- <item> ACCESS </item>
- <item> ACTION </item>
- <item> ADA </item>
- <item> ADMIN </item>
- <item> AFTER </item>
- <item> AGGREGATE </item>
- <item> ALIAS </item>
- <item> ALL </item>
- <item> ALLOCATE </item>
- <item> ALTER </item>
- <item> ANALYSE </item>
- <item> ANALYZE </item>
- <item> ANY </item>
- <item> ARE </item>
- <item> AS </item>
- <item> ASC </item>
- <item> ASENSITIVE </item>
- <item> ASSERTION </item>
- <item> ASSIGNMENT </item>
- <item> ASYMMETRIC </item>
- <item> AT </item>
- <item> ATOMIC </item>
- <item> AUTHORIZATION </item>
- <item> BACKWARD </item>
- <item> BEFORE </item>
- <item> BEGIN </item>
- <item> BETWEEN </item>
- <item> BINARY </item>
- <item> BOTH </item>
- <item> BREADTH </item>
- <item> BY </item>
- <item> C </item>
- <item> CACHE </item>
- <item> CALL </item>
- <item> CALLED </item>
- <item> CARDINALITY </item>
- <item> CASCADE </item>
- <item> CASCADED </item>
- <item> CASE </item>
- <item> CAST </item>
- <item> CATALOG </item>
- <item> CATALOG_NAME </item>
- <item> CHAIN </item>
- <item> CHAR_LENGTH </item>
- <item> CHARACTER_LENGTH </item>
- <item> CHARACTER_SET_CATALOG </item>
- <item> CHARACTER_SET_NAME </item>
- <item> CHARACTER_SET_SCHEMA </item>
- <item> CHARACTERISTICS </item>
- <item> CHECK </item>
- <item> CHECKED </item>
- <item> CHECKPOINT </item>
- <item> CLASS </item>
- <item> CLASS_ORIGIN </item>
- <item> CLOB </item>
- <item> CLOSE </item>
- <item> CLUSTER </item>
- <item> COALESCE </item>
- <item> COBOL </item>
- <item> COLLATE </item>
- <item> COLLATION </item>
- <item> COLLATION_CATALOG </item>
- <item> COLLATION_NAME </item>
- <item> COLLATION_SCHEMA </item>
- <item> COLUMN </item>
- <item> COLUMN_NAME </item>
- <item> COMMAND_FUNCTION </item>
- <item> COMMAND_FUNCTION_CODE </item>
- <item> COMMENT </item>
- <item> COMMIT </item>
- <item> COMMITTED </item>
- <item> COMPLETION </item>
- <item> CONDITION_NUMBER </item>
- <item> CONNECT </item>
- <item> CONNECTION </item>
- <item> CONNECTION_NAME </item>
- <item> CONSTRAINT </item>
- <item> CONSTRAINT_CATALOG </item>
- <item> CONSTRAINT_NAME </item>
- <item> CONSTRAINT_SCHEMA </item>
- <item> CONSTRAINTS </item>
- <item> CONSTRUCTOR </item>
- <item> CONTAINS </item>
- <item> CONTINUE </item>
- <item> CONVERT </item>
- <item> COPY </item>
- <item> CORRESPONDING </item>
- <item> COUNT </item>
- <item> CREATE </item>
- <item> CREATEDB </item>
- <item> CREATEUSER </item>
- <item> CROSS </item>
- <item> CUBE </item>
- <item> CURRENT </item>
- <item> CURRENT_DATE </item>
- <item> CURRENT_PATH </item>
- <item> CURRENT_ROLE </item>
- <item> CURRENT_TIME </item>
- <item> CURRENT_TIMESTAMP </item>
- <item> CURRENT_USER </item>
- <item> CURSOR </item>
- <item> CURSOR_NAME </item>
- <item> CYCLE </item>
- <item> DATA </item>
- <item> DATABASE </item>
- <item> DATE </item>
- <item> DATETIME_INTERVAL_CODE </item>
- <item> DATETIME_INTERVAL_PRECISION </item>
- <item> DAY </item>
- <item> DEALLOCATE </item>
- <item> DEC </item>
- <item> DECIMAL </item>
- <item> DECLARE </item>
- <item> DEFAULT </item>
- <item> DEFERRABLE </item>
- <item> DEFERRED </item>
- <item> DEFINED </item>
- <item> DEFINER </item>
- <item> DELETE </item>
- <item> DELIMITERS </item>
- <item> DEPTH </item>
- <item> DEREF </item>
- <item> DESC </item>
- <item> DESCRIBE </item>
- <item> DESCRIPTOR </item>
- <item> DESTROY </item>
- <item> DESTRUCTOR </item>
- <item> DETERMINISTIC </item>
- <item> DIAGNOSTICS </item>
- <item> DICTIONARY </item>
- <item> DISCONNECT </item>
- <item> DISPATCH </item>
- <item> DISTINCT </item>
- <item> DO </item>
- <item> DOMAIN </item>
- <item> DOUBLE </item>
- <item> DROP </item>
- <item> DYNAMIC </item>
- <item> DYNAMIC_FUNCTION </item>
- <item> DYNAMIC_FUNCTION_CODE </item>
- <item> EACH </item>
- <item> ELSE </item>
- <item> ENCODING </item>
- <item> ENCRYPTED </item>
- <item> END </item>
- <item> END-EXEC </item>
- <item> EQUALS </item>
- <item> ESCAPE </item>
- <item> EVERY </item>
- <item> EXCEPT </item>
- <item> EXCEPTION </item>
- <item> EXCLUSIVE </item>
- <item> EXEC </item>
- <item> EXECUTE </item>
- <item> EXISTING </item>
- <item> EXISTS </item>
- <item> EXPLAIN </item>
- <item> EXTERNAL </item>
- <item> FETCH </item>
- <item> FINAL </item>
- <item> FIRST </item>
- <item> FOR </item>
- <item> FORCE </item>
- <item> FOREIGN </item>
- <item> FORTRAN </item>
- <item> FORWARD </item>
- <item> FOUND </item>
- <item> FREE </item>
- <item> FREEZE </item>
- <item> FROM </item>
- <item> FULL </item>
- <item> FUNCTION </item>
- <item> G </item>
- <item> GENERAL </item>
- <item> GENERATED </item>
- <item> GET </item>
- <item> GLOBAL </item>
- <item> GO </item>
- <item> GOTO </item>
- <item> GRANT </item>
- <item> GRANTED </item>
- <item> GROUP </item>
- <item> GROUPING </item>
- <item> HANDLER </item>
- <item> HAVING </item>
- <item> HIERARCHY </item>
- <item> HOLD </item>
- <item> HOST </item>
- <item> HOUR </item>
- <item> IDENTITY </item>
- <item> IGNORE </item>
- <item> ILIKE </item>
- <item> IMMEDIATE </item>
- <item> IMPLEMENTATION </item>
- <item> IN </item>
- <item> INCREMENT </item>
- <item> INDEX </item>
- <item> INDICATOR </item>
- <item> INFIX </item>
- <item> INHERITS </item>
- <item> INITIALIZE </item>
- <item> INITIALLY </item>
- <item> INNER </item>
- <item> INOUT </item>
- <item> INPUT </item>
- <item> INSENSITIVE </item>
- <item> INSERT </item>
- <item> INSTANCE </item>
- <item> INSTANTIABLE </item>
- <item> INSTEAD </item>
- <item> INTERSECT </item>
- <item> INTERVAL </item>
- <item> INTO </item>
- <item> INVOKER </item>
- <item> IS </item>
- <item> ISNULL </item>
- <item> ISOLATION </item>
- <item> ITERATE </item>
- <item> JOIN </item>
- <item> K </item>
- <item> KEY </item>
- <item> KEY_MEMBER </item>
- <item> KEY_TYPE </item>
- <item> LANCOMPILER </item>
- <item> LANGUAGE </item>
- <item> LARGE </item>
- <item> LAST </item>
- <item> LATERAL </item>
- <item> LEADING </item>
- <item> LEFT </item>
- <item> LENGTH </item>
- <item> LESS </item>
- <item> LEVEL </item>
- <item> LIKE </item>
- <item> LIMIT </item>
- <item> LISTEN </item>
- <item> LOAD </item>
- <item> LOCAL </item>
- <item> LOCALTIME </item>
- <item> LOCALTIMESTAMP </item>
- <item> LOCATION </item>
- <item> LOCATOR </item>
- <item> LOCK </item>
- <item> LOWER </item>
- <item> M </item>
- <item> MAP </item>
- <item> MATCH </item>
- <item> MAX </item>
- <item> MAXVALUE </item>
- <item> MESSAGE_LENGTH </item>
- <item> MESSAGE_OCTET_LENGTH </item>
- <item> MESSAGE_TEXT </item>
- <item> METHOD </item>
- <item> MIN </item>
- <item> MINUTE </item>
- <item> MINVALUE </item>
- <item> MOD </item>
- <item> MODE </item>
- <item> MODIFIES </item>
- <item> MODIFY </item>
- <item> MODULE </item>
- <item> MONTH </item>
- <item> MORE </item>
- <item> MOVE </item>
- <item> MUMPS </item>
- <item> NAME </item>
- <item> NAMES </item>
- <item> NATIONAL </item>
- <item> NATURAL </item>
- <item> NEW </item>
- <item> NEXT </item>
- <item> NO </item>
- <item> NOCREATEDB </item>
- <item> NOCREATEUSER </item>
- <item> NONE </item>
- <item> NOT </item>
- <item> NOTHING </item>
- <item> NOTIFY </item>
- <item> NOTNULL </item>
- <item> NULL </item>
- <item> NULLABLE </item>
- <item> NULLIF </item>
- <item> NUMBER </item>
- <item> NUMERIC </item>
- <item> OBJECT </item>
- <item> OCTET_LENGTH </item>
- <item> OF </item>
- <item> OFF </item>
- <item> OFFSET </item>
- <item> OIDS </item>
- <item> OLD </item>
- <item> ON </item>
- <item> ONLY </item>
- <item> OPEN </item>
- <item> OPERATION </item>
- <item> OPERATOR </item>
- <item> OPTION </item>
- <item> OPTIONS </item>
- <item> ORDER </item>
- <item> ORDINALITY </item>
- <item> OUT </item>
- <item> OUTER </item>
- <item> OUTPUT </item>
- <item> OVERLAPS </item>
- <item> OVERLAY </item>
- <item> OVERRIDING </item>
- <item> OWNER </item>
- <item> PAD </item>
- <item> PARAMETER </item>
- <item> PARAMETER_MODE </item>
- <item> PARAMETER_NAME </item>
- <item> PARAMETER_ORDINAL_POSITION </item>
- <item> PARAMETER_SPECIFIC_CATALOG </item>
- <item> PARAMETER_SPECIFIC_NAME </item>
- <item> PARAMETER_SPECIFIC_SCHEMA </item>
- <item> PARAMETERS </item>
- <item> PARTIAL </item>
- <item> PASCAL </item>
- <item> PASSWORD </item>
- <item> PATH </item>
- <item> PENDANT </item>
- <item> PLI </item>
- <item> POSITION </item>
- <item> POSTFIX </item>
- <item> PRECISION </item>
- <item> PREFIX </item>
- <item> PREORDER </item>
- <item> PREPARE </item>
- <item> PRESERVE </item>
- <item> PRIMARY </item>
- <item> PRIOR </item>
- <item> PRIVILEGES </item>
- <item> PROCEDURAL </item>
- <item> PROCEDURE </item>
- <item> PUBLIC </item>
- <item> READ </item>
- <item> READS </item>
- <item> REAL </item>
- <item> RECURSIVE </item>
- <item> REF </item>
- <item> REFERENCES </item>
- <item> REFERENCING </item>
- <item> REINDEX </item>
- <item> RELATIVE </item>
- <item> RENAME </item>
- <item> REPEATABLE </item>
- <item> REPLACE </item>
- <item> RESET </item>
- <item> RESTRICT </item>
- <item> RESULT </item>
- <item> RETURN </item>
- <item> RETURNED_LENGTH </item>
- <item> RETURNED_OCTET_LENGTH </item>
- <item> RETURNED_SQLSTATE </item>
- <item> RETURNS </item>
- <item> REVOKE </item>
- <item> RIGHT </item>
- <item> ROLE </item>
- <item> ROLLBACK </item>
- <item> ROLLUP </item>
- <item> ROUTINE </item>
- <item> ROUTINE_CATALOG </item>
- <item> ROUTINE_NAME </item>
- <item> ROUTINE_SCHEMA </item>
- <item> ROW </item>
- <item> ROW_COUNT </item>
- <item> ROWS </item>
- <item> RULE </item>
- <item> SAVEPOINT </item>
- <item> SCALE </item>
- <item> SCHEMA </item>
- <item> SCHEMA_NAME </item>
- <item> SCOPE </item>
- <item> SCROLL </item>
- <item> SEARCH </item>
- <item> SECOND </item>
- <item> SECTION </item>
- <item> SECURITY </item>
- <item> SELECT </item>
- <item> SELF </item>
- <item> SENSITIVE </item>
- <item> SEQUENCE </item>
- <item> SERIALIZABLE </item>
- <item> SERVER_NAME </item>
- <item> SESSION </item>
- <item> SESSION_USER </item>
- <item> SET </item>
- <item> SETOF </item>
- <item> SETS </item>
- <item> SHARE </item>
- <item> SHOW </item>
- <item> SIMILAR </item>
- <item> SIMPLE </item>
- <item> SIZE </item>
- <item> SOME </item>
- <item> SOURCE </item>
- <item> SPACE </item>
- <item> SPECIFIC </item>
- <item> SPECIFIC_NAME </item>
- <item> SPECIFICTYPE </item>
- <item> SQL </item>
- <item> SQLCODE </item>
- <item> SQLERROR </item>
- <item> SQLEXCEPTION </item>
- <item> SQLSTATE </item>
- <item> SQLWARNING </item>
- <item> START </item>
- <item> STATE </item>
- <item> STATEMENT </item>
- <item> STATIC </item>
- <item> STATISTICS </item>
- <item> STDIN </item>
- <item> STDOUT </item>
- <item> STRUCTURE </item>
- <item> STYLE </item>
- <item> SUBCLASS_ORIGIN </item>
- <item> SUBLIST </item>
- <item> SUBSTRING </item>
- <item> SUM </item>
- <item> SYMMETRIC </item>
- <item> SYSID </item>
- <item> SYSTEM </item>
- <item> SYSTEM_USER </item>
- <item> TABLE </item>
- <item> TABLE_NAME </item>
- <item> TEMP </item>
- <item> TEMPLATE </item>
- <item> TEMPORARY </item>
- <item> TERMINATE </item>
- <item> THAN </item>
- <item> THEN </item>
- <item> TIMEZONE_HOUR </item>
- <item> TIMEZONE_MINUTE </item>
- <item> TO </item>
- <item> TOAST </item>
- <item> TRAILING </item>
- <item> TRANSACTION </item>
- <item> TRANSACTION_ACTIVE </item>
- <item> TRANSACTIONS_COMMITTED </item>
- <item> TRANSACTIONS_ROLLED_BACK </item>
- <item> TRANSFORM </item>
- <item> TRANSFORMS </item>
- <item> TRANSLATE </item>
- <item> TRANSLATION </item>
- <item> TREAT </item>
- <item> TRIGGER </item>
- <item> TRIGGER_CATALOG </item>
- <item> TRIGGER_NAME </item>
- <item> TRIGGER_SCHEMA </item>
- <item> TRIM </item>
- <item> TRUNCATE </item>
- <item> TRUSTED </item>
- <item> TYPE </item>
- <item> UNCOMMITTED </item>
- <item> UNDER </item>
- <item> UNENCRYPTED </item>
- <item> UNION </item>
- <item> UNIQUE </item>
- <item> UNKNOWN </item>
- <item> UNLISTEN </item>
- <item> UNNAMED </item>
- <item> UNNEST </item>
- <item> UNTIL </item>
- <item> UPDATE </item>
- <item> UPPER </item>
- <item> USAGE </item>
- <item> USER </item>
- <item> USER_DEFINED_TYPE_CATALOG </item>
- <item> USER_DEFINED_TYPE_NAME </item>
- <item> USER_DEFINED_TYPE_SCHEMA </item>
- <item> USING </item>
- <item> VACUUM </item>
- <item> VALID </item>
- <item> VALUE </item>
- <item> VALUES </item>
- <item> VARIABLE </item>
- <item> VARYING </item>
- <item> VERBOSE </item>
- <item> VERSION </item>
- <item> VIEW </item>
- <item> WHEN </item>
- <item> WHENEVER </item>
- <item> WHERE </item>
- <item> WITH </item>
- <item> WITHOUT </item>
- <item> WORK </item>
- <item> WRITE </item>
- <item> YEAR </item>
- <item> ZONE </item>
- <item> FALSE </item>
- <item> TRUE </item>
- </list>
- <list name="operators">
- <item> + </item>
- <item> - </item>
- <item> * </item>
- <item> / </item>
- <item> || </item>
- <item> |/ </item>
- <item> ||/ </item>
- <item> ! </item>
- <item> !! </item>
- <item> @ </item>
- <item> &amp; </item>
- <item> | </item>
- <item> # </item>
- <item> &lt;&lt; </item>
- <item> &gt;&gt; </item>
- <item> % </item>
- <item> ^ </item>
- <item> = </item>
- <item> != </item>
- <item> &lt;&gt; </item>
- <item> &lt; </item>
- <item> &lt;= </item>
- <item> &gt; </item>
- <item> &gt;= </item>
- <item> ~ </item>
- <item> ~* </item>
- <item> !~ </item>
- <item> !~* </item>
- <item> ^= </item>
- <item> := </item>
- <item> =&gt; </item>
- <item> ** </item>
- <item> .. </item>
- <item> AND </item>
- <item> OR </item>
- <item> NOT </item>
- <!-- geometric -->
- <item> ## </item>
- <item> &amp;&amp; </item>
- <item> &amp;&lt; </item>
- <item> &amp;&gt; </item>
- <item> &lt;-&gt; </item>
- <item> &lt;^ </item>
- <item> &gt;^ </item>
- <item> ?# </item>
- <item> ?- </item>
- <item> ?-| </item>
- <item> @-@ </item>
- <item> ?| </item>
- <item> ?|| </item>
- <item> @@ </item>
- <item> ~= </item>
- <!-- network address type -->
- <item> &lt;&lt;= </item>
- <item> &gt;&gt;= </item>
- </list>
- <list name="functions">
- <!-- math -->
- <item> ABS </item>
- <item> CBRT </item>
- <item> CEIL </item>
- <item> DEGREES </item>
- <item> EXP </item>
- <item> FLOOR </item>
- <item> LN </item>
- <item> LOG </item>
- <item> MOD </item>
- <item> PI </item>
- <item> POW </item>
- <item> RADIANS </item>
- <item> RANDOM </item>
- <item> ROUND </item>
- <item> SIGN </item>
- <item> SQRT </item>
- <item> TRUNC </item>
- <!-- trig -->
- <item> ACOS </item>
- <item> ASIN </item>
- <item> ATAN </item>
- <item> ATAN2 </item>
- <item> COS </item>
- <item> COT </item>
- <item> SIN </item>
- <item> TAN </item>
- <!-- string -->
- <item> BIT_LENGTH </item>
- <item> CHAR_LENGTH </item>
- <item> CHARACTER_LENGTH </item>
- <item> LOWER </item>
- <item> OCTET_LENGTH </item>
- <item> POSITION </item>
- <item> SUBSTRING </item>
- <item> TRIM </item>
- <item> UPPER </item>
- <!-- other string -->
- <item> ASCII </item>
- <item> BTRIM </item>
- <item> CHR </item>
- <item> CONVERT </item>
- <item> INITCAP </item>
- <item> LENGTH </item>
- <item> LPAD </item>
- <item> LTRIM </item>
- <item> PG_CLIENT_ENCODING </item>
- <item> REPEAT </item>
- <item> RPAD </item>
- <item> RTRIM </item>
- <item> STRPOS </item>
- <item> SUBSTR </item>
- <item> TO_ASCII </item>
- <item> TRANSLATE </item>
- <item> ENCODE </item>
- <item> DECODE </item>
- <!-- data type formatting -->
- <item> TO_CHAR </item>
- <item> TO_DATE </item>
- <item> TO_TIMESTAMP </item>
- <item> TO_NUMBER </item>
- <!-- date/time -->
- <item> AGE </item>
- <item> DATE_PART </item>
- <item> DATE_TRUNC </item>
- <item> EXTRACT </item>
- <item> ISFINITE </item>
- <item> NOW </item>
- <item> TIMEOFDAY </item>
- <item> TIMESTAMP </item>
- <item> EXTRACT </item>
- <!-- geometric -->
- <item> AREA </item>
- <item> BOX </item>
- <item> CENTER </item>
- <item> DIAMETER </item>
- <item> HEIGHT </item>
- <item> ISCLOSED </item>
- <item> ISOPEN </item>
- <item> PCLOSE </item>
- <item> NPOINT </item>
- <item> POPEN </item>
- <item> RADIUS </item>
- <item> WIDTH </item>
- <!-- geometric type conversion -->
- <item> BOX </item>
- <item> CIRCLE </item>
- <item> LSEG </item>
- <item> PATH </item>
- <item> POINT </item>
- <item> POLYGON </item>
- <!-- network address type, TEXT is omitted as its more commonly a data type -->
- <item> BROADCAST </item>
- <item> HOST </item>
- <item> MASKLEN </item>
- <item> SET_MASKLEN </item>
- <item> NETMASK </item>
- <item> NETWORK </item>
- <item> ABBREV </item>
- <!-- sequence manipulation -->
- <item> NEXTVAL </item>
- <item> CURRVAL </item>
- <item> SETVAL </item>
- <!-- conditional expressions -->
- <item> COALESCE </item>
- <item> NULLIF </item>
- <!-- misc -->
- <item> HAS_TABLE_PRIVILEGE </item>
- <item> PG_GET_VIEWDEF </item>
- <item> PG_GET_RULEDEF </item>
- <item> PG_GET_INDEXDEF </item>
- <item> PG_GET_USERBYID </item>
- <item> OBJ_DESCRIPTION </item>
- <item> COL_DESCRIPTION </item>
- <!-- aggregate -->
- <item> AVG </item>
- <item> COUNT </item>
- <item> MAX </item>
- <item> MIN </item>
- <item> STDDEV </item>
- <item> SUM </item>
- <item> VARIANCE </item>
- </list>
- <list name="types">
- <item> LZTEXT </item>
- <item> BIGINT </item>
- <item> INT2 </item>
- <item> INT8 </item>
- <item> BIGSERIAL </item>
- <item> SERIAL8 </item>
- <item> BIT </item>
- <item> BIT VARYING </item>
- <item> VARBIT </item>
- <item> BOOLEAN </item>
- <item> BOOL </item>
- <item> BOX </item>
- <item> BYTEA </item>
- <item> CHARACTER </item>
- <item> CHAR </item>
- <item> CHARACTER VARYING </item>
- <item> VARCHAR </item>
- <item> CIDR </item>
- <item> CIRCLE </item>
- <item> DATE </item>
- <item> DOUBLE PRECISION </item>
- <item> FLOAT8 </item>
- <item> INET </item>
- <item> INTEGER </item>
- <item> INT </item>
- <item> INT4 </item>
- <item> INTERVAL </item>
- <item> LINE </item>
- <item> LSEG </item>
- <item> MACADDR </item>
- <item> MONEY </item>
- <item> NUMERIC </item>
- <item> DECIMAL </item>
- <item> OID </item>
- <item> PATH </item>
- <item> POINT </item>
- <item> POLYGON </item>
- <item> REAL </item>
- <item> SMALLINT </item>
- <item> SERIAL </item>
- <item> TEXT </item>
- <item> TIME </item>
- <item> TIMETZ </item>
- <item> TIMESTAMP </item>
- <item> TIMESTAMPTZ </item>
- </list>
- <contexts>
- <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Operator" context="#stay" String="operators"/>
- <keyword attribute="Function" context="#stay" String="functions"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Bb][Uu][Ll][Kk]_[Ee][Xx][Cc][Ee][Pp][Tt][Ii][Oo][Nn][Ss]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Bb][Uu][Ll][Kk]_[Rr][Oo][Ww][Cc][Oo][Uu][Nn][Tt]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Ff][Oo][Uu][Nn][Dd]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Ii][Ss][Oo][Pp][Ee][Nn]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Nn][Oo][Tt][Ff][Oo][Uu][Nn][Dd]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Rr][Oo][Ww][Cc][Oo][Uu][Nn][Tt]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Rr][Oo][Ww][Tt][Yy][Pp][Ee]\b"/>
- <RegExpr attribute="Data Type" context="#stay" String="%[Tt][Yy][Pp][Ee]\b"/>
- <Float attribute="Float" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- <DetectChar attribute="String" context="String" char="'"/>
- <DetectChar attribute="Comment" context="SingleLineComment" char="#"/>
- <Detect2Chars attribute="Comment" context="SingleLineComment" char="-" char1="-"/>
- <Detect2Chars attribute="Comment" context="MultiLineComment" char="/" char1="*" beginRegion="Comment"/>
- <RegExpr attribute="Comment" context="SingleLineComment" String="^[Rr][Ee][Mm]\b"/>
- <DetectChar attribute="Comment" context="Identifier" char="&quot;"/>
- <AnyChar attribute="Symbol" context="#stay" String=":&#38;"/>
- <RegExpr attribute="Symbol" context="#stay" String="^/$"/>
- <RegExpr attribute="Preprocessor" context="Preprocessor" String="^@@?[^@ \t\r\n]"/>
- </context>
- <context name="String" attribute="String" lineEndContext="#stay">
- <LineContinue attribute="String" context="#pop"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="Symbol" context="#stay" char="&#38;"/>
- <DetectChar attribute="String" context="#pop" char="'"/>
- </context>
- <context name="SingleLineComment" attribute="Comment" lineEndContext="#pop"/>
- <context name="MultiLineComment" attribute="Comment" lineEndContext="#stay">
- <LineContinue attribute="Comment" context="#pop"/>
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- </context>
- <context name="Identifier" attribute="Identifier" lineEndContext="#pop">
- <DetectChar attribute="Identifier" context="#pop" char="&quot;"/>
- </context>
- <context name="Preprocessor" attribute="Preprocessor" lineEndContext="#pop"/>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Operator" defStyleNum="dsNormal"/>
- <itemData name="Function" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Identifier" defStyleNum="dsOthers"/>
- <itemData name="Symbol" defStyleNum="dsChar"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="--"/>
- <comment name="multiLine" start="/*" end="*/"/>
- </comments>
- <keywords casesensitive="0"/>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<!-- Oracle9i SQL and PL/SQL syntax - ANSI SQL superset -->
-<language name="SQL" version="1.05" kateversion="2.1" section="Scripts"
- extensions="*.sql;*.SQL" mimetype="text/x-sql" casesensitive="0"
- author="Yury Lebedev (yurylebedev@mail.ru)" license="">
- <highlighting>
- <list name="keywords">
- <item> ACCESS </item>
- <item> ACCOUNT </item>
- <item> ADD </item>
- <item> ADMIN </item>
- <item> ADMINISTER </item>
- <item> ADVISE </item>
- <item> AFTER </item>
- <item> AGENT </item>
- <item> ALL </item>
- <item> ALL_ROWS </item>
- <item> ALLOCATE </item>
- <item> ALTER </item>
- <item> ANALYZE </item>
- <item> ANCILLARY </item>
- <item> AND </item>
- <item> ANY </item>
- <item> ARCHIVE </item>
- <item> ARCHIVELOG </item>
- <item> AS </item>
- <item> ASC </item>
- <item> ASSOCIATE </item>
- <item> AT </item>
- <item> ATTRIBUTE </item>
- <item> ATTRIBUTES </item>
- <item> AUDIT </item>
- <item> AUTHENTICATED </item>
- <item> AUTHID </item>
- <item> AUTHORIZATION </item>
- <item> AUTOALLOCATE </item>
- <item> AUTOEXTEND </item>
- <item> AUTOMATIC </item>
- <item> BACKUP </item>
- <item> BECOME </item>
- <item> BEFORE </item>
- <item> BEGIN </item>
- <item> BEHALF </item>
- <item> BETWEEN </item>
- <item> BINDING </item>
- <item> BITMAP </item>
- <item> BLOCK </item>
- <item> BLOCK_RANGE </item>
- <item> BODY </item>
- <item> BOUND </item>
- <item> BOTH </item>
- <item> BREAK </item>
- <item> BROADCAST </item>
- <item> BTITLE </item>
- <item> BUFFER_POOL </item>
- <item> BUILD </item>
- <item> BULK </item>
- <item> BY </item>
- <item> CACHE </item>
- <item> CACHE_INSTANCES </item>
- <item> CALL </item>
- <item> CANCEL </item>
- <item> CASCADE </item>
- <item> CASE </item>
- <item> CATEGORY </item>
- <item> CHAINED </item>
- <item> CHANGE </item>
- <item> CHECK </item>
- <item> CHECKPOINT </item>
- <item> CHILD </item>
- <item> CHOOSE </item>
- <item> CHUNK </item>
- <item> CLASS </item>
- <item> CLEAR </item>
- <item> CLONE </item>
- <item> CLOSE </item>
- <item> CLOSE_CACHED_OPEN_CURSORS </item>
- <item> CLUSTER </item>
- <item> COALESCE </item>
- <item> COLUMN </item>
- <item> COLUMNS </item>
- <item> COLUMN_VALUE </item>
- <item> COMMENT </item>
- <item> COMMIT </item>
- <item> COMMITTED </item>
- <item> COMPATIBILITY </item>
- <item> COMPILE </item>
- <item> COMPLETE </item>
- <item> COMPOSITE_LIMIT </item>
- <item> COMPRESS </item>
- <item> COMPUTE </item>
- <item> CONNECT </item>
- <item> CONNECT_TIME </item>
- <item> CONSIDER </item>
- <item> CONSISTENT </item>
- <item> CONSTANT </item>
- <item> CONSTRAINT </item>
- <item> CONSTRAINTS </item>
- <item> CONTAINER </item>
- <item> CONTENTS </item>
- <item> CONTEXT </item>
- <item> CONTINUE </item>
- <item> CONTROLFILE </item>
- <item> COPY </item>
- <item> COST </item>
- <item> CPU_PER_CALL </item>
- <item> CPU_PER_SESSION </item>
- <item> CREATE </item>
- <item> CREATE_STORED_OUTLINES </item>
- <item> CROSS </item>
- <item> CUBE </item>
- <item> CURRENT </item>
- <item> CURSOR </item>
- <item> CYCLE </item>
- <item> DANGLING </item>
- <item> DATA </item>
- <item> DATABASE </item>
- <item> DATAFILE </item>
- <item> DATAFILES </item>
- <item> DAY </item>
- <item> DBA </item>
- <item> DDL </item>
- <item> DEALLOCATE </item>
- <item> DEBUG </item>
- <item> DECLARE </item>
- <item> DEFAULT </item>
- <item> DEFERRABLE </item>
- <item> DEFERRED </item>
- <item> DEFINER </item>
- <item> DEGREE </item>
- <item> DELETE </item>
- <item> DEMAND </item>
- <item> DESC </item>
- <item> DETERMINES </item>
- <item> DICTIONARY </item>
- <item> DIMENSION </item>
- <item> DIRECTORY </item>
- <item> DISABLE </item>
- <item> DISASSOCIATE </item>
- <item> DISCONNECT </item>
- <item> DISMOUNT </item>
- <item> DISTINCT </item>
- <item> DISTRIBUTED </item>
- <item> DROP </item>
- <item> DYNAMIC </item>
- <item> EACH </item>
- <item> ELSE </item>
- <item> ENABLE </item>
- <item> END </item>
- <item> ENFORCE </item>
- <item> ENTRY </item>
- <item> ESCAPE </item>
- <item> ESTIMATE </item>
- <item> EVENTS </item>
- <item> EXCEPT </item>
- <item> EXCEPTION </item>
- <item> EXCEPTIONS </item>
- <item> EXCHANGE </item>
- <item> EXCLUDING </item>
- <item> EXCLUSIVE </item>
- <item> EXEC </item>
- <item> EXECUTE </item>
- <item> EXISTS </item>
- <item> EXPIRE </item>
- <item> EXPLAIN </item>
- <item> EXPLOSION </item>
- <item> EXTENDS </item>
- <item> EXTENT </item>
- <item> EXTENTS </item>
- <item> EXTERNALLY </item>
- <item> FAILED_LOGIN_ATTEMPTS </item>
- <item> FALSE </item>
- <item> FAST </item>
- <item> FILE </item>
- <item> FILTER </item>
- <item> FIRST_ROWS </item>
- <item> FLAGGER </item>
- <item> FLUSH </item>
- <item> FOLLOWING </item>
- <item> FOR </item>
- <item> FORCE </item>
- <item> FOREIGN </item>
- <item> FREELIST </item>
- <item> FREELISTS </item>
- <item> FRESH </item>
- <item> FROM </item>
- <item> FULL </item>
- <item> FUNCTION </item>
- <item> FUNCTIONS </item>
- <item> GENERATED </item>
- <item> GLOBAL </item>
- <item> GLOBALLY </item>
- <item> GLOBAL_NAME </item>
- <item> GRANT </item>
- <item> GROUP </item>
- <item> GROUPS </item>
- <item> HASH </item>
- <item> HASHKEYS </item>
- <item> HAVING </item>
- <item> HEADER </item>
- <item> HEAP </item>
- <item> HIERARCHY </item>
- <item> HOUR </item>
- <item> ID </item>
- <item> IDENTIFIED </item>
- <item> IDENTIFIER </item>
- <item> IDGENERATORS </item>
- <item> IDLE_TIME </item>
- <item> IF </item>
- <item> IMMEDIATE </item>
- <item> IN </item>
- <item> INCLUDING </item>
- <item> INCREMENT </item>
- <item> INCREMENTAL </item>
- <item> INDEX </item>
- <item> INDEXED </item>
- <item> INDEXES </item>
- <item> INDEXTYPE </item>
- <item> INDEXTYPES </item>
- <item> INDICATOR </item>
- <item> INITIAL </item>
- <item> INITIALIZED </item>
- <item> INITIALLY </item>
- <item> INITRANS </item>
- <item> INNER </item>
- <item> INSERT </item>
- <item> INSTANCE </item>
- <item> INSTANCES </item>
- <item> INSTEAD </item>
- <item> INTERMEDIATE </item>
- <item> INTERSECT </item>
- <item> INTERVAL </item>
- <item> INTO </item>
- <item> INVALIDATE </item>
- <item> IS </item>
- <item> ISOLATION </item>
- <item> ISOLATION_LEVEL </item>
- <item> JAVA </item>
- <item> JOIN </item>
- <item> KEEP </item>
- <item> KEY </item>
- <item> KILL </item>
- <item> LABEL </item>
- <item> LAYER </item>
- <item> LEADING </item>
- <item> LEFT </item>
- <item> LESS </item>
- <item> LEVEL </item>
- <item> LIBRARY </item>
- <item> LIKE </item>
- <item> LIMIT </item>
- <item> LINK </item>
- <item> LIST </item>
- <item> LOCAL </item>
- <item> LOCATOR </item>
- <item> LOCK </item>
- <item> LOCKED </item>
- <item> LOGFILE </item>
- <item> LOGGING </item>
- <item> LOGICAL_READS_PER_CALL </item>
- <item> LOGICAL_READS_PER_SESSION </item>
- <item> LOGOFF </item>
- <item> LOGON </item>
- <item> MANAGE </item>
- <item> MANAGED </item>
- <item> MANAGEMENT </item>
- <item> MASTER </item>
- <item> MATERIALIZED </item>
- <item> MAXARCHLOGS </item>
- <item> MAXDATAFILES </item>
- <item> MAXEXTENTS </item>
- <item> MAXINSTANCES </item>
- <item> MAXLOGFILES </item>
- <item> MAXLOGHISTORY </item>
- <item> MAXLOGMEMBERS </item>
- <item> MAXSIZE </item>
- <item> MAXTRANS </item>
- <item> MAXVALUE </item>
- <item> METHOD </item>
- <item> MEMBER </item>
- <item> MERGE </item>
- <item> MINIMIZE </item>
- <item> MINIMUM </item>
- <item> MINEXTENTS </item>
- <item> MINUS </item>
- <item> MINUTE </item>
- <item> MINVALUE </item>
- <item> MODE </item>
- <item> MODIFY </item>
- <item> MONITORING </item>
- <item> MONTH </item>
- <item> MOUNT </item>
- <item> MOVE </item>
- <item> MOVEMENT </item>
- <item> MTS_DISPATCHERS </item>
- <item> MULTISET </item>
- <item> NAMED </item>
- <item> NATURAL </item>
- <item> NEEDED </item>
- <item> NESTED </item>
- <item> NESTED_TABLE_ID </item>
- <item> NETWORK </item>
- <item> NEVER </item>
- <item> NEW </item>
- <item> NEXT </item>
- <item> NLS_CALENDAR </item>
- <item> NLS_CHARACTERSET </item>
- <item> NLS_COMP </item>
- <item> NLS_CURRENCY </item>
- <item> NLS_DATE_FORMAT </item>
- <item> NLS_DATE_LANGUAGE </item>
- <item> NLS_ISO_CURRENCY </item>
- <item> NLS_LANG </item>
- <item> NLS_LANGUAGE </item>
- <item> NLS_NUMERIC_CHARACTERS </item>
- <item> NLS_SORT </item>
- <item> NLS_SPECIAL_CHARS </item>
- <item> NLS_TERRITORY </item>
- <item> NO </item>
- <item> NOARCHIVELOG </item>
- <item> NOAUDIT </item>
- <item> NOCACHE </item>
- <item> NOCOMPRESS </item>
- <item> NOCYCLE </item>
- <item> NOFORCE </item>
- <item> NOLOGGING </item>
- <item> NOMAXVALUE </item>
- <item> NOMINIMIZE </item>
- <item> NOMINVALUE </item>
- <item> NOMONITORING </item>
- <item> NONE </item>
- <item> NOORDER </item>
- <item> NOOVERRIDE </item>
- <item> NOPARALLEL </item>
- <item> NORELY </item>
- <item> NORESETLOGS </item>
- <item> NOREVERSE </item>
- <item> NORMAL </item>
- <item> NOSEGMENT </item>
- <item> NOSORT </item>
- <item> NOT </item>
- <item> NOTHING </item>
- <item> NOVALIDATE </item>
- <item> NOWAIT </item>
- <item> NULL </item>
- <item> NULLS </item>
- <item> OBJNO </item>
- <item> OBJNO_REUSE </item>
- <item> OF </item>
- <item> OFF </item>
- <item> OFFLINE </item>
- <item> OID </item>
- <item> OIDINDEX </item>
- <item> OLD </item>
- <item> ON </item>
- <item> ONLINE </item>
- <item> ONLY </item>
- <item> OPCODE </item>
- <item> OPEN </item>
- <item> OPERATOR </item>
- <item> OPTIMAL </item>
- <item> OPTIMIZER_GOAL </item>
- <item> OPTION </item>
- <item> OR </item>
- <item> ORDER </item>
- <item> ORGANIZATION </item>
- <item> OUT </item>
- <item> OUTER </item>
- <item> OUTLINE </item>
- <item> OVER </item>
- <item> OVERFLOW </item>
- <item> OVERLAPS </item>
- <item> OWN </item>
- <item> PACKAGE </item>
- <item> PACKAGES </item>
- <item> PARALLEL </item>
- <item> PARAMETERS </item>
- <item> PARENT </item>
- <item> PARTITION </item>
- <item> PARTITIONS </item>
- <item> PARTITION_HASH </item>
- <item> PARTITION_RANGE </item>
- <item> PASSWORD </item>
- <item> PASSWORD_GRACE_TIME </item>
- <item> PASSWORD_LIFE_TIME </item>
- <item> PASSWORD_LOCK_TIME </item>
- <item> PASSWORD_REUSE_MAX </item>
- <item> PASSWORD_REUSE_TIME </item>
- <item> PASSWORD_VERIFY_FUNCTION </item>
- <item> PCTFREE </item>
- <item> PCTINCREASE </item>
- <item> PCTTHRESHOLD </item>
- <item> PCTUSED </item>
- <item> PCTVERSION </item>
- <item> PERCENT </item>
- <item> PERMANENT </item>
- <item> PLAN </item>
- <item> PLSQL_DEBUG </item>
- <item> POST_TRANSACTION </item>
- <item> PREBUILT </item>
- <item> PRECEDING </item>
- <item> PREPARE </item>
- <item> PRESERVE </item>
- <item> PRIMARY </item>
- <item> PRIOR </item>
- <item> PRIVATE </item>
- <item> PRIVATE_SGA </item>
- <item> PRIVILEGE </item>
- <item> PRIVILEGES </item>
- <item> PROCEDURE </item>
- <item> PROFILE </item>
- <item> PUBLIC </item>
- <item> PURGE </item>
- <item> QUERY </item>
- <item> QUEUE </item>
- <item> QUOTA </item>
- <item> RANDOM </item>
- <item> RANGE </item>
- <item> RBA </item>
- <item> READ </item>
- <item> READS </item>
- <item> REBUILD </item>
- <item> RECORDS_PER_BLOCK </item>
- <item> RECOVER </item>
- <item> RECOVERABLE </item>
- <item> RECOVERY </item>
- <item> RECYCLE </item>
- <item> REDUCED </item>
- <item> REFERENCES </item>
- <item> REFERENCING </item>
- <item> REFRESH </item>
- <item> RELY </item>
- <item> RENAME </item>
- <item> RESET </item>
- <item> RESETLOGS </item>
- <item> RESIZE </item>
- <item> RESOLVE </item>
- <item> RESOLVER </item>
- <item> RESOURCE </item>
- <item> RESTRICT </item>
- <item> RESTRICTED </item>
- <item> RESUME </item>
- <item> RETURN </item>
- <item> RETURNING </item>
- <item> REUSE </item>
- <item> REVERSE </item>
- <item> REVOKE </item>
- <item> REWRITE </item>
- <item> RIGHT </item>
- <item> ROLE </item>
- <item> ROLES </item>
- <item> ROLLBACK </item>
- <item> ROLLUP </item>
- <item> ROW </item>
- <item> ROWNUM </item>
- <item> ROWS </item>
- <item> RULE </item>
- <item> SAMPLE </item>
- <item> SAVEPOINT </item>
- <item> SCAN </item>
- <item> SCAN_INSTANCES </item>
- <item> SCHEMA </item>
- <item> SCN </item>
- <item> SCOPE </item>
- <item> SD_ALL </item>
- <item> SD_INHIBIT </item>
- <item> SD_SHOW </item>
- <item> SECOND </item>
- <item> SEGMENT </item>
- <item> SEG_BLOCK </item>
- <item> SEG_FILE </item>
- <item> SELECT </item>
- <item> SELECTIVITY </item>
- <item> SEQUENCE </item>
- <item> SERIALIZABLE </item>
- <item> SERVERERROR </item>
- <item> SESSION </item>
- <item> SESSION_CACHED_CURSORS </item>
- <item> SESSIONS_PER_USER </item>
- <item> SET </item>
- <item> SHARE </item>
- <item> SHARED </item>
- <item> SHARED_POOL </item>
- <item> SHRINK </item>
- <item> SHUTDOWN </item>
- <item> SINGLETASK </item>
- <item> SIZE </item>
- <item> SKIP </item>
- <item> SKIP_UNUSABLE_INDEXES </item>
- <item> SNAPSHOT </item>
- <item> SOME </item>
- <item> SORT </item>
- <item> SOURCE </item>
- <item> SPECIFICATION </item>
- <item> SPLIT </item>
- <item> SQL_TRACE </item>
- <item> STANDBY </item>
- <item> START </item>
- <item> STARTUP </item>
- <item> STATEMENT_ID </item>
- <item> STATISTICS </item>
- <item> STATIC </item>
- <item> STOP </item>
- <item> STORAGE </item>
- <item> STORE </item>
- <item> STRUCTURE </item>
- <item> SUBPARTITION </item>
- <item> SUBPARTITIONS </item>
- <item> SUCCESSFUL </item>
- <item> SUMMARY </item>
- <item> SUSPEND </item>
- <item> SWITCH </item>
- <item> SYS_OP_BITVEC </item>
- <item> SYS_OP_ENFORCE_NOT_NULL$ </item>
- <item> SYS_OP_NOEXPAND </item>
- <item> SYS_OP_NTCIMG$ </item>
- <item> SYNONYM </item>
- <item> SYSDBA </item>
- <item> SYSOPER </item>
- <item> SYSTEM </item>
- <item> TABLE </item>
- <item> TABLES </item>
- <item> TABLESPACE </item>
- <item> TABLESPACE_NO </item>
- <item> TABNO </item>
- <item> TEMPFILE </item>
- <item> TEMPORARY </item>
- <item> THAN </item>
- <item> THE </item>
- <item> THEN </item>
- <item> THREAD </item>
- <item> THROUGH </item>
- <item> TIMEOUT </item>
- <item> TIMEZONE_HOUR </item>
- <item> TIMEZONE_MINUTE </item>
- <item> TIME_ZONE </item>
- <item> TO </item>
- <item> TOPLEVEL </item>
- <item> TRACE </item>
- <item> TRACING </item>
- <item> TRAILING </item>
- <item> TRANSACTION </item>
- <item> TRANSITIONAL </item>
- <item> TRIGGER </item>
- <item> TRIGGERS </item>
- <item> TRUE </item>
- <item> TRUNCATE </item>
- <item> TYPE </item>
- <item> TYPES </item>
- <item> UNARCHIVED </item>
- <item> UNBOUND </item>
- <item> UNBOUNDED </item>
- <item> UNDO </item>
- <item> UNIFORM </item>
- <item> UNION </item>
- <item> UNIQUE </item>
- <item> UNLIMITED </item>
- <item> UNLOCK </item>
- <item> UNRECOVERABLE </item>
- <item> UNTIL </item>
- <item> UNUSABLE </item>
- <item> UNUSED </item>
- <item> UPD_INDEXES </item>
- <item> UPDATABLE </item>
- <item> UPDATE </item>
- <item> UPPPER </item>
- <item> USAGE </item>
- <item> USE </item>
- <item> USE_STORED_OUTLINES </item>
- <item> USER_DEFINED </item>
- <item> USING </item>
- <item> VALIDATE </item>
- <item> VALIDATION </item>
- <item> VALUES </item>
- <item> VIEW </item>
- <item> WHEN </item>
- <item> WHENEVER </item>
- <item> WHERE </item>
- <item> WITH </item>
- <item> WITHOUT </item>
- <item> WORK </item>
- <item> WRITE </item>
- <item> YEAR </item>
- <item> ZONE </item>
- </list>
- <list name="operators">
- <item> + </item>
- <item> - </item>
- <item> * </item>
- <item> / </item>
- <item> || </item>
- <item> = </item>
- <item> != </item>
- <item> &lt;&gt; </item>
- <item> &lt; </item>
- <item> &lt;= </item>
- <item> &gt; </item>
- <item> &gt;= </item>
- <item> ~= </item>
- <item> ^= </item>
- <item> := </item>
- <item> =&gt; </item>
- <item> ** </item>
- <item> .. </item>
- </list>
- <list name="functions">
- <item> ABS </item>
- <item> ACOS </item>
- <item> ADD_MONTHS </item>
- <item> ASCII </item>
- <item> ASCIISTR </item>
- <item> ASIN </item>
- <item> ATAN </item>
- <item> ATAN2 </item>
- <item> AVG </item>
- <item> BFILENAME </item>
- <item> BIN_TO_NUM </item>
- <item> BITAND </item>
- <item> CAST </item>
- <item> CEIL </item>
- <item> CHARTOROWID </item>
- <item> CHR </item>
- <item> COALESCE </item>
- <item> COMPOSE </item>
- <item> CONCAT </item>
- <item> CONVERT </item>
- <item> CORR </item>
- <item> COS </item>
- <item> COSH </item>
- <item> COUNT </item>
- <item> COVAR_POP </item>
- <item> COVAR_SAMP </item>
- <item> CUME_DIST </item>
- <item> CURRENT_DATE </item>
- <item> CURRENT_TIMESTAMP </item>
- <item> DBTIMEZONE </item>
- <item> DECODE </item>
- <item> DECOMPOSE </item>
- <item> DENSE_RANK </item>
- <item> DEREF </item>
- <item> DUMP </item>
- <item> EMPTY_BLOB </item>
- <item> EMPTY_CLOB </item>
- <item> EXISTSNODE </item>
- <item> EXP </item>
- <item> EXTRACT </item>
- <item> FIRST </item>
- <item> FIRST_VALUE </item>
- <item> FLOOR </item>
- <item> FROM_TZ </item>
- <item> GREATEST </item>
- <item> GROUP_ID </item>
- <item> GROUPING </item>
- <item> GROUPING_ID </item>
- <item> HEXTORAW </item>
- <item> INITCAP </item>
- <item> INSTR </item>
- <item> INSTRB </item>
- <item> LAG </item>
- <item> LAST </item>
- <item> LAST_DAY </item>
- <item> LAST_VALUE </item>
- <item> LEAD </item>
- <item> LEAST </item>
- <item> LENGTH </item>
- <item> LENGTHB </item>
- <item> LN </item>
- <item> LOCALTIMESTAMP </item>
- <item> LOG </item>
- <item> LOWER </item>
- <item> LPAD </item>
- <item> LTRIM </item>
- <item> MAKE_REF </item>
- <item> MAX </item>
- <item> MIN </item>
- <item> MOD </item>
- <item> MONTHS_BETWEEN </item>
- <item> NCHR </item>
- <item> NEW_TIME </item>
- <item> NEXT_DAY </item>
- <item> NLS_CHARSET_DECL_LEN </item>
- <item> NLS_CHARSET_ID </item>
- <item> NLS_CHARSET_NAME </item>
- <item> NLS_INITCAP </item>
- <item> NLS_LOWER </item>
- <item> NLS_UPPER </item>
- <item> NLSSORT </item>
- <item> NTILE </item>
- <item> NULLIF </item>
- <item> NUMTODSINTERVAL </item>
- <item> NUMTOYMINTERVAL </item>
- <item> NVL </item>
- <item> NVL2 </item>
- <item> PERCENT_RANK </item>
- <item> PERCENTILE_CONT </item>
- <item> PERCENTILE_DISC </item>
- <item> POWER </item>
- <item> RANK </item>
- <item> RATIO_TO_REPORT </item>
- <item> RAWTOHEX </item>
- <item> REF </item>
- <item> REFTOHEX </item>
- <item> REGR_SLOPE </item>
- <item> REGR_INTERCEPT </item>
- <item> REGR_COUNT </item>
- <item> REGR_R2 </item>
- <item> REGR_AVGX </item>
- <item> REGR_AVGY </item>
- <item> REGR_SXX </item>
- <item> REGR_SYY </item>
- <item> REGR_SXY </item>
- <item> REPLACE </item>
- <item> ROUND </item>
- <item> ROW_NUMBER </item>
- <item> ROWIDTOCHAR </item>
- <item> ROWIDTONCHAR </item>
- <item> RPAD </item>
- <item> RTRIM </item>
- <item> SESSIONTIMEZONE </item>
- <item> SIGN </item>
- <item> SIN </item>
- <item> SINH </item>
- <item> SOUNDEX </item>
- <item> SUBSTR </item>
- <item> SQRT </item>
- <item> STDDEV </item>
- <item> STDDEV_POP </item>
- <item> STDDEV_SAMP </item>
- <item> SUBSTR </item>
- <item> SUBSTRB </item>
- <item> SUM </item>
- <item> SYS_CONNECT_BY_PATH </item>
- <item> SYS_CONTEXT </item>
- <item> SYS_DBURIGEN </item>
- <item> SYS_EXTRACT_UTC </item>
- <item> SYS_GUID </item>
- <item> SYS_TYPEID </item>
- <item> SYS_XMLAGG </item>
- <item> SYS_XMLGEN </item>
- <item> SYSDATE </item>
- <item> SYSTIMESTAMP </item>
- <item> TAN </item>
- <item> TANH </item>
- <item> TO_CHAR </item>
- <item> TO_CLOB </item>
- <item> TO_DATE </item>
- <item> TO_DSINTERVAL </item>
- <item> TO_LOB </item>
- <item> TO_MULTI_BYTE </item>
- <item> TO_NCHAR </item>
- <item> TO_NCLOB </item>
- <item> TO_NUMBER </item>
- <item> TO_SINGLE_BYTE </item>
- <item> TO_TIMESTAMP </item>
- <item> TO_TIMESTAMP_TZ </item>
- <item> TO_YMINTERVAL </item>
- <item> TRANSLATE </item>
- <item> TREAT </item>
- <item> TRIM </item>
- <item> TRUNC </item>
- <item> TZ_OFFSET </item>
- <item> UID </item>
- <item> UNISTR </item>
- <item> UPPER </item>
- <item> USER </item>
- <item> USERENV </item>
- <item> VALUE </item>
- <item> VAR_POP </item>
- <item> VAR_SAMP </item>
- <item> VARIANCE </item>
- <item> VSIZE </item>
- <item> WIDTH_BUCKET </item>
- </list>
- <list name="types">
- <item> ANYDATA </item>
- <item> ANYDATASET </item>
- <item> ANYTYPE </item>
- <item> ARRAY </item>
- <item> BFILE </item>
- <item> BINARY_INTEGER </item>
- <item> BLOB </item>
- <item> BOOLEAN </item>
- <item> CFILE </item>
- <item> CHAR </item>
- <item> CHARACTER </item>
- <item> CLOB </item>
- <item> DATE </item>
- <item> DBURITYPE </item>
- <item> DEC </item>
- <item> DECIMAL </item>
- <item> DOUBLE </item>
- <item> FLOAT </item>
- <item> FLOB </item>
- <item> HTTPURITYPE </item>
- <item> INT </item>
- <item> INTEGER </item>
- <item> LOB </item>
- <item> LONG </item>
- <item> MLSLABEL </item>
- <item> NATIONAL </item>
- <item> NCHAR </item>
- <item> NCLOB </item>
- <item> NUMBER </item>
- <item> NUMERIC </item>
- <item> NVARCHAR </item>
- <item> NVARCHAR2 </item>
- <item> OBJECT </item>
- <item> PLS_INTEGER </item>
- <item> PRECISION </item>
- <item> RAW </item>
- <item> RECORD </item>
- <item> REAL </item>
- <item> ROWID </item>
- <item> SINGLE </item>
- <item> SMALLINT </item>
- <item> TIMESTAMP </item>
- <item> TIME </item>
- <item> URIFACTORYTYPE </item>
- <item> URITYPE </item>
- <item> UROWID </item>
- <item> VARCHAR </item>
- <item> VARCHAR2 </item>
- <item> VARYING </item>
- <item> VARRAY </item>
- <item> XMLTYPE </item>
- </list>
- <contexts>
- <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
- <keyword attribute="Keyword" String="keywords" context="#stay"/>
- <keyword attribute="Operator" String="operators" context="#stay"/>
- <keyword attribute="Function" String="functions" context="#stay"/>
- <keyword attribute="Data Type" String="types" context="#stay"/>
- <RegExpr attribute="Data Type" String="%[Bb][Uu][Ll][Kk]_[Ee][Xx][Cc][Ee][Pp][Tt][Ii][Oo][Nn][Ss]\b" context="#stay"/>
- <RegExpr attribute="Data Type" String="%[Bb][Uu][Ll][Kk]_[Rr][Oo][Ww][Cc][Oo][Uu][Nn][Tt]\b" context="#stay"/>
- <RegExpr attribute="Data Type" String="%[Ff][Oo][Uu][Nn][Dd]\b" context="#stay"/>
- <RegExpr attribute="Data Type" String="%[Ii][Ss][Oo][Pp][Ee][Nn]\b" context="#stay"/>
- <RegExpr attribute="Data Type" String="%[Nn][Oo][Tt][Ff][Oo][Uu][Nn][Dd]\b" context="#stay"/>
- <RegExpr attribute="Data Type" String="%[Rr][Oo][Ww][Cc][Oo][Uu][Nn][Tt]\b" context="#stay"/>
- <RegExpr attribute="Data Type" String="%[Rr][Oo][Ww][Tt][Yy][Pp][Ee]\b" context="#stay"/>
- <RegExpr attribute="Data Type" String="%[Tt][Yy][Pp][Ee]\b" context="#stay"/>
- <Float attribute="Float" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- <DetectChar attribute="String" context="String literal" char="'"/>
- <Detect2Chars attribute="Comment" context="Singleline PL/SQL-style comment" char="-" char1="-"/>
- <Detect2Chars attribute="Comment" context="Multiline C-style comment" char="/" char1="*"/>
- <RegExpr attribute="Comment" context="SQL*Plus remark directive" String="^[Rr][Ee][Mm]\b"/>
- <DetectChar attribute="Identifier" context="User-defined identifier" char="&quot;"/>
- <RegExpr attribute="External Variable" context="#stay" String="(:|&amp;&amp;?)\w+"/>
- <RegExpr attribute="Symbol" context="#stay" String="^/$"/>
- <RegExpr attribute="Preprocessor" context="SQL*Plus directive to include file" String="^@@?[^@ \t\r\n]"/>
- </context>
- <context name="String literal" attribute="String" lineEndContext="#stay">
- <HlCStringChar attribute="String Char" context="#stay"/>
- <RegExpr attribute="External Variable" context="#stay" String="&amp;&amp;?\w+"/>
- <DetectChar attribute="String" context="#pop" char="'"/>
- </context>
- <context name="Singleline PL/SQL-style comment" attribute="Comment" lineEndContext="#pop"/>
- <context name="Multiline C-style comment" attribute="Comment" lineEndContext="#stay">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/"/>
- </context>
- <context name="SQL*Plus remark directive" attribute="Comment" lineEndContext="#pop"/>
- <context name="User-defined identifier" attribute="Identifier" lineEndContext="#pop">
- <DetectChar attribute="Identifier" context="#pop" char="&quot;"/>
- </context>
- <context name="SQL*Plus directive to include file" attribute="Preprocessor" lineEndContext="#pop"/>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Operator" defStyleNum="dsNormal"/>
- <itemData name="Function" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Identifier" defStyleNum="dsOthers"/>
- <itemData name="External Variable" defStyleNum="dsChar"/>
- <itemData name="Symbol" defStyleNum="dsChar"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="--"/>
- <comment name="multiLine" start="/*" end="*/"/>
- </comments>
- <keywords casesensitive="0"/>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-
-<!-- Authors: Alexander Dederer & JM. Philippe -->
-<!-- Copyright: BSD copyright & Irsid - Arcelor Innovation R&D -->
-<!-- Ported to Kate 2.0/ KWrite 4.0 by Joseph Wenninger (Updated by Simon Robins)-->
-
-<language name="Tcl/Tk" version="1.05" kateversion="2.1" section="Scripts" extensions="*.tcl;*.tk" mimetype="text/x-tcl">
- <highlighting>
- <list name="keywords">
- <item> after </item>
- <item> append </item>
- <item> AppleScript </item>
- <item> argv </item>
- <item> argc </item>
- <item> array </item>
- <item> auto_execk </item>
- <item> auto_load </item>
- <item> auto_mkindex </item>
- <item> auto_path </item>
- <item> auto_reset </item>
- <item> beep </item>
- <item> bell </item>
- <item> binary </item>
- <item> bind </item>
- <item> bindtags </item>
- <item> bgerror </item>
- <item> break </item>
- <item> button </item>
- <item> canvas </item>
- <item> case </item>
- <item> catch </item>
- <item> cd </item>
- <item> checkbutton </item>
- <item> clipboard </item>
- <item> clock </item>
- <item> close </item>
- <item> concat </item>
- <item> console </item>
- <item> continue </item>
- <item> dde </item>
- <item> destroy </item>
- <item> else </item>
- <item> elseif </item>
- <item> encoding </item>
- <item> entry </item>
- <item> env </item>
- <item> eof </item>
- <item> error </item>
- <item> errorCode </item>
- <item> errorInfo </item>
- <item> eval </item>
- <item> event </item>
- <item> exec </item>
- <item> exit </item>
- <item> expr </item>
- <item> fblocked </item>
- <item> fconfigure </item>
- <item> fcopy </item>
- <item> file </item>
- <item> fileevent </item>
- <item> flush </item>
- <item> focus </item>
- <item> font </item>
- <item> for </item>
- <item> foreach </item>
- <item> format </item>
- <item> frame </item>
- <item> gets </item>
- <item> glob </item>
- <item> global </item>
- <item> grab </item>
- <item> grid </item>
- <item> history </item>
- <item> if </item>
- <item> image </item>
- <item> incr </item>
- <item> info </item>
- <item> interp </item>
- <item> join </item>
- <item> label </item>
- <item> lappend </item>
- <item> lindex </item>
- <item> linsert </item>
- <item> list </item>
- <item> listbox </item>
- <item> llength </item>
- <item> load </item>
- <item> lower </item>
- <item> lrange </item>
- <item> lreplace </item>
- <item> lsearch </item>
- <item> lsort </item>
- <item> menu </item>
- <item> menubutton </item>
- <item> message </item>
- <item> namespace </item>
- <item> open </item>
- <item> option </item>
- <item> OptProc </item>
- <item> pack </item>
- <item> package </item>
- <item> parray </item>
- <item> pid </item>
- <item> place </item>
- <item> pkg_mkindex </item>
- <item> proc </item>
- <item> puts </item>
- <item> pwd </item>
- <item> radiobutton </item>
- <item> raise </item>
- <item> read </item>
- <item> regexp </item>
- <item> registry </item>
- <item> regsub </item>
- <item> rename </item>
- <item> resource </item>
- <item> return </item>
- <item> scale </item>
- <item> scan </item>
- <item> scrollbar </item>
- <item> seek </item>
- <item> selection </item>
- <item> send </item>
- <item> set </item>
- <item> socket </item>
- <item> source </item>
- <item> split </item>
- <item> string </item>
- <item> subst </item>
- <item> switch </item>
- <item> tclLog </item>
- <item> tcl_endOfWord </item>
- <item> tcl_findLibrary </item>
- <item> tcl_library </item>
- <item> tcl_patchLevel </item>
- <item> tcl_platform </item>
- <item> tcl_precision </item>
- <item> tcl_rcFileName </item>
- <item> tcl_rcRsrcName </item>
- <item> tcl_startOfNextWord </item>
- <item> tcl_startOfPreviousWord </item>
- <item> tcl_traceCompile </item>
- <item> tcl_traceExec </item>
- <item> tcl_version </item>
- <item> tcl_wordBreakAfter </item>
- <item> tcl_wordBreakBefore </item>
- <item> tell </item>
- <item> text </item>
- <item> time </item>
- <item> tk </item>
- <item> tkTabToWindow </item>
- <item> tkwait </item>
- <item> tk_chooseColor </item>
- <item> tk_chooseDirectory </item>
- <item> tk_focusFollowMouse </item>
- <item> tk_focusNext </item>
- <item> tk_focusPrev </item>
- <item> tk_getOpenFile </item>
- <item> tk_getSaveFile </item>
- <item> tk_library </item>
- <item> tk_messageBox </item>
- <item> tk_optionMenu </item>
- <item> tk_patchLevel </item>
- <item> tk_popup </item>
- <item> tk_strictMotif </item>
- <item> tk_version </item>
- <item> toplevel </item>
- <item> trace </item>
- <item> unknown </item>
- <item> unset </item>
- <item> update </item>
- <item> uplevel </item>
- <item> upvar </item>
- <item> variable </item>
- <item> vwait </item>
- <item> while </item>
- <item> winfo </item>
- <item> wm </item>
- </list>
-
- <list name="keywords-opt">
- <item> add </item>
- <item> args </item>
- <item> atime </item>
- <item> attributes </item>
- <item> body </item>
- <item> bytelength </item>
- <item> cancel </item>
- <item> channels </item>
- <item> clicks </item>
- <item> cmdcount </item>
- <item> commands </item>
- <item> compare </item>
- <item> complete </item>
- <item> convertfrom </item>
- <item> convertto </item>
- <item> copy </item>
- <item> default </item>
- <item> delete </item>
- <item> dirname </item>
- <item> equal </item>
- <item> executable </item>
- <item> exists </item>
- <item> extension </item>
- <item> first </item>
- <item> forget </item>
- <item> format </item>
- <item> functions </item>
- <item> globals </item>
- <item> hostname </item>
- <item> idle </item>
- <item> ifneeded </item>
- <item> index </item>
- <item> info </item>
- <item> is </item>
- <item> isdirectory </item>
- <item> isfile </item>
- <item> join </item>
- <item> last </item>
- <item> length </item>
- <item> level </item>
- <item> library </item>
- <item> link </item>
- <item> loaded </item>
- <item> locals </item>
- <item> lstat </item>
- <item> map </item>
- <item> match </item>
- <item> mkdir </item>
- <item> mtime </item>
- <item> nameofexecutable </item>
- <item> names </item>
- <item> nativename </item>
- <item> normalize </item>
- <item> number </item>
- <item> owned </item>
- <item> patchlevel </item>
- <item> pathtype </item>
- <item> present </item>
- <item> procs </item>
- <item> provide </item>
- <item> range </item>
- <item> readable </item>
- <item> readlink </item>
- <item> remove </item>
- <item> rename </item>
- <item> repeat </item>
- <item> replace </item>
- <item> require </item>
- <item> rootname </item>
- <item> scan </item>
- <item> script </item>
- <item> seconds </item>
- <item> separator </item>
- <item> sharedlibextension </item>
- <item> size </item>
- <item> split </item>
- <item> stat </item>
- <item> system </item>
- <item> tail </item>
- <item> tclversion </item>
- <item> tolower </item>
- <item> totitle </item>
- <item> toupper </item>
- <item> trim </item>
- <item> trimleft </item>
- <item> trimright </item>
- <item> type </item>
- <item> unknown </item>
- <item> variable </item>
- <item> vars </item>
- <item> vcompare </item>
- <item> vdelete </item>
- <item> versions </item>
- <item> vinfo </item>
- <item> volumes </item>
- <item> vsatisfies </item>
- <item> wordend </item>
- <item> wordstart </item>
- <item> writable </item>
-
- <item> activate </item>
- <item> actual </item>
- <item> addtag </item>
- <item> append </item>
- <item> appname </item>
- <item> aspect </item>
- <item> atom </item>
- <item> atomname </item>
- <item> bbox </item>
- <item> bind </item>
- <item> broadcast </item>
- <item> canvasx </item>
- <item> canvasy </item>
- <item> caret </item>
- <item> cells </item>
- <item> cget </item>
- <item> children </item>
- <item> class </item>
- <item> clear </item>
- <item> client </item>
- <item> clone </item>
- <item> colormapfull </item>
- <item> colormapwindows </item>
- <item> command </item>
- <item> configure </item>
- <item> containing </item>
- <item> coords </item>
- <item> create </item>
- <item> current </item>
- <item> curselection </item>
- <item> dchars </item>
- <item> debug </item>
- <item> deiconify </item>
- <item> delta </item>
- <item> depth </item>
- <item> deselect </item>
- <item> dlineinfo </item>
- <item> dtag </item>
- <item> dump </item>
- <item> edit </item>
- <item> entrycget </item>
- <item> entryconfigure </item>
- <item> families </item>
- <item> find </item>
- <item> flash </item>
- <item> focus </item>
- <item> focusmodel </item>
- <item> fpixels </item>
- <item> fraction </item>
- <item> frame </item>
- <item> generate </item>
- <item> geometry </item>
- <item> get </item>
- <item> gettags </item>
- <item> grid </item>
- <item> group </item>
- <item> handle </item>
- <item> height </item>
- <item> hide </item>
- <item> iconbitmap </item>
- <item> iconify </item>
- <item> iconmask </item>
- <item> iconname </item>
- <item> iconposition </item>
- <item> iconwindow </item>
- <item> icursor </item>
- <item> id </item>
- <item> identify </item>
- <item> image </item>
- <item> insert </item>
- <item> interps </item>
- <item> inuse </item>
- <item> invoke </item>
- <item> ismapped </item>
- <item> itemcget </item>
- <item> itemconfigure </item>
- <item> keys </item>
- <item> lower </item>
- <item> manager </item>
- <item> mark </item>
- <item> maxsize </item>
- <item> measure </item>
- <item> metrics </item>
- <item> minsize </item>
- <item> move </item>
- <item> name </item>
- <item> nearest </item>
- <item> overrideredirect </item>
- <item> own </item>
- <item> panecget </item>
- <item> paneconfigure </item>
- <item> panes </item>
- <item> parent </item>
- <item> pathname </item>
- <item> pixels </item>
- <item> pointerx </item>
- <item> pointerxy </item>
- <item> pointery </item>
- <item> positionfrom </item>
- <item> post </item>
- <item> postcascade </item>
- <item> postscript </item>
- <item> protocol </item>
- <item> proxy </item>
- <item> raise </item>
- <item> release </item>
- <item> reqheight </item>
- <item> reqwidth </item>
- <item> resizable </item>
- <item> rgb </item>
- <item> rootx </item>
- <item> rooty </item>
- <item> scale </item>
- <item> scaling </item>
- <item> screen </item>
- <item> screencells </item>
- <item> screendepth </item>
- <item> screenheight </item>
- <item> screenmmheight </item>
- <item> screenmmwidth </item>
- <item> screenvisual </item>
- <item> screenwidth </item>
- <item> search </item>
- <item> see </item>
- <item> select </item>
- <item> selection </item>
- <item> server </item>
- <item> set </item>
- <item> show </item>
- <item> sizefrom </item>
- <item> stackorder </item>
- <item> state </item>
- <item> status </item>
- <item> tag </item>
- <item> title </item>
- <item> toplevel </item>
- <item> transient </item>
- <item> types </item>
- <item> unpost </item>
- <item> useinputmethods </item>
- <item> validate </item>
- <item> values </item>
- <item> viewable </item>
- <item> visual </item>
- <item> visualid </item>
- <item> visualsavailable </item>
- <item> vrootheight </item>
- <item> vrootwidth </item>
- <item> vrootx </item>
- <item> vrooty </item>
- <item> width </item>
- <item> window </item>
- <item> windowingsystem </item>
- <item> withdraw </item>
- <item> x </item>
- <item> xview </item>
- <item> y </item>
- </list>
-
- <contexts>
- <context name = "Base" attribute = "Normal Text" lineEndContext="#stay">
- <RegExpr attribute="Region Marker" context="#stay" String="#\s*BEGIN.*$" beginRegion="region"/>
- <RegExpr attribute="Region Marker" context="#stay" String="#\s*END.*$" endRegion="region"/>
- <keyword String = "keywords" attribute = "Keyword" context="#stay"/>
- <keyword String = "keywords-opt" attribute = "Parameter" context="#stay"/>
- <Float attribute = "Float" context="#stay"/>
- <Int attribute ="Decimal" context="#stay"/>
- <RegExpr String = "\W-\w+" attribute = "Parameter" content="#stay"/>
- <RegExpr String = "\$(::)?[\S\D]\w+" attribute = "Variable" content="#stay"/>
- <RegExpr String = "[^\\]&quot;&quot;" attribute = "String" context="#stay"/>
- <RegExpr String = "[^\\]&quot;" attribute = "String" context="String"/>
- <RegExpr String= "(^|[^\\])#.*$" attribute = "Comment" context="#stay"/>
- <DetectChar char = "{" attribute = "Keyword" context="#stay" beginRegion="block"/>
- <DetectChar char = "}" attribute = "Keyword" context="#stay" endRegion="block"/>
- <DetectChar char = "[" attribute = "Keyword" context="#stay"/>
- <DetectChar char = "]" attribute = "Keyword" context="#stay"/>
- <RegExpr String = "\\$" attribute = "Keyword" context="#stay"/>
- </context>
-
- <context name = "String" attribute = "String" lineEndContext="#stay">
- <RegExpr String="\\." attribute = "Char" context = "#stay"/>
- <DetectChar char="&quot;" attribute = "String" context = "#pop"/>
- </context>
- </contexts>
-
- <itemDatas>
- <itemData name = "Normal Text" defStyleNum = "dsNormal"/>
- <itemData name = "Keyword" defStyleNum = "dsKeyword"/>
- <itemData name = "Decimal" defStyleNum = "dsDecVal"/>
- <itemData name = "Float" defStyleNum = "dsFloat"/>
- <itemData name = "String" defStyleNum = "dsString"/>
- <itemData name = "Comment" defStyleNum = "dsComment"/>
- <itemData name = "Parameter" defStyleNum = "dsOthers"/>
- <itemData name = "Variable" defStyleNum = "dsDataType"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="Region Marker" defStyleNum="dsNormal" color="#0000ff"/>
- </itemDatas>
-
- <general>
- <keywords casesensitive="1"/>
- </general>
-
- </highlighting>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="UnrealScript" version="0.8" kateversion="2.2" section="Games" extensions="*.uc" mimetype="text/x-uscript">
- <highlighting>
- <list name="keywords">
- <item> break </item>
- <item> continue </item>
- <item> if </item>
- <item> else </item>
- <item> switch </item>
- <item> while </item>
- <item> for </item>
- <item> do </item>
- <item> foreach </item>
- <item> true </item>
- <item> false </item>
- <item> null </item>
- <item> new </item>
- <item> instanceof </item>
- <item> state </item>
- <item> auto </item>
- <item> exec </item>
- <item> function </item>
- <item> defaultproperties </item>
- <item> native </item>
- <item> noexport</item>
- <item> var </item>
- <item> out </item>
- <item> local </item>
- <item> event </item>
- <item> return </item>
- <item> static </item>
- <item> Static </item>
- <item> synchronized </item>
- <item> transient </item>
- <item> volatile </item>
- <item> final </item>
- <item> throws </item>
- <item> extends </item>
- <item> expands </item>
- <item> public </item>
- <item> protected </item>
- <item> private </item>
- <item> abstract </item>
- <item> case </item>
- <item> default </item>
- <item> final </item>
- <item> simulated </item>
- <item> Dot </item>
- <item> nativereplication </item>
- <item> replication </item>
- <item> unreliable </item>
- <item> reliable </item>
- <item> ignores </item>
- <item> localized </item>
- <item> latent </item>
- <item> singular </item>
- <item> Cross </item>
- <item> config </item>
- <item> enum </item>
- <item> struct </item>
- <item> operator </item>
- <item> preoperator </item>
- <item> postoperator </item>
- <item> iterator </item>
- <item> coerce </item>
- <item> optional </item>
- <item> const </item>
- <item> editconst </item>
- <item> array </item>
- <item> export </item>
- <item> editinline </item>
- <item> editinlinenew </item>
- <item> editinlineuse </item>
- <item> cpptext </item>
- <item> placeable </item>
- <item> virtual </item>
- <item> hidecategories </item>
- <item> super </item>
- <item> global </item>
- <item> none </item>
- <item> self </item>
- </list>
-
- <list name="types">
- <item> boolean </item>
- <item> char </item>
- <item> byte </item>
- <item> short </item>
- <item> int </item>
- <item> long </item>
- <item> float </item>
- <item> double </item>
- <item> void </item>
- <item> Pawn </item>
- <item> sound </item>
- <item> ipaddr </item>
- <item> ELightType </item>
- <item> actor </item>
- <item> ammo </item>
- <item> bool </item>
- <item> vector </item>
- <item> rotator </item>
- <item> name </item>
- <item> string </item>
- <item> object </item>
- <item> plane </item>
- <item> staticmesh </item>
- <item> package </item>
- <item> color </item>
- <item> coords </item>
- <item> material </item>
- <item> class </item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <Float attribute="Float" context="#stay">
- <AnyChar String="fF" attribute="Float" context="#stay"/>
- </Float>
- <HlCOct attribute="Octal" context="#stay"/>
- <HlCHex attribute="Hex" context="#stay"/>
- <Int attribute="Decimal" context="#stay">
- <StringDetect attribute="Decimal" context="#stay" String="ULL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LUL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LLU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="UL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LU" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="LL" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="U" insensitive="TRUE"/>
- <StringDetect attribute="Decimal" context="#stay" String="L" insensitive="TRUE"/>
- </Int>
- <HlCChar attribute="Char" context="#stay"/>
- <RegExpr attribute="Decimal" context="#stay" String="//BEGIN.*$" beginRegion="Region1"/>
- <RegExpr attribute="Decimal" context="#stay" String="//END.*$" endRegion="Region1"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <DetectChar attribute="String" context="String" char="&#39;"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*" beginRegion="Comment"/>
- <DetectChar attribute="Normal Text" context="#stay" char="{" beginRegion="Brace1"/>
- <DetectChar attribute="Normal Text" context="#stay" char="}" endRegion="Brace1"/>
- <AnyChar attribute="Symbol" context="#stay" String="!%&amp;()+,-&lt;=&gt;?[]^{|}~"/>
- <RegExpr attribute="Preprocessor" context="Preprocessor" insensitive="TRUE" String="#exec"/>
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- <DetectChar attribute="String" context="#pop" char="&#39;"/>
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Commentar 1"/>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar 2">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" endRegion="Comment"/>
- </context>
- <context attribute="Preprocessor" lineEndContext="#pop" name="Preprocessor">
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//"/>
- <comment name="multiLine" start="/*" end="*/"/>
- </comments>
- <keywords casesensitive="0" additionalDeliminator="&quot;&#39;"/>
- </general>
-</language>
-
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Velocity" version="1.03" kateversion="2.1" section="Scripts"
- extensions="*.vm;" mimetype="text/x-velocity-src;text/x-vm-src"
- author="John Christopher (John@animalsinneed.net)" license="">
- <highlighting>
- <list name="keywords">
- <item> #set </item>
- <item> #foreach </item>
- <item> #end </item>
- <item> #if </item>
- <item> #else </item>
- <item> #elseif </item>
- <item> #parse</item>
- <item>#macro</item>
- <item>#stop</item>
- <item>#include</item>
- </list>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Keyword">
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <RegExpr attribute="Variable" context="#stay" String="\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\.\-]*(\[[a-zA-Z0-9_]*\])*" />
- <RegExpr attribute="Variable" context="#stay" String="\$\{[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\.\-]*(\[[a-zA-Z0-9_]*\])*\}" />
- <RegExpr attribute="Variable" context="#stay" String="\$!\{[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\.\-]*(\[[a-zA-Z0-9_]*\])*\}." />
- <RegExpr attribute="Variable" context="#stay" String="\{\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\.\-]*(\[([0-9]*|&quot;[a-zA-Z_]*&quot;)|'[a-zA-Z_]*'|\])*(->[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\[[a-zA-Z0-9_]*\])*(\[([0-9]*|&quot;[a-zA-Z_]*&quot;)|'[a-zA-Z_]*'|\])*)*\}" />
- <RegExpr attribute="Properties" context="#stay" String="[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\-]*(\[[a-zA-Z0-9_]*\])*\.[a-zA-Z0-9_\x7f-\xff\-]*" />
- <AnyChar attribute="Other" context="#stay" String=" ( ) , [ ] " />
- <Detect2Chars attribute="Comment" context="singleline comment" char="#" char1="#" />
- <Detect2Chars attribute="Comment" context="multilinecomment" char="#" char1="&#42;" />
- </context>
- <context attribute="Comment" name="singleline comment" lineEndContext="#pop">
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="multilinecomment" >
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="#" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="Variable" defStyleNum="dsKeyword" color="#5555FF" selColor="#ffffff" bold="0" italic="0" />
- <itemData name="Other" defStyleNum="dsOther" />
- <itemData name="Properties" defStyleNum="dsNormal" color="#8AC6FF" selColor="#ffffff" bold="0" italic="1"/>
- <itemData name="Comment" defStyleNum="dsComment" />
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="##" />
- <comment name="multiLine" start="#*" end="*#" />
- </comments>
- <keywords casesensitive="1" weakDeliminator="+"/>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="Verilog" version="1.05" kateversion="2.1" section="Sources"
- extensions="*.v;*.V;*.vl" mimetype="text/x-verilog-src"
- author="Yevgen Voronenko (ysv22@drexel.edu)" license="">
- <highlighting>
- <list name="keywords">
- <item> module </item>
- <item> macromodule </item>
- <item> endmodule </item>
- <item> task </item>
- <item> endtask </item>
- <item> function </item>
- <item> endfunction </item>
- <item> table </item>
- <item> endtable </item>
- <item> specify </item>
- <item> specparam </item>
- <item> endspecify </item>
- <item> case </item>
- <item> casex </item>
- <item> casez </item>
- <item> endcase </item>
- <item> fork </item>
- <item> join </item>
-
- <item> defparam </item>
- <item> default </item>
- <item> begin </item>
- <item> end </item>
- <item> if </item>
- <item> ifnone </item>
- <item> else </item>
- <item> forever </item>
- <item> while </item>
- <item> for </item>
- <item> wait </item>
- <item> repeat </item>
- <item> disable </item>
-
- <item> assign </item>
- <item> deassign </item>
- <item> force </item>
- <item> release </item>
-
- <item> always </item>
- <item> initial </item>
- <item> edge </item>
- <item> posedge </item>
- <item> negedge </item>
- </list>
-
- <list name="strength">
- <!-- drive strength supply0/supply1 omitted, its in types.. -->
- <item> strong0 </item>
- <item> strong1 </item>
- <item> pull0 </item>
- <item> pull1 </item>
- <item> weak0 </item>
- <item> weak1 </item>
- <item> highz0 </item>
- <item> highz1 </item>
- <!-- charge strength -->
- <item> small </item>
- <item> medium </item>
- <item> large </item>
- </list>
-
- <list name="gates">
- <item> pullup </item>
- <item> pulldown </item>
- <item> cmos </item>
- <item> rcmos </item>
- <item> nmos </item>
- <item> pmos </item>
- <item> rnmos </item>
- <item> rpmos </item>
- <item> and </item>
- <item> nand </item>
- <item> or </item>
- <item> nor </item>
- <item> xor </item>
- <item> xnor </item>
- <item> not </item>
- <item> buf </item>
- <item> tran </item>
- <item> rtran </item>
- <item> tranif0 </item>
- <item> tranif1 </item>
- <item> rtranif0 </item>
- <item> rtranif1 </item>
- <item> bufif0 </item>
- <item> bufif1 </item>
- <item> notif0 </item>
- <item> notif1 </item>
- </list>
-
- <list name="types">
- <!-- port direction -->
- <item> input </item>
- <item> output </item>
- <item> inout </item>
- <!-- net type -->
- <item> wire </item>
- <item> tri </item>
- <item> tri0 </item>
- <item> tri1 </item>
- <item> wand </item>
- <item> wor </item>
- <item> triand </item>
- <item> trior </item>
- <item> supply0 </item>
- <item> supply1 </item>
- <!-- reg/variable -->
- <item> reg </item>
- <item> integer </item>
- <item> real </item>
- <item> realtime </item>
- <item> time </item>
- <!-- modifier -->
- <item> vectored </item>
- <item> scalared </item>
- <item> trireg </item>
- <!-- other -->
- <item> parameter </item>
- <item> event </item>
- </list>
-
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <RegExpr attribute="Keyword" context="Block name" String="begin\ *:"/>
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Data Type" context="#stay" String="types" />
- <keyword attribute="Drive/charge strength" context="#stay" String="strength" />
- <keyword attribute="Gate instantiation" context="#stay" String="gates" />
-
- <RegExpr attribute="Normal Text" context="#stay" String="[a-zA-Z]+[a-zA-Z0-9_$]*"/>
- <RegExpr attribute="Normal Text" context="#stay" String="\\[^ ]+ "/>
-
- <RegExpr attribute="Decimal" context="#stay" String="[0-9_]*'d[0-9_]+"/>
- <RegExpr attribute="Octal" context="#stay" String="[0-9_]*'o[0-7xXzZ_]+"/>
- <RegExpr attribute="Hex" context="#stay" String="[0-9_]*'h[0-9a-fA-FxXzZ_]+"/>
- <RegExpr attribute="Binary" context="#stay" String="[0-9_]*'b[01_zZxX]+"/>
- <Float attribute="Float" context="#stay"/>
- <Int attribute="Integer" context="#stay" />
-
- <RegExpr attribute="Port connection" context="#stay" String="[^a-zA-Z0-9_$]\.[a-zA-Z]+[a-zA-Z0-9_$]*"/>
-
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar 2" char="/" char1="*"/>
- <AnyChar attribute="Symbol" context="#stay" String="!%&amp;()+,-&lt;=+/:;&gt;?[]^{|}~@"/>
-
- <StringDetect attribute="Comment" context="Some Context2" String="#if 0" insensitive="FALSE"/>
-
- <RegExpr attribute="Preprocessor" context="Preprocessor" String="^`"/>
- <RegExpr attribute="Preprocessor" context="#stay" String="\`[a-zA-Z_]+[a-zA-Z0-9_]*" />
- <RegExpr attribute="System Task" context="#stay" String="\$[a-zA-Z_]+[a-zA-Z0-9_]*" />
- <RegExpr attribute="Delay" context="#stay" String="#[0-9_]+" />
- </context>
- <context attribute="String" lineEndContext="#pop" name="String">
- <LineContinue attribute="String" context="Some Context"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context attribute="Comment" lineEndContext="#pop" name="Commentar 1">
- <RegExpr attribute="Decimal" context="#stay" String="(FIXME|TODO)" />
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar 2">
- <RegExpr attribute="Decimal" context="#stay" String="(FIXME|TODO)" />
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/"/>
- </context>
- <context attribute="Preprocessor" lineEndContext="#pop" name="Preprocessor">
- <LineContinue attribute="Preprocessor" context="Some Context"/>
- <RangeDetect attribute="Prep. Lib" context="#stay" char="&quot;" char1="&quot;"/>
- <RangeDetect attribute="Prep. Lib" context="#stay" char="&lt;" char1="&gt;"/>
- <Detect2Chars attribute="Comment" context="Commentar 1" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="Commentar/Preprocessor" char="/" char1="*"/>
- </context>
- <context attribute="Comment" lineEndContext="#stay" name="Commentar/Preprocessor">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" />
- </context>
- <context attribute="Normal Text" lineEndContext="#pop" name="Some Context"/>
- <context attribute="Comment" lineEndContext="#stay" name="Some Context2">
- <RegExpr attribute="Decimal" context="#stay" String="(FIXME|TODO)" />
- <RegExpr attribute="Comment" context="#pop" String="^#endif" />
- </context>
-
- <context attribute="Block name" lineEndContext="#pop" name="Block name">
- <RegExpr attribute="Data Type" context="#pop" String="[^ ]+"/>
- </context>
- </contexts>
-
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
-
- <itemData name="Decimal" defStyleNum="dsBaseN"/>
- <itemData name="Octal" defStyleNum="dsBaseN"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Binary" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
-
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsNormal"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- <itemData name="Prep. Lib" defStyleNum="dsFloat"/>
- <itemData name="System Task" defStyleNum="dsDataType"/>
-
- <itemData name="Integer" defStyleNum="dsDecVal"/>
- <itemData name="Delay" defStyleNum="dsBaseN"/>
- <itemData name="Block name" defStyleNum="dsDataType"/>
- <itemData name="Drive/charge strength" defStyleNum="dsBaseN"/>
- <itemData name="Gate instantiation" defStyleNum="dsDataType"/>
- <itemData name="Port connection" defStyleNum="dsDataType"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="VHDL" version="1.03" kateversion="2.1" section="Sources" extensions="*.vhdl;*.vhd" mimetype="text/x-vhdl">
- <highlighting>
- <list name="keywords">
- <item> access </item>
- <item> after </item>
- <item> alias </item>
- <item> all </item>
- <item> assert </item>
- <item> architecture </item>
- <item> begin </item>
- <item> block </item>
- <item> body </item>
- <item> buffer </item>
- <item> bus </item>
- <item> case </item>
- <item> component </item>
- <item> configuration </item>
- <item> constant </item>
- <item> disconnect </item>
- <item> downto </item>
- <item> else </item>
- <item> elsif </item>
- <item> end </item>
- <item> entity </item>
- <item> exit </item>
- <item> file </item>
- <item> for </item>
- <item> function </item>
- <item> generate </item>
- <item> generic </item>
- <item> group </item>
- <item> guarded </item>
- <item> if </item>
- <item> impure </item>
- <item> in </item>
- <item> inertial </item>
- <item> inout </item>
- <item> is </item>
- <item> label </item>
- <item> library </item>
- <item> linkage </item>
- <item> literal </item>
- <item> loop </item>
- <item> map </item>
- <item> new </item>
- <item> next </item>
- <item> null </item>
- <item> of </item>
- <item> on </item>
- <item> open </item>
- <item> others </item>
- <item> out </item>
- <item> package </item>
- <item> port </item>
- <item> postponed </item>
- <item> procedure </item>
- <item> process </item>
- <item> pure </item>
- <item> range </item>
- <item> record </item>
- <item> register </item>
- <item> reject </item>
- <item> report </item>
- <item> return </item>
- <item> select </item>
- <item> severity </item>
- <item> signal </item>
- <item> shared </item>
- <item> subtype </item>
- <item> then </item>
- <item> to </item>
- <item> transport </item>
- <item> type </item>
- <item> unaffected </item>
- <item> units </item>
- <item> until </item>
- <item> use </item>
- <item> variable </item>
- <item> wait </item>
- <item> when </item>
- <item> while </item>
- <item> with </item>
- <item> note </item>
- <item> warning </item>
- <item> error </item>
- <item> failure </item>
- <item> ACCESS </item>
- <item> AFTER </item>
- <item> ALIAS </item>
- <item> ALL </item>
- <item> ASSERT </item>
- <item> ARCHITECTURE </item>
- <item> BEGIN </item>
- <item> BLOCK </item>
- <item> BODY </item>
- <item> BUFFER </item>
- <item> BUS </item>
- <item> CASE </item>
- <item> COMPONENT </item>
- <item> CONFIGURATION </item>
- <item> CONSTANT </item>
- <item> DISCONNECT </item>
- <item> DOWNTO </item>
- <item> ELSE </item>
- <item> ELSIF </item>
- <item> END </item>
- <item> ENTITY </item>
- <item> EXIT </item>
- <item> FILE </item>
- <item> FOR </item>
- <item> FUNCTION </item>
- <item> GENERATE </item>
- <item> GENERIC </item>
- <item> GROUP </item>
- <item> GUARDED </item>
- <item> IF </item>
- <item> IMPURE </item>
- <item> IN </item>
- <item> INERTIAL </item>
- <item> INOUT </item>
- <item> IS </item>
- <item> LABEL </item>
- <item> LIBRARY </item>
- <item> LINKAGE </item>
- <item> LITERAL </item>
- <item> LOOP </item>
- <item> MAP </item>
- <item> NEW </item>
- <item> NEXT </item>
- <item> NULL </item>
- <item> OF </item>
- <item> ON </item>
- <item> OPEN </item>
- <item> OTHERS </item>
- <item> OUT </item>
- <item> PACKAGE </item>
- <item> PORT </item>
- <item> POSTPONED </item>
- <item> PROCEDURE </item>
- <item> PROCESS </item>
- <item> PURE </item>
- <item> RANGE </item>
- <item> RECORD </item>
- <item> REGISTER </item>
- <item> REJECT </item>
- <item> REPORT </item>
- <item> RETURN </item>
- <item> SELECT </item>
- <item> SEVERITY </item>
- <item> SIGNAL </item>
- <item> SHARED </item>
- <item> SUBTYPE </item>
- <item> THEN </item>
- <item> TO </item>
- <item> TRANSPORT </item>
- <item> TYPE </item>
- <item> UNAFFECTED </item>
- <item> UNITS </item>
- <item> UNTIL </item>
- <item> USE </item>
- <item> VARIABLE </item>
- <item> WAIT </item>
- <item> WHEN </item>
- <item> WHILE </item>
- <item> WITH </item>
- <item> NOTE </item>
- <item> WARNING </item>
- <item> ERROR </item>
- <item> FAILURE </item>
- <item> and </item>
- <item> or </item>
- <item> xor </item>
- <item> not </item>
- <item> AND </item>
- <item> OR </item>
- <item> XOR </item>
- <item> NOT </item>
- </list>
- <list name="types">
- <item> bit </item>
- <item> bit_vector </item>
- <item> character </item>
- <item> boolean </item>
- <item> integer </item>
- <item> real </item>
- <item> time </item>
- <item> string </item>
- <item> severity_level </item>
- <item> positive </item>
- <item> natural </item>
- <item> signed </item>
- <item> unsigned </item>
- <item> line </item>
- <item> text </item>
- <item> std_logic </item>
- <item> std_logic_vector </item>
- <item> std_ulogic </item>
- <item> std_ulogic_vector </item>
- <item> qsim_state </item>
- <item> qsim_state_vector </item>
- <item> qsim_12state </item>
- <item> qsim_12state_vector </item>
- <item> qsim_strength </item>
- <item> mux_bit </item>
- <item> mux_vector </item>
- <item> reg_bit </item>
- <item> reg_vector </item>
- <item> wor_bit </item>
- <item> wor_vector </item>
- <item> BIT </item>
- <item> BIT_VECTOR </item>
- <item> CHARACTER </item>
- <item> BOOLEAN </item>
- <item> INTEGER </item>
- <item> REAL </item>
- <item> TIME </item>
- <item> STRING </item>
- <item> SEVERITY_LEVEL </item>
- <item> POSITIVE </item>
- <item> NATURAL </item>
- <item> SIGNED </item>
- <item> UNSIGNED </item>
- <item> LINE </item>
- <item> TEXT </item>
- <item> STD_LOGIC </item>
- <item> STD_LOGIC_VECTOR </item>
- <item> STD_ULOGIC </item>
- <item> STD_ULOGIC_VECTOR </item>
- <item> QSIM_STATE </item>
- <item> QSIM_STATE_VECTOR </item>
- <item> QSIM_12STATE </item>
- <item> QSIM_12STATE_VECTOR </item>
- <item> QSIM_STRENGTH </item>
- <item> MUX_BIT </item>
- <item> MUX_VECTOR </item>
- <item> REG_BIT </item>
- <item> REG_VECTOR </item>
- <item> WOR_BIT </item>
- <item> WOR_VECTOR </item>
- </list>
- <contexts>
- <context name="normal" attribute="Normal Text" lineEndContext="#stay">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <Detect2Chars attribute="Comment" context="comment" char="-" char1="-" />
- <Int attribute="Integer" context="#stay" />
- <HlCChar attribute="Bit" context="#stay" />
- <DetectChar attribute="Vector" context="string" char="&quot;" />
- <AnyChar attribute="Operator" context="#stay" String="[&amp;&gt;&lt;=:+\-*\/|]().,;" />
- <DetectChar attribute="Attribute" context="attribute" char="'" />
- </context>
- <context name="comment" attribute="Comment" lineEndContext="#pop" />
- <context name="string" attribute="Vector" lineEndContext="#stay" >
- <DetectChar attribute="Vector" context="#pop" char="&quot;" />
- </context>
- <context name="attribute" attribute="Attribute" lineEndContext="#pop">
- <DetectChar attribute="Attribute" context="quot in att" char="&quot;" />
- <DetectChar attribute="Normal Text" context="#pop" char=" " />
- <AnyChar attribute="Attribute" context="#pop" String=")=&lt;&gt;" />
- </context>
- <context name="quot in att" attribute="Attribute" lineEndContext="#stay">
- <DetectChar attribute="Attribute" context="#pop" char="&quot;" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal" />
- <itemData name="Keyword" defStyleNum="dsKeyword" />
- <itemData name="Data Type" defStyleNum="dsDataType" />
- <itemData name="Comment" defStyleNum="dsComment" />
- <itemData name="Integer" defStyleNum="dsDecVal" />
- <itemData name="Bit" defStyleNum="dsChar" />
- <itemData name="Vector" defStyleNum="dsString" />
- <itemData name="Operator" defStyleNum="dsOthers" />
- <itemData name="Attribute" defStyleNum="dsBaseN" />
- </itemDatas>
- </highlighting>
- <general>
- <keywords casesensitive="1" />
- </general>
-</language>
-
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="VRML" version="1.0" section="Markup" extensions="*.wrl" mimetype="model/vrml">
- <highlighting>
- <list name="keywords">
- <item>DEF</item>
- <item>EXTERNPROTO</item>
- <item>FALSE</item>
- <item>IS</item>
- <item>NULL</item>
- <item>PROTO</item>
- <item>ROUTE</item>
- <item>TO</item>
- <item>TRUE</item>
- <item>USE</item>
- <item>eventIn</item>
- <item>eventOut</item>
- <item>exposedField</item>
- <item>field</item>
- </list>
- <list name="types">
- <item>MFColor</item>
- <item>MFFloat</item>
- <item>MFInt32</item>
- <item>MFNode</item>
- <item>MFRotation</item>
- <item>MFString</item>
- <item>MFTime</item>
- <item>MFVec2f</item>
- <item>MFVec3f</item>
- <item>SFBool</item>
- <item>SFColor</item>
- <item>SFFloat</item>
- <item>SFImage</item>
- <item>SFInt32</item>
- <item>SFNode</item>
- <item>SFRotation</item>
- <item>SFString</item>
- <item>SFTime</item>
- <item>SFVec2f</item>
- <item>SFVec3f</item>
- </list>
- <list name="nodes">
- <item>Anchor</item>
- <item>AudioClip</item>
- <item>Appearance</item>
- <item>Background</item>
- <item>Billboard</item>
- <item>Box</item>
- <item>Collision</item>
- <item>Color</item>
- <item>ColorInterpolator</item>
- <item>Cone</item>
- <item>Coordinate</item>
- <item>CoordinateInterpolator</item>
- <item>Cylinder</item>
- <item>CylinderSensor</item>
- <item>DirectionalLight</item>
- <item>ElevationGrid</item>
- <item>Extrusion</item>
- <item>Fog</item>
- <item>FontStyle</item>
- <item>Group</item>
- <item>ImageTexture</item>
- <item>IndexedFaceSet</item>
- <item>IndexedLineSet</item>
- <item>Inline</item>
- <item>LOD</item>
- <item>Material</item>
- <item>MovieTexture</item>
- <item>NavigationInfo</item>
- <item>Normal</item>
- <item>NormalInterpolator</item>
- <item>OrientationInterpolator</item>
- <item>PixelTexture</item>
- <item>Plane</item>
- <item>PlaneSensor</item>
- <item>PointLight</item>
- <item>PointSet</item>
- <item>PositionInterpolator</item>
- <item>ProximitySensor</item>
- <item>ScalarInterpolator</item>
- <item>Script</item>
- <item>Shape</item>
- <item>Sensor</item>
- <item>Sound</item>
- <item>Sphere</item>
- <item>SphereSensor</item>
- <item>SpotLight</item>
- <item>Switch</item>
- <item>Text</item>
- <item>TextureCoordinate</item>
- <item>TextureTransform</item>
- <item>TimeSensor</item>
- <item>TouchSensor</item>
- <item>Transform</item>
- <item>Viewpoint</item>
- <item>VisibilitySensor</item>
- <item>WorldInfo</item>
- </list>
- <contexts>
- <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <keyword attribute="Node" context="#stay" String="nodes"/>
- <keyword attribute="Data Type" context="#stay" String="types"/>
- <Float attribute="Float" context="#stay"/>
- <HlCHex attribute="Hex" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- <DetectChar attribute="Normal Text" context="#stay" char="{" beginRegion="Brace"/>
- <DetectChar attribute="Normal Text" context="#stay" char="}" endRegion="Brace"/>
- <DetectChar attribute="String" context="String" char="&quot;"/>
- <DetectChar attribute="Comment" context="Comment" char="#"/>
- </context>
- <context name="Comment" attribute="Comment" lineEndContext="#pop"/>
- <context attribute="String" lineEndContext="#stay" name="String">
- <LineContinue attribute="String" context="#stay"/>
- <HlCStringChar attribute="String Char" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Data Type" defStyleNum="dsDataType"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Hex" defStyleNum="dsBaseN"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="String Char" defStyleNum="dsChar"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Node" defStyleNum="dsNormal" color="#000080" selColor="#FFFFFF" bold="1" italic="0"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="#"/>
- </comments>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="WINE Config" version="1.02" kateversion="2.1" section="Other" extensions="*.reg" mimetype="">
- <highlighting>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal">
- <RegExpr String="WINE REGISTRY Version.*$" attribute="RegistryBeginEnd" context="#stay" />
- <RegExpr String="^#\s*&lt;\s*wineconf\s*&gt;" attribute="RegistryBeginEnd" context="#stay" />
- <RegExpr String="^#\s*&lt;\s*\/\s*wineconf\s*&gt;" attribute="RegistryBeginEnd" context="#stay" />
- <RegExpr String="^\[.*\]$" attribute="Section" context="#stay"/>
- <RegExpr String=";.*$" attribute="Comment" context="#stay"/>
-
- <RegExpr String="\s*&quot;\s*[a-zA-Z0-9_.:*]*\s*&quot;" attribute="Key" context="#stay" />
-
- <DetectChar char="=" attribute="Normal Text" context="Value"/>
- </context>
-
- <context attribute="Normal Text" lineEndContext="#pop" name="Value">
- <RegExpr String="\s*&quot;.*&quot;" attribute="Value" context="#stay" />
- <RegExpr String=";.*$" attribute="Comment" context="#stay"/>
- </context>
-
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Section" defStyleNum="dsKeyword"/>
- <itemData name="Key" defStyleNum="dsDataType"/>
- <itemData name="Value" defStyleNum="dsNormal" color="#0000FF" selColor="#ffffff" italic="0" bold="1"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="ValueFilesystem1" defStyleNum="dsNormal" color="#00AA00" selColor="#ffffff" italic="0" bold="1"/>
- <itemData name="ValueFilesystem2" defStyleNum="dsNormal" color="#FF0000" selColor="#ffffff" italic="0" bold="1"/>
- <itemData name="RegistryBeginEnd" defStyleNum="dsNormal" color="#00AAAA" selColor="#ffffff" italic="0" bold="1"/>
- </itemDatas>
- </highlighting>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="xHarbour" version="1.01" kateversion="2.1" section="Sources"
- extensions="*.prg;*.ch" mimetype="text/x-xharbour-src"
- author="Giancarlo Niccolai (giancarlo@niccolai.ws)" license="GPL">
-<highlighting>
-
- <list name="keywords">
- <item> local </item>
- <item> global </item>
- <item> extern </item>
- <item> field </item>
- <item> each </item>
- <item> as </item>
- <item> set </item>
- <item> clear </item>
- <item> screen </item>
- <item> databases </item>
- <item> all </item>
- <item> close </item>
- <item> color </item>
- <item> date </item>
- <item> else </item>
- <item> elseif </item>
- <item> in </item>
- <item> to </item>
- <item> do </item>
- <item> loop </item>
- <item> catch </item>
- <item> exit </item>
- <item> box </item>
- <item> say </item>
- <item> case </item>
- <item> switch </item>
- <item> self </item>
- <item> super </item>
- <item> say </item>
- <item> get </item>
- <item> read </item>
- <item> use </item>
- <item> select </item>
- <item> otherwise</item>
- <item> index </item>
- <item> alias </item>
- <item> like </item>
- <item> has </item>
- <item> return </item>
- <item> static </item>
- <item> on </item>
- <item> off </item>
- <item> nil </item>
- <item> ? </item>
- <item> class </item>
- <item> external</item>
- </list>
-
- <list name="context_beginners">
- <item> FOR </item>
- <item> IF </item>
- <item> SWITCH </item>
- <item> WHILE </item>
- <item> TRY </item>
- <item> BEGIN </item>
- <item> PROCEDURE </item>
- <item> FUNCTION </item>
- <item> METHOD </item>
- </list>
-
- <list name="context_terminators">
- <item> NEXT </item>
- <item> END </item>
- <item> ENDIF </item>
- <item> ENDDO </item>
- <item> ENDCASE </item>
- </list>
-
- <list name="class_keywords">
- <item> data </item>
- <item> inline </item>
- <item> method </item>
- <item> classdata </item>
- <item> init </item>
- <item> from </item>
- <item> hidden </item>
- </list>
-
- <list name="set_commands">
- <item> INVALID </item>
- <item> EXACT </item>
- <item> FIXED </item>
- <item> DECIMALS </item>
- <item> DATEFORMAT </item>
- <item> EPOCH </item>
- <item> PATH </item>
- <item> DEFAULT </item>
- <item> EXCLUSIVE </item>
- <item> SOFTSEEK </item>
- <item> UNIQUE </item>
- <item> DELETED </item>
- <item> CANCEL </item>
- <item> DEBUG </item>
- <item> TYPEAHEAD </item>
- <item> COLOR </item>
- <item> CURSOR </item>
- <item> CONSOLE </item>
- <item> ALTERNATE </item>
- <item> ALTFILE </item>
- <item> DEVICE </item>
- <item> EXTRA </item>
- <item> EXTRAFILE </item>
- <item> PRINTER </item>
- <item> PRINTFILE </item>
- <item> MARGIN </item>
- <item> BELL </item>
- <item> CONFIRM </item>
- <item> ESCAPE </item>
- <item> INSERT </item>
- <item> EXIT </item>
- <item> INTENSITY </item>
- <item> SCOREBOARD </item>
- <item> DELIMITERS </item>
- <item> DELIMCHARS </item>
- <item> WRAP </item>
- <item> MESSAGE </item>
- <item> MCENTER </item>
- <item> SCROLLBREAK </item>
- <item> EVENTMASK </item>
- <item> VIDEOMODE </item>
- <item> MBLOCKSIZE </item>
- <item> MFILEEXT </item>
- <item> STRICTREAD </item>
- <item> OPTIMIZE </item>
- <item> AUTOPEN </item>
- <item> AUTORDER </item>
- <item> AUTOSHARE </item>
- <item> LANGUAGE </item>
- <item> IDLEREPEAT </item>
- <item> TRACE </item>
- <item> TRACEFILE </item>
- <item> TRACESTACK </item>
- <item> FILECASE </item>
- <item> DIRCASE </item>
- <item> DIRSEPARATOR </item>
- </list>
-
- <list name="functions">
- <item> aadd </item>
- <item> adel </item>
- <item> achoice </item>
- <item> aclone </item>
- <item> aeval </item>
- <item> ains </item>
- <item> ascan </item>
- <item> asize </item>
- <item> adir </item>
- <item> afill </item>
- <item> atail </item>
- <item> asort </item>
- <item> array </item>
- <item> TAssociativeArray </item>
-
- <item> bin21 </item>
- <item> bin2l </item>
- <item> bin2u </item>
- <item> bin2w </item>
- <item> i2bin </item>
- <item> l2bin </item>
- <item> u2bin </item>
- <item> w2bin </item>
-
- <item> eval </item>
- <item> fieldblock </item>
- <item> fieldwblock </item>
-
- <item> inkey </item>
- <item> lastkey </item>
- <item> mcol </item>
- <item> mrow </item>
- <item> nextkey </item>
-
- <item> empty </item>
- <item> word </item>
- <item> descend </item>
- <item> __dbdelim </item>
- <item> __dbsdf </item>
-
- <item> os </item>
- <item> __run </item>
-
- <item> alert </item>
- <item> browse </item>
- <item> dbedit </item>
- <item> outerr </item>
- <item> outstd </item>
- <item> readkey </item>
- <item> readvar </item>
- <item> __atprompt </item>
- <item> __input </item>
- <item> __menuto </item>
- <item> __nonoallert </item>
- <item> __typefile </item>
- <item> __xrestscreen </item>
- <item> __xsavescreen </item>
-
- <item> DBAPPEND </item>
- <item> DBCLEARFILTER </item>
- <item> DBCLOSEALL </item>
- <item> DBCLOSEAREA </item>
- <item> DBCOMMIT </item>
- <item> DBCOMMITALL </item>
- <item> DBCREATE </item>
- <item> DBDELETE </item>
- <item> DBEVAL </item>
- <item> DBF </item>
- <item> DBFILTER </item>
- <item> DBGOBOTTOM </item>
- <item> DBGOTO </item>
- <item> DBGOTOP </item>
- <item> DBRECALL </item>
- <item> DBRLOCK </item>
- <item> DBRLOCKLIST </item>
- <item> DBRUNLOCK </item>
- <item> DBSEEK </item>
- <item> DBSELECTAREA </item>
- <item> DBSETDRIVER </item>
- <item> DBSETFILTER </item>
- <item> DBSKIP </item>
- <item> DBSTRUCT </item>
- <item> DBUNLOCK </item>
- <item> DBUNLOCKALL </item>
- <item> DBUSEAREA </item>
- <item> INDEXEXT </item>
- <item> INDEXKEY </item>
- <item> INDEXORD </item>
- <item> ORDBAGEXT </item>
- <item> ORDBAGNAME </item>
- <item> ORDCONDSET </item>
- <item> ORDCREATE </item>
- <item> ORDDESTROY </item>
- <item> ORDFOR </item>
- <item> ORDKEY </item>
- <item> ORDLISTADD </item>
- <item> ORDLISTCLEAR </item>
- <item> ORDLISTREBUILD </item>
- <item> ORDNAME </item>
- <item> ORDNUMBER </item>
- <item> ORDSETFOCUS </item>
- <item> RDDLIST </item>
- <item> RDDNAME </item>
- <item> RDDSETDEFAULT </item>
- <item> __DBCONTINUE </item>
- <item> __DBZAP </item>
- <item> __FLEDIT </item>
- <item> __RDDSETDEFAULT </item>
- <item> __dbCopyStruct </item>
- <item> __dbCopyXStruct </item>
- <item> __dbCreate </item>
- <item> __dbStructFilter </item>
- <item> dbSkipper </item>
- <item> CDOW </item>
- <item> CMONTH </item>
- <item> CTOD </item>
- <item> DATE </item>
- <item> DAY </item>
- <item> DAYS </item>
- <item> DOW </item>
- <item> DTOC </item>
- <item> DTOS </item>
- <item> MONTH </item>
- <item> YEAR </item>
-
- <item> GETENV </item>
- <item> SET </item>
- <item> SETMODE </item>
- <item> SETTYPEAHEAD </item>
- <item> VERSION </item>
- <item> __SETCENTURY </item>
- <item> __SetFunction </item>
-
- <item> break </item>
- <item> errorsys </item>
- <item> throw </item>
- <item> errornew </item>
-
- <item> HB_SETKEYSAVE </item>
- <item> HB_SetKeyCheck </item>
- <item> HB_SetKeyGet </item>
- <item> SETKEY </item>
- <item> __QUIT </item>
- <item> __WAIT </item>
-
- <item> file </item>
- <item> frename </item>
- <item> __dir </item>
-
- <item> col </item>
- <item> maxcol </item>
- <item> maxrow </item>
- <item> row </item>
- <item> hb_colorindex </item>
-
- <item> CURDIR </item>
- <item> DIRCHANGE </item>
- <item> DIRREMOVE </item>
- <item> DISKSPACE </item>
- <item> FCLOSE </item>
- <item> FCREATE </item>
- <item> FERASE </item>
- <item> FERROR </item>
- <item> FOPEN </item>
- <item> FREAD </item>
- <item> FREADSTR </item>
- <item> FSEEK </item>
- <item> FWRITE </item>
- <item> HB_DISKSPACE </item>
- <item> HB_FEOF </item>
- <item> ISDISK </item>
- <item> MAKEDIR </item>
-
- <item> ABS </item>
- <item> EXP </item>
- <item> INT </item>
- <item> LOG </item>
- <item> MAX </item>
- <item> MIN </item>
- <item> MOD </item>
- <item> ROUND </item>
- <item> SQRT </item>
-
- <item> HB_ISBYREF </item>
- <item> PROCFILE </item>
- <item> PROCLINE </item>
- <item> PROCNAME </item>
- <item> TYPE </item>
- <item> VALTYPE </item>
- <item> valtoprg </item>
- <item> tone </item>
-
- <item> HB_LANGNAME </item>
- <item> HB_LANGSELECT </item>
- <item> ISAFFIRM </item>
- <item> ISNEGATIVE </item>
- <item> NATIONMSG </item>
-
- <item> pcount </item>
- <item> HB_pvalue </item>
-
- <item> ALLTRIM </item>
- <item> ASC </item>
- <item> AT </item>
- <item> CHR </item>
- <item> HARDCR </item>
- <item> HB_ANSITOOEM </item>
- <item> HB_OEMTOANSI </item>
- <item> HB_VALTOSTR </item>
- <item> ISALPHA </item>
- <item> ISDIGIT </item>
- <item> ISLOWER </item>
- <item> ISUPPER </item>
- <item> LEFT </item>
- <item> LEN </item>
- <item> LOWER </item>
- <item> LTRIM </item>
- <item> MEMOTRAN </item>
- <item> PADC </item>
- <item> PADL </item>
- <item> PADR </item>
- <item> RAT </item>
- <item> REPLICATE </item>
- <item> RIGHT </item>
- <item> RTRIM </item>
- <item> SPACE </item>
- <item> STR </item>
- <item> STRTRAN </item>
- <item> STRZERO </item>
- <item> SUBSTR </item>
- <item> TRANSFORM </item>
- <item> TRIM </item>
- <item> UPPER </item>
- <item> VAL </item>
-
- <item> devoutpict </item>
-
- <item> elaptime </item>
- <item> seconds </item>
- <item> secs </item>
- <item> time </item>
-
- <item> do </item>
-
- <item> ThreadStart </item>
- <item> ThreadStop </item>
- <item> ThreadSleep </item>
- <item> ThreadKill </item>
- <item> ThreadJoin </item>
- <item> CreateMutex </item>
- <item> DestroyMutex </item>
- <item> MutexLock </item>
- <item> MutexUnlock </item>
- <item> Subscribe </item>
- <item> SubscribeNow </item>
- <item> Notify </item>
- <item> NotifyAll </item>
- <item> WaitForThreads </item>
- <item> KillAllThreads </item>
-
- <item> InetInit </item>
- <item> InetCleanup </item>
- <item> InetCreate </item>
- <item> InetDestroy </item>
- <item> InetConnect </item>
- <item> InetServer </item>
- <item> InetAccept </item>
- <item> InetSetTimeout </item>
- <item> InetGetTimeout </item>
- <item> InetClearTimeout </item>
- <item> InetRecv </item>
- <item> InetRecvAll </item>
- <item> InetSend </item>
- <item> InetSendAll </item>
- <item> InetDGram </item>
- <item> InetDGramRecv </item>
- <item> InetDGramSend </item>
- <item> InetAddress </item>
- <item> InetPort </item>
- <item> InetError </item>
- <item> InetErrorDesc </item>
- <item> InetGetHosts </item>
- <item> InetConnectIP </item>
-
- <item> hb_regex </item>
- <item> hb_regexmatch </item>
- <item> hb_regexsplit </item>
- <item> hb_regexcomp </item>
- <item> hb_readini </item>
- <item> hb_writeini </item>
- <item> hb_random </item>
- <item> hb_chechsum </item>
- <item> hb_crypt </item>
- <item> hb_decrypt </item>
- <item> hb_hextonum </item>
- <item> hb_numtohex </item>
- <item> hb_exec </item>
- <item> hb_execfromarray </item>
-
- <item> hb_class </item>
- <item> hb_keyput </item>
- <item> hb_osnewline </item>
-
- </list>
-
- <list name="pragma">
- <item> #include </item>
- <item> #if </item>
- <item> #ifdef </item>
- <item> #ifndef </item>
- <item> #endif </item>
- <item> #else </item>
- <item> #define </item>
- </list>
-
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="TopLevel">
-
- <StringDetect attribute="Comment" context="ml_comment" String="/*"
- beginRegion="comment_region"/>
- <RegExpr attribute="Comment" context="comment" String="^[\t ]*[*]" />
- <StringDetect attribute="Comment" context="comment" String="//" />
-
- <DetectChar attribute="String" context="string" char="&quot;" />
- <DetectChar attribute="String" context="stringc" char="'" />
-
- <StringDetect attribute="Operator" context="#stay" String=".and." insensitive="TRUE"/>
- <StringDetect attribute="Operator" context="#stay" String=".or." insensitive="TRUE"/>
- <StringDetect attribute="Operator" context="#stay" String=".not." insensitive="TRUE"/>
- <StringDetect attribute="Operator" context="#stay" String=".f." insensitive="TRUE"/>
- <StringDetect attribute="Operator" context="#stay" String=".t." insensitive="TRUE"/>
-
- <DetectChar attribute="Operator" context="#stay" char=":"/>
- <DetectChar attribute="Operator" context="#stay" char="="/>
- <DetectChar attribute="Operator" context="#stay" char="!"/>
- <DetectChar attribute="Keyword" context="#stay" char="@"/>
-
- <RegExpr String="^[\t ]*CLASS[\t ]+" attribute="Keyword" context="ClassContext"
- insensitive="TRUE" beginRegion="ClassDeclRegion" />
-
- <RegExpr String="^[\t ]*DO[\t ]+CASE[\t ]*$" attribute="Keyword" context="#stay"
- insensitive="TRUE" beginRegion="IndentRegion" />
- <keyword attribute="Keyword" context="#stay" String="context_beginners"
- beginRegion="IndentRegion" />
- <keyword attribute="Keyword" context="#stay" String="context_terminators"
- endRegion="IndentRegion" />
- <RegExpr String="^return ?" attribute="Keyword" context="#stay"
- insensitive="TRUE" endRegion="IndentRegion" />
-
- <keyword attribute="Keyword" context="#stay" String="keywords" />
- <keyword attribute="Keyword" context="#stay" String="set_commands" />
- <keyword attribute="Function" context="#stay" String="functions" />
- <keyword attribute="Preprocessor" context="#stay" String="pragma" />
- <RegExpr attribute="Operator" context="#stay" String="->" />
- <RegExpr attribute="Number" context="#stay" String="[0-9]+" />
- </context>
-
- <context attribute="Comment" lineEndContext="#pop" name="comment"/>
-
- <context attribute="Comment" lineEndContext="#stay" name="ml_comment">
- <StringDetect attribute="Comment" context="#pop" String="*/"
- endRegion="comment_region"/>
- </context>
-
- <context attribute="String" lineEndContext="#pop" name="string">
- <DetectChar attribute="String" context="#pop" char="&quot;" />
- </context>
- <context attribute="String" lineEndContext="#pop" name="stringc">
- <DetectChar attribute="String" context="#pop" char="'" />
- </context>
-
- <context attribute="Operator" lineEndContext="#pop" name="logic">
- <DetectChar attribute="Operator" context="#pop" char="." />
- </context>
-
- <context attribute="Normal Text" lineEndContext="#stay" name="ClassContext">
-
- <StringDetect attribute="Comment" context="ml_comment" String="/*"
- beginRegion="comment_region"/>
- <RegExpr attribute="Comment" context="comment" String="^[ ]*[*]" />
- <StringDetect attribute="Comment" context="comment" String="//" />
-
- <keyword attribute="Keyword" context="#stay" String="class_keywords" />
- <RegExpr String="^[\t ]*END(CLASS)? *$" attribute="Keyword" context="#pop"
- insensitive="TRUE" endRegion="ClassDeclRegion" />
- </context>
-
- </contexts>
-
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Operator" defStyleNum="dsBaseN" color="#A01060" selColor="#400040" bold="0" italic="0"/>
- <itemData name="Number" defStyleNum="dsDecVal" color="#5050C0" selColor="#000000" bold="0" italic="0"/>
- <itemData name="Function" defStyleNum="dsNormal" color="#000090" selColor="#ffffff" bold="0" italic="0"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Preprocessor" defStyleNum="dsOthers"/>
- </itemDatas>
-</highlighting>
-
-<general>
- <comments>
- <comment name="singleLine" start="*" />
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="0" />
-</general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language version="1.03" kateversion="2.1" name="XML" section="Markup" extensions="*.docbook;*.xml;*.rc;*.daml;*.rdf" mimetype="text/xml;text/book;text/daml;text/rdf">
- <highlighting>
- <contexts>
- <context attribute="Normal Text" lineEndContext="#stay" name="Normal Text" >
- <StringDetect attribute="Comment" context="Comment" beginRegion="Comment" String="&lt;!--"/>
- <RegExpr attribute="Tag" context="Attribute" beginRegion="Element" String="&lt;\s*[a-zA-Z_:][a-zA-Z0-9._:-]*" />
- <RegExpr attribute="Tag" context="Attribute" endRegion="Element" String="&lt;\s*\/\s*[a-zA-Z_:][a-zA-Z0-9._:-]*" />
- </context>
-
- <context attribute="Attribute Name" lineEndContext="#stay" name="Attribute" >
- <Detect2Chars attribute="Tag" context="#pop" endRegion="Element" char="/" char1="&gt;" />
- <DetectChar attribute="Tag" context="#pop" char="&gt;" />
- <RegExpr attribute="Normal Text" context="Value" String="\s*=\s*" />
- </context>
-
- <context attribute="Attribute Value" lineEndContext="#stay" name="Value" >
- <Detect2Chars attribute="Tag" context="#pop#pop" char="/" char1="&gt;" />
- <DetectChar attribute="Tag" context="#pop#pop" char="&gt;" />
- <DetectChar attribute="Attribute Value" context="Value 2" char="&quot;" />
- <DetectChar attribute="Attribute Value" context="Value 2" char="&apos;" />
- </context>
-
- <context attribute="Attribute Value" lineEndContext="#stay" name="Value 2" >
- <DetectChar attribute="Attribute Value" context="#pop#pop" char="&quot;" />
- <DetectChar attribute="Attribute Value" context="#pop#pop" char="&apos;" />
- </context>
-
- <context attribute="Comment" lineEndContext="#stay" name="Comment" >
- <StringDetect attribute="Comment" context="#pop" endRegion="Comment" String="--&gt;"/>
- </context>
-
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Tag" defStyleNum="dsKeyword"/>
- <itemData name="Attribute Name" defStyleNum="dsOthers"/>
- <itemData name="Attribute Value" defStyleNum="dsDataType"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="multiLine" start="&lt;!--" end="//--&gt;" />
- </comments>
- <keywords casesensitive="0" />
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language version="1.01" kateversion="2.1" name="XML (Debug)" section="Markup" extensions="" mimetype="">
- <highlighting>
- <list name="AttType">
- <item>CDATA</item>
- <item>ID</item>
- <item>IDREF</item>
- <item>IDREFS</item>
- <item>ENTITY</item>
- <item>ENTITIES</item>
- <item>NMTOKEN</item>
- <item>NMTOKENS</item>
- </list>
- <contexts>
-
- <context name="0:prolog" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Doctype Declaration" context="1:XMLDecl Version" String="&lt;\?xml(\s+|$)"/>
- </context>
-
- <context name="1:XMLDecl Version" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Attribute" context="2:XMLDecl Version Eq" String="\s*version\s*"/>
- <RegExpr attribute="Doctype Declaration" String="\s+" context="#stay"/>
- </context>
-
- <context name="2:XMLDecl Version Eq" attribute="Error" lineEndContext="5:XMLDecl Encoding Eq">
- <RegExpr attribute="Attribute" context="3:XMLDecl Version" String="\s*=\s*"/>
- <RegExpr attribute="Attribute" context="#stay" String="\s+"/>
- </context>
-
- <context name="3:XMLDecl Version" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Value" context="4:XMLDecl Encoding" String="\s*(&quot;[A-Za-z0-9:._-]*&quot;|'[A-Za-z0-9:._-]*')(?!e)\s*"/>
- <RegExpr attribute="Attribute" context="#stay" String="\s+"/>
- </context>
-
- <context name="4:XMLDecl Encoding" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Attribute" context="5:XMLDecl Encoding Eq" String="\s*encoding\s*"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- <RegExpr attribute="Doctype Declaration" context="11:Misc after XMLDecl" String="\?>"/>
- </context>
-
- <context name="5:XMLDecl Encoding Eq" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Attribute" context="6:XMLDecl Encoding" String="\s*=\s*"/>
- <RegExpr attribute="Attribute" context="#stay" String="\s+"/>
- </context>
-
- <context name="6:XMLDecl Encoding" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Value" context="7:XMLDecl Standalone" String="\s*(&quot;[A-Za-z][A-Za-z0-9._-]*&quot;|'[A-Za-z][A-Za-z0-9._-]*')(?!s)\s*"/>
- <RegExpr attribute="Attribute" context="#stay" String="\s+"/>
- </context>
-
- <context name="7:XMLDecl Standalone" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Attribute" context="8:XMLDecl Standalone Eq" String="\s*standalone\s*"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- <RegExpr attribute="Doctype Declaration" context="11:Misc after XMLDecl" String="\?>"/>
- </context>
-
- <context name="8:XMLDecl Standalone Eq" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Attribute" context="9:XMLDecl Standalone" String="\s*=\s*"/>
- <RegExpr attribute="Attribute" context="#stay" String="\s+"/>
- </context>
-
- <context name="9:XMLDecl Standalone" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Value" context="10:XMLDecl Standalone" String="\s*&quot;(yes|no)&quot;|'(yes|no)'\s*"/>
- <RegExpr attribute="Attribute" context="#stay" String="\s+"/>
- </context>
-
- <context name="10:XMLDecl Standalone" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- <RegExpr attribute="Doctype Declaration" context="11:Misc after XMLDecl" String="\?>"/>
- </context>
-
- <context name="11:Misc after XMLDecl" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Normal Text" context="#stay" String="\s+"/>
- <RegExpr attribute="Comment" context="12:Comment after XMLDecl" String="\s*&lt;!--\s*"/>
- <RegExpr attribute="Processing Instruction" context="13:PI after XMLDecl" String="\s*&lt;\?xml-stylesheet(\s+|$)"/>
- <RegExpr attribute="Error" context="13:PI after XMLDecl" String="\s*&lt;\??[xX][mM][lL]"/>
- <RegExpr attribute="Processing Instruction" context="13:PI after XMLDecl" String="\s*&lt;\?[a-zA-Z_][a-zA-Z0-9_-]*(:[a-zA-Z0-9_-]*)?(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="14:Doctype Decl Name" String="&lt;!DOCTYPE(\s+|$)"/>
- <RegExpr attribute="Error" context="80:STag" String="&lt;[xX][mM][lL](\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Normal Tag" context="80:STag" String="&lt;(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|_)(\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Error" context="80:STag" String="&lt;(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[:_])(\w|[:_.-])*"/>
- <RegExpr attribute="Error" context="85:ETag" String="&lt;/[xX][mM][lL](\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Normal Tag" context="85:ETag" String="&lt;/(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|_)(\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Error" context="85:ETag" String="&lt;/(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[:_])(\w|[:_.-])*"/>
- <RegExpr attribute="Entity" context="79:Outside" String="&amp;(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*;"/>
- <RegExpr attribute="Entity" context="79:Outside" String="&amp;#(x[0-9a-fA-F]+|[0-9]+);"/>
- <RegExpr attribute="Entity" context="86:CDSect" String="&lt;!\[CDATA\["/>
- <RegExpr attribute="Comment" context="87:Comment inside IS" String="&lt;!--"/>
- <RegExpr attribute="Normal Tag" context="88:PI inside IS" String="&lt;\?xml-stylesheet(\s|$)"/>
- <RegExpr attribute="Error" context="88:PI inside IS" String="&lt;\?[xX][mM][lL](\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Normal Tag" context="88:PI inside IS" String="&lt;\?(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|_)(\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Error" context="88:PI inside IS" String="&lt;\?(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[:_])(\w|[:_.-])*"/>
- <DetectChar attribute="Error" context="79:Outside" char="&lt;"/>
- <DetectChar attribute="Error" context="79:Outside" char="&amp;"/>
- <RegExpr attribute="Error" context="79:Outside" String="\]\]>"/>
- </context>
-
- <context name="12:Comment after XMLDecl" attribute="Comment" lineEndContext="#stay">
- <RegExpr attribute="Error" context="#pop" String="--->"/>
- <RegExpr attribute="Comment" context="#pop" String="-->"/>
- <Detect2Chars attribute="Error" context="#stay" char="-" char1="-"/>
- </context>
-
- <context name="13:PI after XMLDecl" attribute="Processing Instruction Body" lineEndContext="#stay">
- <Detect2Chars attribute="Processing Instruction" context="#pop" char="?" char1="&gt;"/>
- </context>
-
- <context name="14:Doctype Decl Name" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Doctype Declaration" context="15:Doctype Decl ExternalID" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="15:Doctype Decl ExternalID" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Doctype Declaration" context="16:Doctype Decl PublicID" String="PUBLIC(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="19:Doctype Decl SystemID" String="SYSTEM(\s+|$)"/>
- <DetectChar attribute="Doctype Declaration" context="23:Doctype Decl IS" char="["/>
- <!-- rodda: this was originally context="?", so my best guess... most likely wrong -->
- <DetectChar attribute="Doctype Declaration" context="23:Doctype Decl IS" char=">"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="16:Doctype Decl PublicID" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="17:Doctype Decl PublicID qq" char="&quot;"/>
- <DetectChar attribute="Value" context="18:Doctype Decl PublicID q" char="'"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="17:Doctype Decl PublicID qq" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="19:Doctype Decl SystemID" char="&quot;(\s+|$)"/>
- <RegExpr attribute="Value" context="#stay" String="[&#x20;&#xD;&#xA;a-zA-Z0-9'()+,./:=?;!*#@$_%-]"/>
- </context>
-
- <context name="18:Doctype Decl PublicID q" attribute="Value" lineEndContext="#stay">
- <DetectChar attribute="Value" context="19:Doctype Decl SystemID" char="'(\s+|$)"/>
- <RegExpr attribute="Value" context="#stay" String="[&#x20;&#xD;&#xA;a-zA-Z0-9()+,./:=?;!*#@$_%-]"/>
- </context>
-
- <context name="19:Doctype Decl SystemID" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="20:Doctype Decl SystemID qq" char="&quot;"/>
- <DetectChar attribute="Value" context="21:Doctype Decl SystemID q" char="'"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="20:Doctype Decl SystemID qq" attribute="Value" lineEndContext="#stay">
- <DetectChar attribute="Value" context="22:Doctype Decl IS or end" char="&quot;"/>
- </context>
-
- <context name="21:Doctype Decl SystemID q" attribute="Value" lineEndContext="#stay">
- <DetectChar attribute="Value" context="22:Doctype Decl IS or end" char="'"/>
- </context>
-
- <context name="22:Doctype Decl IS or end" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Doctype Declaration" context="23:Doctype Decl IS" char="["/>
- <DetectChar attribute="Doctype Declaration" context="79:Outside" char=">"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="23:Doctype Decl IS" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Entity" context="#stay" String="%(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*;"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- <RegExpr attribute="Doctype Declaration" context="24:elementdecl" String="&lt;!ELEMENT(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="38:AttlistDecl" String="&lt;!ATTLIST(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="50:EntityDecl" String="&lt;!ENTITY(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="71:NotationDecl Name" String="&lt;!NOTATION(\s+|$)"/>
- <RegExpr attribute="Comment" context="77:Comment inside IS" String="\s*&lt;!--\s*"/>
- <RegExpr attribute="Processing Instruction" context="78:PI inside IS" String="\s*&lt;\?xml-stylesheet(\s+|$)"/>
- <RegExpr attribute="Error" context="78:PI inside IS" String="\s*&lt;\??[xX][mM][lL]"/>
- <RegExpr attribute="Processing Instruction" context="78:PI inside IS" String="\s*&lt;\?[a-zA-Z_][a-zA-Z0-9_-]*(:[a-zA-Z0-9_-]*)?(\s+|$)"/>
- <Detect2Chars attribute="Doctype Declaration" context="79:Outside" char="]" char1=">"/>
- </context>
-
- <context name="24:elementdecl" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Normal Tag" context="25:contentspec" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="25:contentspec" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Attribute" context="37:element end" String="(EMPTY|ANY)"/>
- <DetectChar attribute="Attribute" context="26:MixedOrChildren" char="("/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="26:MixedOrChildren" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Attribute" context="27:MixedShort" String="#PCDATA"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- <DetectChar attribute="Doctype Declaration" context="30:children unknown" char="("/>
- <RegExpr attribute="Value" context="30:children unknown" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*[\?\*\+]?"/>
- </context>
-
- <context name="27:MixedShort" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Doctype Declaration" context="28:MixedLong" char="|"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- <DetectChar attribute="Doctype Declaration" context="37:element end" char=")"/>
- </context>
-
- <context name="28:MixedLong" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Value" context="29:MixedLong endOrContinue" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="29:MixedLong endOrContinue" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Doctype Declaration" context="#pop" char="|"/>
- <RegExpr attribute="Doctype Declaration" context="#pop#pop" String="\s+"/>
- <Detect2Chars attribute="Doctype Declaration" context="37:element end" char=")" char1="*"/>
- </context>
-
- <context name="30:children unknown" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Doctype Declaration" context="33:children choice" char="|"/>
- <DetectChar attribute="Doctype Declaration" context="35:children seq" char=","/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- <RegExpr attribute="Doctype Declaration" context="31:children unknownOrEnd" String="\)[\?\*\+]?"/>
- </context>
-
- <context name="31:children unknownOrEnd" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Doctype Declaration" context="33:children choice" char="|"/>
- <DetectChar attribute="Doctype Declaration" context="35:children seq" char=","/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\)[\?\*\+]?"/>
- <DetectChar attribute="Doctype Declaration" context="23:Doctype Decl IS" char=">"/>
- </context>
-
- <context name="32:children unknownName" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Value" context="30:children unknown" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*[\?\*\+]?"/>
- <DetectChar attribute="Doctype Declaration" context="#stay" char="("/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="33:children choice" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Value" context="34:children choiceOrEnd" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*[\?\*\+]?"/>
- <DetectChar attribute="Doctype Declaration" context="32:children unknownName" char="("/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="34:children choiceOrEnd" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Doctype Declaration" context="#pop" char="|"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- <RegExpr attribute="Doctype Declaration" context="31:children unknownOrEnd" String="\)[\?\*\+]?"/>
- </context>
-
- <context name="35:children seq" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Value" context="36:children seqOrEnd" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*[\?\*\+]?"/>
- <DetectChar attribute="Doctype Declaration" context="32:children unknownName" char="("/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="36:children seqOrEnd" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Doctype Declaration" context="#pop" char=","/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- <RegExpr attribute="Doctype Declaration" context="31:children unknownOrEnd" String="\)[\?\*\+]?"/>
- </context>
-
- <context name="37:element end" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Doctype Declaration" context="23:Doctype Decl IS" char=">"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="38:AttlistDecl" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Normal Tag" context="39:AttDef" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*(\s+|$)"/>
- <RegExpr attribute="Normal Tag" context="23:Doctype Decl IS" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*>"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="39:AttDef" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Attribute" context="40:AttType" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- <DetectChar attribute="Doctype Declaration" context="23:Doctype Decl IS" char=">"/>
- </context>
-
- <context name="40:AttType" attribute="Error" lineEndContext="#stay">
- <keyword attribute="Doctype Declaration" context="46:DefaultDecl" String="AttType"/>
- <RegExpr attribute="Doctype Declaration" context="41:NotationStart" String="NOTATION(\s+|$)"/>
- <DetectChar attribute="Doctype Declaration" context="42:Notation" char="("/>
- <RegExpr attribute="Doctype Declaration" context="#pop" String="\s+"/>
- </context>
-
- <context name="41:NotationStart" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Doctype Declaration" context="42:Notation" char="("/>
- <RegExpr attribute="Doctype Declaration" context="#pop#pop" String="\s+"/>
- </context>
-
- <context name="42:Notation" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Value" context="43:Notation or End" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="43:Notation or End" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Doctype Declaration" context="#pop" char="|"/>
- <RegExpr attribute="Doctype Declaration" context="46:DefaultDecl" String="\)(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="44:Enumeration" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Value" context="#stay" String="(\w|[_:.-])+"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="45:Enumeration or End" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Doctype Declaration" context="44:Enumeration" char="|"/>
- <RegExpr attribute="Doctype Declaration" context="46:DefaultDecl" String="\)(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="46:DefaultDecl" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Attribute" context="39:AttDef" String="(#REQUIRED|#IMPLIED)(\s+|$)"/>
- <RegExpr attribute="Attribute" context="47:DefaultDecl AttValue" String="#FIXED(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- <RegExpr attribute="Value" context="48:DefaultDecl AttValue qq" String="&quot;"/>
- <RegExpr attribute="Value" context="49:DefaultDecl AttValue q" String="'"/>
- </context>
-
- <context name="47:DefaultDecl AttValue" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Value" context="48:DefaultDecl AttValue qq" String="&quot;"/>
- <RegExpr attribute="Value" context="49:DefaultDecl AttValue q" String="'"/>
- </context>
-
- <context name="48:DefaultDecl AttValue qq" attribute="Value" lineEndContext="#stay">
- <RegExpr attribute="Entity" context="#stay" String="&amp;(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*;"/>
- <RegExpr attribute="Entity" context="#stay" String="&amp;#(x[0-9a-fA-F]+|[0-9]+);"/>
- <DetectChar attribute="Error" context="#stay" char="&amp;"/>
- <DetectChar attribute="Error" context="#stay" char="&lt;"/>
- <DetectChar attribute="Value" context="39:AttDef" char="&quot;"/>
- </context>
-
- <context name="49:DefaultDecl AttValue q" attribute="Value" lineEndContext="#stay">
- <RegExpr attribute="Entity" context="#stay" String="&amp;(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*;"/>
- <RegExpr attribute="Entity" context="#stay" String="&amp;#(x[0-9a-fA-F]+|[0-9]+);"/>
- <DetectChar attribute="Error" context="#stay" char="&amp;"/>
- <DetectChar attribute="Error" context="#stay" char="&lt;"/>
- <DetectChar attribute="Value" context="39:AttDef" char="&quot;"/>
- </context>
-
- <context name="50:EntityDecl" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Entity" context="52:GEDecl EntityValueOrExternalID" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*(\s+|$)"/>
- <DetectChar attribute="Entity" context="61:PEDecl" char="%"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="51:unused" attribute="Error" lineEndContext="#stay">
- </context>
-
- <context name="52:GEDecl EntityValueOrExternalID" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Value" context="53:GEDecl EntityValue qq" String="&quot;"/>
- <RegExpr attribute="Value" context="54:GEDecl EntityValue q" String="'"/>
- <RegExpr attribute="Doctype Declaration" context="55:GEDecl PublicID" String="PUBLIC(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="58:GEDecl SystemID" String="SYSTEM(\s+|$)"/>
- </context>
-
- <context name="53:GEDecl EntityValue qq" attribute="Value" lineEndContext="#stay">
- <RegExpr attribute="Entity" context="#stay" String="[&amp;%](?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*;"/>
- <RegExpr attribute="Entity" context="#stay" String="&amp;#(x[0-9a-fA-F]+|[0-9]+);"/>
- <DetectChar attribute="Error" context="#stay" char="&amp;"/>
- <DetectChar attribute="Error" context="#stay" char="%"/>
- <DetectChar attribute="Error" context="#stay" char="&lt;"/>
- <DetectChar attribute="Value" context="69:GEDecl endOrNDATA" char="&quot;"/>
- </context>
-
- <context name="54:GEDecl EntityValue q" attribute="Value" lineEndContext="#stay">
- <RegExpr attribute="Entity" context="#stay" String="[&amp;%](?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*;"/>
- <RegExpr attribute="Entity" context="#stay" String="&amp;#(x[0-9a-fA-F]+|[0-9]+);"/>
- <DetectChar attribute="Error" context="#stay" char="&amp;"/>
- <DetectChar attribute="Error" context="#stay" char="%"/>
- <DetectChar attribute="Error" context="#stay" char="&lt;"/>
- <DetectChar attribute="Value" context="69:GEDecl endOrNDATA" char="'"/>
- </context>
-
- <context name="55:GEDecl PublicID" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="56:GEDecl PublicID qq" char="&quot;"/>
- <DetectChar attribute="Value" context="57:GEDecl PublicID q" char="'"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="56:GEDecl PublicID qq" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="58:GEDecl SystemID" char="&quot;(\s+|$)"/>
- <RegExpr attribute="Value" context="#stay" String="[&#x20;&#xD;&#xA;a-zA-Z0-9'()+,./:=?;!*#@$_%-]"/>
- </context>
-
- <context name="57:GEDecl PublicID q" attribute="Value" lineEndContext="#stay">
- <DetectChar attribute="Value" context="58:GEDecl SystemID" char="'(\s+|$)"/>
- <RegExpr attribute="Value" context="#stay" String="[&#x20;&#xD;&#xA;a-zA-Z0-9()+,./:=?;!*#@$_%-]"/>
- </context>
-
- <context name="58:GEDecl SystemID" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="59:GEDecl SystemID qq" char="&quot;"/>
- <DetectChar attribute="Value" context="60:GEDecl SystemID q" char="'"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="59:GEDecl SystemID qq" attribute="Value" lineEndContext="#stay">
- <DetectChar attribute="Value" context="69:GEDecl endOrNDATA" char="&quot;"/>
- </context>
-
- <context name="60:GEDecl SystemID q" attribute="Value" lineEndContext="#stay">
- <DetectChar attribute="Value" context="69:GEDecl endOrNDATA" char="'"/>
- </context>
-
- <context name="61:PEDecl" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Entity" context="62:PEDecl EntityValueOrExternalID" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="62:PEDecl EntityValueOrExternalID" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Value" context="53:GEDecl EntityValue qq" String="&quot;"/>
- <RegExpr attribute="Value" context="54:GEDecl EntityValue q" String="'"/>
- <RegExpr attribute="Doctype Declaration" context="63:PEDecl PublicID" String="PUBLIC(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="66:PEDecl SystemID" String="SYSTEM(\s+|$)"/>
- </context>
-
- <context name="63:PEDecl PublicID" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="64:PEDecl PublicID qq" char="&quot;"/>
- <DetectChar attribute="Value" context="65:PEDecl PublicID q" char="'"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="64:PEDecl PublicID qq" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="66:PEDecl SystemID" char="&quot;(\s+|$)"/>
- <RegExpr attribute="Value" context="#stay" String="[&#x20;&#xD;&#xA;a-zA-Z0-9'()+,./:=?;!*#@$_%-]"/>
- </context>
-
- <context name="65:PEDecl PublicID q" attribute="Value" lineEndContext="#stay">
- <DetectChar attribute="Value" context="66:PEDecl SystemID" char="'(\s+|$)"/>
- <RegExpr attribute="Value" context="#stay" String="[&#x20;&#xD;&#xA;a-zA-Z0-9()+,./:=?;!*#@$_%-]"/>
- </context>
-
- <context name="66:PEDecl SystemID" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="67:PEDecl SystemID qq" char="&quot;"/>
- <DetectChar attribute="Value" context="68:PEDecl SystemID q" char="'"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="67:PEDecl SystemID qq" attribute="Value" lineEndContext="#stay">
- <DetectChar attribute="Value" context="37:element end" char="&quot;"/>
- </context>
-
- <context name="68:PEDecl SystemID q" attribute="Value" lineEndContext="#stay">
- <DetectChar attribute="Value" context="37:element end" char="'"/>
- </context>
-
- <context name="69:GEDecl endOrNDATA" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Doctype Declaration" context="23:Doctype Decl IS" char=">"/>
- <RegExpr attribute="Doctype Declaration" context="70:GEDecl NDATA" String="NDATA(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="70:GEDecl NDATA" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Entity" context="37:element end" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="71:NotationDecl Name" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Entity" context="72:NotationDecl ExternalID" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="72:NotationDecl ExternalID" attribute="Error" lineEndContext="#stay">
- <RegExpr attribute="Doctype Declaration" context="73:NotationDecl PublicID" String="PUBLIC(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="66:PEDecl SystemID" String="SYSTEM(\s+|$)"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="73:NotationDecl PublicID" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="74:NotationDecl PublicID qq" char="&quot;"/>
- <DetectChar attribute="Value" context="75:NotationDecl PublicID q" char="'"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="74:NotationDecl PublicID qq" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="76:NotationDecl SystemIDOrEnd" char="&quot;(\s+|$)"/>
- <RegExpr attribute="Value" context="#stay" String="[&#x20;&#xD;&#xA;a-zA-Z0-9'()+,./:=?;!*#@$_%-]"/>
- </context>
-
- <context name="75:NotationDecl PublicID q" attribute="Value" lineEndContext="#stay">
- <DetectChar attribute="Value" context="76:NotationDecl SystemIDOrEnd" char="'(\s+|$)"/>
- <RegExpr attribute="Value" context="#stay" String="[&#x20;&#xD;&#xA;a-zA-Z0-9()+,./:=?;!*#@$_%-]"/>
- </context>
-
- <context name="76:NotationDecl SystemIDOrEnd" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="67:PEDecl SystemID qq" char="&quot;"/>
- <DetectChar attribute="Value" context="68:PEDecl SystemID q" char="'"/>
- <DetectChar attribute="Doctype Declaration" context="23:Doctype Decl IS" char=">"/>
- <RegExpr attribute="Doctype Declaration" context="#stay" String="\s+"/>
- </context>
-
- <context name="77:Comment inside IS" attribute="Comment" lineEndContext="#stay">
- <RegExpr attribute="Error" context="23:Doctype Decl IS" String="--->"/>
- <RegExpr attribute="Comment" context="23:Doctype Decl IS" String="-->"/>
- <Detect2Chars attribute="Error" context="#stay" char="-" char1="-"/>
- </context>
-
- <context name="78:PI inside IS" attribute="Processing Instruction Body" lineEndContext="#stay">
- <Detect2Chars attribute="Processing Instruction" context="23:Doctype Decl IS" char="?" char1="&gt;"/>
- </context>
-
- <context name="79:Outside" attribute="Normal Text" lineEndContext="#stay">
- <RegExpr attribute="Error" context="80:STag" String="&lt;[xX][mM][lL](\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Normal Tag" context="80:STag" String="&lt;(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|_)(\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Error" context="80:STag" String="&lt;(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[:_])(\w|[:_.-])*"/>
- <RegExpr attribute="Error" context="85:ETag" String="&lt;/[xX][mM][lL](\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Normal Tag" context="85:ETag" String="&lt;/(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|_)(\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Error" context="85:ETag" String="&lt;/(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[:_])(\w|[:_.-])*"/>
- <RegExpr attribute="Entity" context="#stay" String="&amp;(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*;"/>
- <RegExpr attribute="Entity" context="#stay" String="&amp;#(x[0-9a-fA-F]+|[0-9]+);"/>
- <RegExpr attribute="Entity" context="86:CDSect" String="&lt;!\[CDATA\["/>
- <RegExpr attribute="Comment" context="87:Comment inside IS" String="&lt;!--"/>
- <RegExpr attribute="Normal Tag" context="88:PI inside IS" String="&lt;\?xml-stylesheet(\s|$)"/>
- <RegExpr attribute="Error" context="88:PI inside IS" String="&lt;\?[xX][mM][lL](\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Normal Tag" context="88:PI inside IS" String="&lt;\?(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|_)(\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Error" context="88:PI inside IS" String="&lt;\?(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[:_])(\w|[:_.-])*"/>
- <DetectChar attribute="Error" context="#stay" char="&lt;"/>
- <DetectChar attribute="Error" context="#stay" char="&amp;"/>
- <RegExpr attribute="Error" context="#stay" String="\]\]>"/>
- </context>
-
- <context name="80:STag" attribute="Error" lineEndContext="#stay">
- <Detect2Chars attribute="Normal Tag" context="79:Outside" char="/" char1="&gt;"/>
- <DetectChar attribute="Normal Tag" context="79:Outside" char="&gt;"/>
- <RegExpr attribute="Attribute" context="81:STag Attribute" String="(xmlns:(\w|[_.-])*|xmlns|xml:(lang|base|space))"/>
- <RegExpr attribute="Error" context="81:STag Attribute" String="[xX][mM][lL](\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Attribute" context="81:STag Attribute" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|_)(\w|[_.-])*(:(\w|[_.-])+)?"/>
- <RegExpr attribute="Error" context="81:STag Attribute" String="(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[:_])(\w|[:_.-])*"/>
- <RegExpr attribute="Normal Tag" context="#stay" String="\s+"/>
- </context>
-
- <context name="81:STag Attribute" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Attribute" context="82:STag Attribute Value" char="="/>
- <RegExpr attribute="Normal Tag" context="#stay" String="\s+"/>
- </context>
-
- <context name="82:STag Attribute Value" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Value" context="83:STag Value qq" char="&quot;"/>
- <DetectChar attribute="Value" context="84:STag Value q" char="'"/>
- <RegExpr attribute="Normal Tag" context="#stay" String="\s+"/>
- </context>
-
- <context name="83:STag Value qq" attribute="Value" lineEndContext="#stay">
- <RegExpr attribute="Entity" context="#stay" String="&amp;(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*;"/>
- <RegExpr attribute="Entity" context="#stay" String="&amp;#(x[0-9a-fA-F]+|[0-9]+);"/>
- <DetectChar attribute="Error" context="#stay" char="&amp;"/>
- <DetectChar attribute="Error" context="#stay" char="&lt;"/>
- <RegExpr attribute="Error" context="80:STag" String="&quot;(?=(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:]))"/>
- <RegExpr attribute="Value" context="80:STag" String="&quot;(?=>|/>|\s|$)"/>
- </context>
-
- <context name="84:STag Value q" attribute="Value" lineEndContext="#stay">
- <RegExpr attribute="Entity" context="#stay" String="&amp;(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:])(\w|[_:.-])*;"/>
- <RegExpr attribute="Entity" context="#stay" String="&amp;#(x[0-9a-fA-F]+|[0-9]+);"/>
- <DetectChar attribute="Error" context="#stay" char="&amp;"/>
- <DetectChar attribute="Error" context="#stay" char="&lt;"/>
- <RegExpr attribute="Error" context="80:STag" String="'(?=(?![&#x0660;-&#x0669;&#x06F0;-&#x06F9;&#x0966;-&#x096F;&#x09E6;-&#x09EF;&#x0A66;-&#x0A6F;&#x0AE6;-&#x0AEF;&#x0B66;-&#x0B6F;&#x0BE7;-&#x0BEF;&#x0C66;-&#x0C6F;&#x0CE6;-&#x0CEF;&#x0D66;-&#x0D6F;&#x0E50;-&#x0E59;&#x0ED0;-&#x0ED9;&#x0F20;-&#x0F29;]|\d)(\w|[_:]))"/>
- <RegExpr attribute="Value" context="80:STag" String="'(?=>|/>|\s|$)"/>
- </context>
-
- <context name="85:ETag" attribute="Error" lineEndContext="#stay">
- <DetectChar attribute="Normal Tag" context="79:Outside" char="&gt;"/>
- <RegExpr attribute="Normal Tag" context="#stay" String="\s+"/>
- </context>
-
- <context name="86:CDSect" attribute="Normal Text" lineEndContext="#stay">
- <RegExpr attribute="Entity" context="79:Outside" String="\]\]>"/>
- </context>
-
- <context name="87:Comment inside IS" attribute="Comment" lineEndContext="#stay">
- <RegExpr attribute="Error" context="79:Outside" String="--->"/>
- <RegExpr attribute="Comment" context="79:Outside" String="-->"/>
- <Detect2Chars attribute="Error" context="#stay" char="-" char1="-"/>
- </context>
-
- <context name="88:PI inside IS" attribute="Processing Instruction Body" lineEndContext="#stay">
- <Detect2Chars attribute="Processing Instruction" context="79:Outside" char="?" char1="&gt;"/>
- </context>
-
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Entity" defStyleNum="dsChar"/>
- <itemData name="Normal Tag" defStyleNum="dsKeyword"/>
- <itemData name="Attribute" defStyleNum="dsDataType"/>
- <itemData name="Value" defStyleNum="dsString"/>
- <itemData name="Doctype Declaration" defStyleNum="dsKeyword"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Processing Instruction" defStyleNum="dsKeyword"/>
- <itemData name="PI content" defStyleNum="dsOthers"/>
- <itemData name="Stylesheet" defStyleNum="dsKeyword"/>
- <itemData name="Error" defStyleNum="dsDecVal"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="multiLine" start="&lt;!--" end="--&gt;"/>
- </comments>
- <keywords casesensitive="1"/>
- </general>
-</language>
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE language SYSTEM "language.dtd">
-<language name="yacas" version="1.0" kateversion="2.1" section="Sources" extensions="*.ys" mimetype="text/x-yacassrc">
- <highlighting>
- <list name="keywords">
- <item> And </item>
- <item> ApplyPure </item>
- <item> ArrayCreate </item>
- <item> ArrayGet </item>
- <item> ArraySet </item>
- <item> ArraySize </item>
- <item> Atom </item>
- <item> Berlekamp </item>
- <item> BitAnd </item>
- <item> BitOr </item>
- <item> BitXor </item>
- <item> Bodied </item>
- <item> CTokenizer </item>
- <item> Check </item>
- <item> Clear </item>
- <item> CommonLispTokenizer </item>
- <item> Concat </item>
- <item> ConcatStrings </item>
- <item> CurrentFile </item>
- <item> CurrentLine </item>
- <item> CustomEval </item>
- <item> CustomEval'Expression </item>
- <item> CustomEval'Locals </item>
- <item> CustomEval'Result </item>
- <item> CustomEval'Stop </item>
- <item> DefLoad </item>
- <item> DefLoadFunction </item>
- <item> DefMacroRuleBase </item>
- <item> DefMacroRuleBaseListed </item>
- <item> DefaultDirectory </item>
- <item> DefaultTokenizer </item>
- <item> Delete </item>
- <item> DestructiveDelete </item>
- <item> DestructiveInsert </item>
- <item> DestructiveReplace </item>
- <item> DestructiveReverse </item>
- <item> DllEnumerate </item>
- <item> DllLoad </item>
- <item> DllUnload </item>
- <item> Equals </item>
- <item> Eval </item>
- <item> FastArcCos </item>
- <item> FastArcSin </item>
- <item> FastArcTan </item>
- <item> FastAssoc </item>
- <item> FastCos </item>
- <item> FastExp </item>
- <item> FastIsPrime </item>
- <item> FastLog </item>
- <item> FastPower </item>
- <item> FastSin </item>
- <item> FastTan </item>
- <item> FindFile </item>
- <item> FindFunction </item>
- <item> FlatCopy </item>
- <item> FromBase </item>
- <item> FromFile </item>
- <item> FromString </item>
- <item> FullForm </item>
- <item> GarbageCollect </item>
- <item> GenericTypeName </item>
- <item> GetExtraInfo </item>
- <item> GetPrecision </item>
- <item> GreaterThan </item>
- <item> Head </item>
- <item> Hold </item>
- <item> HoldArg </item>
- <item> If </item>
- <item> Infix </item>
- <item> Insert </item>
- <item> IsAtom </item>
- <item> IsBodied </item>
- <item> IsBound </item>
- <item> IsFunction </item>
- <item> IsGeneric </item>
- <item> IsInfix </item>
- <item> IsInteger </item>
- <item> IsList </item>
- <item> IsNumber </item>
- <item> IsPostfix </item>
- <item> IsPrefix </item>
- <item> IsString </item>
- <item> LazyGlobal </item>
- <item> LeftPrecedence </item>
- <item> Length </item>
- <item> LessThan </item>
- <item> LispRead </item>
- <item> LispReadListed </item>
- <item> List </item>
- <item> Listify </item>
- <item> Load </item>
- <item> Local </item>
- <item> LocalSymbols </item>
- <item> MacroClear </item>
- <item> MacroLocal </item>
- <item> MacroRule </item>
- <item> MacroRuleBase </item>
- <item> MacroRuleBaseListed </item>
- <item> MacroRulePattern </item>
- <item> MacroSet </item>
- <item> MathAbs </item>
- <item> MathAdd </item>
- <item> MathAnd </item>
- <item> MathArcCos </item>
- <item> MathArcSin </item>
- <item> MathArcTan </item>
- <item> MathCeil </item>
- <item> MathCos </item>
- <item> MathDiv </item>
- <item> MathDivide </item>
- <item> MathExp </item>
- <item> MathFac </item>
- <item> MathFloor </item>
- <item> MathGcd </item>
- <item> MathGetExactBits </item>
- <item> MathLibrary </item>
- <item> MathLog </item>
- <item> MathMod </item>
- <item> MathMultiply </item>
- <item> MathNot </item>
- <item> MathNth </item>
- <item> MathOr </item>
- <item> MathPi </item>
- <item> MathPower </item>
- <item> MathSetExactBits </item>
- <item> MathSin </item>
- <item> MathSqrt </item>
- <item> MathSubtract </item>
- <item> MathTan </item>
- <item> MaxEvalDepth </item>
- <item> Not </item>
- <item> OpLeftPrecedence </item>
- <item> OpPrecedence </item>
- <item> OpRightPrecedence </item>
- <item> Or </item>
- <item> PatchLoad </item>
- <item> PatchString </item>
- <item> PatternCreate </item>
- <item> PatternMatches </item>
- <item> Postfix </item>
- <item> Precision </item>
- <item> Prefix </item>
- <item> PrettyPrinter </item>
- <item> Prog </item>
- <item> Read </item>
- <item> ReadToken </item>
- <item> Replace </item>
- <item> Retract </item>
- <item> RightAssociative </item>
- <item> RightPrecedence </item>
- <item> Rule </item>
- <item> RuleBase </item>
- <item> RuleBaseArgList </item>
- <item> RuleBaseDefined </item>
- <item> RuleBaseListed </item>
- <item> RulePattern </item>
- <item> Secure </item>
- <item> Set </item>
- <item> SetExtraInfo </item>
- <item> SetStringMid </item>
- <item> ShiftLeft </item>
- <item> ShiftRight </item>
- <item> String </item>
- <item> StringMid </item>
- <item> Subst </item>
- <item> SystemCall </item>
- <item> Tail </item>
- <item> ToBase </item>
- <item> ToFile </item>
- <item> ToString </item>
- <item> TraceRule </item>
- <item> TraceStack </item>
- <item> Type </item>
- <item> UnFence </item>
- <item> UnList </item>
- <item> Use </item>
- <item> Version </item>
- <item> While </item>
- <item> Write </item>
- <item> WriteString </item>
- <item> XmlExplodeTag </item>
- <item> XmlTokenizer </item>
- <item> ` </item>
- <item> = </item>
- </list>
- <contexts>
- <context name="default" attribute="Normal Text" lineEndContext="#stay">
- <DetectChar attribute="String" context="string" char="&quot;"/>
- <Detect2Chars attribute="Comment" context="linecomment" char="/" char1="/"/>
- <Detect2Chars attribute="Comment" context="multilinecomment" char="/" char1="*"/>
- <DetectChar attribute="Parens" context="#stay" char="{" beginRegion="Brace" />
- <DetectChar attribute="Parens" context="#stay" char="}" endRegion="Brace" />
- <DetectChar attribute="Parens" context="#stay" char="[" beginRegion="Bracket" />
- <DetectChar attribute="Parens" context="#stay" char="]" endRegion="Bracket" />
- <DetectChar attribute="Parens" context="#stay" char="(" beginRegion="Paren" />
- <DetectChar attribute="Parens" context="#stay" char=")" endRegion="Paren" />
- <keyword attribute="Keyword" context="#stay" String="keywords"/>
- <AnyChar attribute="Symbol" context="#stay" String="+-*/=`~:!@#$^&amp;*_|&lt;&gt;"/>
-
- <Float attribute="Float" context="#stay"/>
- <Int attribute="Decimal" context="#stay"/>
- </context>
- <context name="string" attribute="String" lineEndContext="#pop">
- <LineContinue attribute="String" context="#stay"/>
- <DetectChar attribute="String" context="#pop" char="&quot;"/>
- </context>
- <context name="linecomment" attribute="Comment" lineEndContext="#pop">
- <RegExpr attribute="Highlight" context="#stay" String="(FIXME|TODO)" />
- </context>
- <context name="multilinecomment" attribute="Comment" lineEndContext="#stay">
- <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/"/>
- <RegExpr attribute="Highlight" context="#stay" String="(FIXME|TODO)" />
- </context>
- </contexts>
- <itemDatas>
- <itemData name="Normal Text" defStyleNum="dsNormal"/>
- <itemData name="Keyword" defStyleNum="dsKeyword"/>
- <itemData name="Decimal" defStyleNum="dsDecVal"/>
- <itemData name="Float" defStyleNum="dsFloat"/>
- <itemData name="Char" defStyleNum="dsChar"/>
- <itemData name="String" defStyleNum="dsString"/>
- <itemData name="Comment" defStyleNum="dsComment"/>
- <itemData name="Symbol" defStyleNum="dsOthers"/>
- <itemData name="Parens" defStyleNum="dsNormal"/>
- <itemData name="Highlight" defStyleNum="dsString"/>
- </itemDatas>
- </highlighting>
- <general>
- <comments>
- <comment name="singleLine" start="//" />
- <comment name="multiLine" start="/*" end="*/" />
- </comments>
- <keywords casesensitive="1" />
- </general>
-</language>
diff --git a/bench/output b/bench/output
deleted file mode 100644
index 2805f92..0000000
--- a/bench/output
+++ /dev/null
@@ -1,18 +0,0 @@
-RUBY:
-L:\root\trunk>ruby -rubygems -Ilib bench\bench.rb ruby comp
- user system total real
-CodeRay 1.042000 0.010000 1.052000 ( 1.092000)
- 91.58 KB/sec (100.0 KB) 21.38 KTok/sec
-Syntax 9.854000 0.110000 9.964000 ( 9.984000)
- 10.02 KB/sec
-SilverCity 0.000000 0.000000 0.000000 ( 6.209000)
- 16.11 KB/sec
-
-C++:
-L:\root\trunk>ruby -rubygems -Ilib bench\bench.rb cpp comp
- user system total real
-CodeRay 0.431000 0.030000 0.461000 ( 0.471000)
- 212.31 KB/sec (100.0 KB) 33.30 KTok/sec
-Syntax [not available]
-SilverCity 0.000000 0.010000 0.010000 ( 7.261000)
- 13.77 KB/sec
diff --git a/bench/strange.c b/bench/strange.c
deleted file mode 100644
index 42f339d..0000000
--- a/bench/strange.c
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "ruby.h" /*
- /sLaSh *
- oBfUsCaTeD RuBy *
- cOpYrIgHt 2005 *
-bY SiMoN StRaNdGaArD *
- #{X=320;Y=200;Z=20} */
-
-#define GUN1 42:
-#define GUN2 43:
-#define bo do
-#define when(gun) /**/
-#define DATA "p 'Hello embedded world'"
-#define DIRTY(argc,argv)\
-argc,argv,char=eval(\
-"#{DATA.read}\n[3,2,1]"\
-);sun=O.new\
-if(0)
-
-int
-sun[]={12,9,16,9,2,1,7,1,3,9,27,4, 13,2,11,5,4,1,25,
-5,0,1,14,9,15,4,26,9,23,2,17,6,31, 6,10,8,22,9,21,1,
-24,8,20,8,18,9,29,5,9,5,1,1,28,8,8,1,30, 9,6,8, 5,1,
-19,9,36,19,43, 9,34,11,50,19,48,18,49,9, 35,8,42,18,
-51,8,44,11,32, 11,47,9,37,1,39,9,38,19, 45,8,40,12,
-41,9,46,12,33,1,57,1,85,5,88,28,83,4,87, 6,62,28,89,
-9,80,28,60,21,52,21,72,29,54,21,75,8,70,29,58,28,65,
-9,91,8,74,29,79,2,77,1,53,1,81,5, 69,2,64,21, 86,29,
-67,9,59,1,61,5,73,6,76,28,56,21,68,29,78,29,63,5,66,
-28,90,29, 71,4,55,9,84,28,82,29,101,5, 103,9, 98,35,
-97,1,94,35,93,1,100,35,92,31,99,5,96,39,95,5,102,35};
-
-void run(int gun=0) { // [gun]=[:GUN1,:GUN2]
- printf("run() %i\n", gun);
- switch(gun) {
- case GUN1 when(2)
- printf("when2\n");
- break; // end
- case GUN2 when(3)
- printf("when3\n");
- break; // end
- }
-}
-
-int main(int argc, char** argv) {
- printf("hello world. number of arguments=%i\n", argc);
- int fun=5;
- bo {
- fun -= 1; //.id - gun = fun
- run(fun);
- } while(fun>0);
- ruby_init();
- rb_eval_string(DATA);
- return 0;
-}
-
-# if 0 // nobody reads un-defined code
-def goto*s;$s=[];Y.times{s=[];X.times{s<<[0]*3};$s<< s}end;A=0.5
-include Math;def u g,h,i,j,k,l;f,*m=((j-h).abs>(k-i).abs)?[proc{
-|n,o| g[o] [n ]=l },[h ,i ],[j,k]]:[proc{
-|p,q| g[ p][ q] =l} ,[ i,h ], [k,j]];b,a=m.sort
-c,d=a [1 ]-b [1 ],a [0 ]-b [0 ];d.times{|e|f.
-call( e+b[ 0] ,c* e/d+b [1])};end;V=0;def bo&u
-$u||= V; ;$u += 1+V ;; return u.call if$u>1;q=128.0
-;x=(V .. 255 ). map {| y|f1,z =sin(y.to_f*PI/q),
-sin(( y. to_f + 200 )*PI/( q));[(f1*30.0+110.0).
-to_i,((f1+z)*10.0+40.0).to_i,(z*20.0+120.0).to_i]};Y.times{|i|X.
-times{|j|i1=((i*0.3+150)*(j*1.1+50)/50.0).to_i;i2=((i*0.8+510)*(
-j*0.9+1060)/51.0).to_i;$s[i][j]=x[(i1*i2)%255].clone}};$a=(0..25).
-inject([]){|a,i|a<<(V..3).inject([]){|r,j|r<<$c[i*4+j]}};u.call;end
-I=LocalJumpError;def run*a,&b;return if a.size==V;if a[V]==666;$b=b
-elsif$b;$b.call;end;end;def main s,&u;$m=V;u.call rescue I;end
-def rb_eval_string(*a);end # you promised not to look here
-def ruby_init;q=2.0;l=((X**q)*A+(Y**q)*A)**A;V.upto(Y-4){|s|V.
-upto(X-4){|q|d=((q-X/A)**q+(s-Y/A)**q)**A;e=(cos(d*PI/(l/q))/q
-+A)*3.0+1.0;v=2;f=v/e;a,p,b=$s[s],$s[s+1],$s[s+v];r=a[q][V]*e+
-p[q][V]+a[q+1][V]+b[q][V]+a[q+v][V]+b[q+v/v][V]+p[q+v][V]+b[q+
-v][V]*f;g=[a[q][V],b[q][V],a[q+v][V],b[q+v][V]];h=(g.max-g.min
-)*f;$s[s][q][V]=[[(r/(e+f+6.0)+A+(h*0.4)).to_i,255].min,V].max
-}};File.open("res.ppm","w+"){|f|f.write(# secret.greetings :-)
-"P3\n# res.ppm\n#{X} #{Y}\n255\n"+$s.map{|a|a.map{|b|b.join' '
-}.join(' ')+"\n"}.join)};end;def switch i,&b;b.call;return unless
-defined?($m);b=(X*0.01).to_i;d=1.0/40.0;e=0.09;c=(Y*0.01).to_i
-a=$a.map{|(f,g,h,j)|[f*d,g*e,h*d,j*e]};a.each{|(k,l,m,n)|u($s,(k*X
-).to_i+b+i,(l*Y).to_i+c+i,(m*X).to_i+b+i,(n*Y).to_i+c+i,[Z]*3)}
-a.each{|(o,q,r,s)|u($s,(o*(X-Z)).to_i+i,(q*(Y-Z)).to_i+i,(r*(X-
-Z)).to_i+i,(s*(Y-Z)).to_i+i,[(1<<8)-1]*3)};end;Q=Object;class
-Regexp;def []=(v,is);is.each{|s|Q.send(:remove_const,s)if Q.
-const_defined? s;Q.const_set(s,v)};end;end;def int*ptr;666
-end;class O;def []=(a,b=nil);$c=a;end;end;alias:void:goto
-#endif // pretend as if you havn't seen anything
diff --git a/bench/strange.ruby b/bench/strange.ruby
deleted file mode 100644
index 6ff93ee..0000000
--- a/bench/strange.ruby
+++ /dev/null
@@ -1,328 +0,0 @@
-a.each{|el|anz[el]=anz[el]?anz[el]+1:1}
-while x<10000
-#a bis f dienen dazu die Nachbarschaft festzulegen. Man stelle sich die #Zahl von 1 bis 64 im Binärcode vor 1 bedeutet an 0 aus
- b=(p[x]%32)/16<1 ? 0 : 1
-
- (x-102>=0? n[x-102].to_i : 0)*a+(x-101>=0?n[x-101].to_i : 0)*e+n[x-100].to_i+(x-99>=0? n[x-99].to_i : 0)*f+(x-98>=0? n[x-98].to_i : 0)*a+
- n[x+199].to_i*b+n[x+200].to_i*d+n[x+201].to_i*b
-
-#und die Ausgabe folgt
-g=%w{}
-x=0
-
-while x<100
- puts"#{g[x]}"
- x+=1
-end
-
-puts""
-sleep(10)
-
-1E1E1
-puts 30.send(:/, 5) # prints 6
-
-"instance variables can be #@included, #@@class_variables\n and #$globals as well."
-`instance variables can be #@included, #@@class_variables\n and #$globals as well.`
-'instance variables can be #@included, #@@class_variables\n and #$globals as well.'
-/instance variables can be #@included, #@@class_variables\n and #$globals as well./mousenix
-:"instance variables can be #@included, #@@class_variables\n and #$globals as well."
-:'instance variables can be #@included, #@@class_variables\n and #$globals as well.'
-%'instance variables can be #@included, #@@class_variables\n and #$globals as well.'
-%q'instance variables can be #@included, #@@class_variables\n and #$globals as well.'
-%Q'instance variables can be #@included, #@@class_variables\n and #$globals as well.'
-%w'instance variables can be #@included, #@@class_variables\n and #$globals as well.'
-%W'instance variables can be #@included, #@@class_variables\n and #$globals as well.'
-%s'instance variables can be #@included, #@@class_variables\n and #$globals as well.'
-%r'instance variables can be #@included, #@@class_variables\n and #$globals as well.'
-%x'instance variables can be #@included, #@@class_variables\n and #$globals as well.'
-
-#%W[ but #@0illegal_values look strange.]
-
-%s#ruby allows strange#{constructs}
-%s#ruby allows strange#$constructs
-%s#ruby allows strange#@@constructs
-
-%r\VERY STRANGE!\x00
-%x\VERY STRANGE!\x00
-
-~%r#<XMP>#i .. ~%r#</XMP>#i;
-
-a = <<"EOF"
-This is a multiline #$here document
-terminated by EOF on a line by itself
-EOF
-
-a = <<'EOF'
-This is a multiline #$here document
-terminated by EOF on a line by itself
-EOF
-
-b=(p[x] %32)/16<1 ? 0 : 1
-
-#<<""
-<<"X"
-#{test}
-#@bla
-#die suppe!!!
-\xfffff
-
-
-super <<-EOE % [
- EOE
-
-<<X
-X
-X
-%s(uninter\)pre\ted)
-%q(uninter\)pre\ted)
-%Q(inter\)pre\ted)
-:"inter\)pre\ted"
-:'uninter\'pre\ted'
-
-%q[haha! [nesting [rocks] ] ! ]
-
-%Q[hehe! #{ %Q]nesting #{"really"} rocks] } ! ]
-
-"but it #{<<may} break"
-the code.
-may
-
-# this is a known bug.
-p <<this
-but it may break #{<<that}
-code.
-that
-this
-that
-
-##################################################################
-class NP
-def initialize a=@p=[], b=@b=[]; end
-def +@;@b<<1;b2c end;def-@;@b<<0;b2c end
-def b2c;if @b.size==8;c=0;@b.each{|b|c<<=1;c|=b};send(
- 'lave'.reverse,(@p.join))if c==0;@p<<c.chr;@b=[] end
- self end end ; begin _ = NP.new end
-c
-# ^ This is a bug :(
-
-# The Programming Language `NegaPosi'
-+-+--++----+--+-+++--+-------+--++--+++---+-+++-+-+-+++-----+++-_
-+--++++--+---++-+-+-+++--+--+-+------+--++++-++---++-++---++-++-_
-+++--++-+-+--++--+++--+------+----+--++--+++-++-+----++------+--_
--+-+----+++--+--+----+--+--+-++-++--+++-++++-++-----+-+-+----++-_
----------+-+---- _
-##################################################################
-
-
-# date: 03/18/2004
-# title: primes less than 1000 ( 2005 Obfuscated Ruby Contest )
-# author: Jim Lawless
-# email: jimbo at radiks dotski net
-# comments: This program will display all positive prime integers
-# less than 1000. Program licens is the same as the Ruby
-# license ( http://www.ruby-lang.org/en/LICENSE.txt )
-
- $e=""
-
-def a()
- $a=$a+1
-end
-
-def b()
- $a=$a+5
-end
-
-def c()
- $e=$e+$a.chr
-end
-
-def d()
- $a=10
-end
-
-def e()
- $a=$a+16
-end
-
-d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;e;e;a;a;a;c;d;e;e;b;b;
-a;c;d;c;d;e;e;e;e;e;e;b;b;a;a;a;c;d;e;e;e;e;e;b;b;a;a;a;a;c;d;e;e;e;e;
-e;b;b;a;a;a;a;a;c;d;e;e;e;e;e;e;a;a;c;d;e;e;e;e;e;b;b;a;c;d;e;b;a;c;
-d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;e;e;a;a;c;d;e;e;b;a;a;
-c;d;e;e;b;a;c;d;e;e;b;a;c;d;e;e;b;a;c;d;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;b;
-b;a;a;a;a;a;c;d;e;e;e;a;a;a;c;d;e;e;b;a;a;a;c;d;c;d;e;b;a;a;a;a;a;c;d;e;
-e;e;e;e;b;b;a;a;c;d;e;e;e;e;e;e;a;a;a;a;a;c;d;e;e;e;e;e;e;b;b;a;c;
-d;e;e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;e;e;e;a;a;a;c;d;e;
-e;b;a;c;d;c;d;e;e;e;e;e;e;b;b;a;a;a;c;d;e;e;e;e;e;b;b;a;a;a;a;c;d;e;e;
-e;e;e;b;b;a;a;a;a;a;c;d;e;e;e;e;e;e;a;a;c;d;e;e;e;e;e;b;b;a;c;d;e;b;
-a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;b;b;a;a;a;a;a;c;d;e;e;e;a;a;c;d;e;b;
-a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;b;a;c;d;c;d;e;e;e;e;e;b;b;a;
-a;a;a;a;c;d;e;e;e;e;e;b;b;a;a;c;d;e;b;b;a;a;a;a;c;d;e;b;a;c;d;e;b;b;a;
-a;a;a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;e;a;a;a;a;c;
-d;e;e;e;e;e;e;a;a;a;c;d;e;e;e;e;e;e;a;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;
-a;a;c;d;e;e;e;e;e;e;b;b;a;c;d;e;e;e;e;e;e;a;a;c;d;e;e;e;e;e;e;a;a;a;
-a;a;c;d;e;b;b;a;a;a;a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;b;b;a;a;a;a;a;
-c;d;e;b;b;a;a;a;a;a;c;d;e;b;b;a;a;a;a;a;c;d;e;e;e;a;a;a;c;d;e;e;e;a;a;
-a;c;d;e;e;b;a;c;d;e;b;b;a;a;a;a;a;c;d;e;b;a;c;d;c;d;e;b;a;a;a;a;a;c;d;e;e;
-e;e;e;b;b;a;a;c;d;e;e;e;e;e;e;a;a;a;a;a;c;d;e;e;e;e;e;e;b;b;a;c;d;e;
-e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;e;e;e;a;a;a;c;d;e;e;
-b;a;a;c;d;c;d;e;e;e;e;e;b;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;c;d;e;e;e;e;e;
-b;b;a;c;d;e;e;e;e;e;b;a;a;c;d;e;e;e;e;e;e;a;c;d;c;d;e;e;e;e;e;b;b;a;c;
-d;e;e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;c;d;e;b;a;a;a;a;a;
-c;d;e;e;e;e;e;b;b;a;a;a;a;a;c;d;e;e;e;a;a;a;c;d;e;b;a;a;a;a;a;c;d;e;e;
-e;e;e;b;b;a;a;a;a;a;c;d;e;e;a;c;d;e;e;b;a;a;c;d;c;d;e;e;e;e;e;b;b;a;a;
-a;a;a;c;d;e;e;e;e;e;b;b;a;a;c;d;e;b;a;c;d;e;b;b;a;a;a;a;c;d;e;b;b;a;a;
-a;a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;b;b;a;a;a;a;a;c;d;e;b;b;b;a;c;d;e;
-b;a;a;a;a;a;c;d;e;e;e;e;e;b;b;a;a;a;a;a;c;d;e;b;b;a;a;a;a;a;c;d;e;e;
-e;a;a;a;a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;b;b;a;a;
-a;a;a;c;d;c;d;e;e;e;e;e;b;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;c;d;e;e;e;e;e;
-b;b;a;c;d;e;e;e;e;e;b;a;a;c;d;e;e;e;e;e;e;a;c;d;c;d;e;e;e;e;e;b;b;a;c;
-d;e;e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;c;d;e;e;e;e;e;b;b;
-a;c;d;e;e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;c;d;e;e;e;e;e;
-b;b;a;a;a;a;a;c;d;e;e;e;e;e;b;b;a;a;c;d;e;b;b;a;a;a;a;c;d;e;b;a;a;a;
-a;a;c;d;e;e;e;e;e;b;b;a;a;c;d;e;e;e;e;e;e;a;a;a;a;a;c;d;e;e;e;e;e;e;
-b;b;a;c;d;e;e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;e;e;e;a;
-a;a;c;d;e;e;e;a;a;a;c;d;e;e;b;a;c;d;e;b;b;a;a;a;a;a;c;d;e;b;a;c;d;c;d;e;e;
-e;e;e;e;b;a;c;d;e;e;e;e;e;e;b;b;a;c;d;e;e;e;e;e;e;b;a;a;a;a;a;c;d;e;
-e;e;e;e;e;b;a;a;a;a;c;d;e;b;a;c;d;e;b;a;a;a;c;d;e;b;a;a;a;a;c;d;e;e;e;
-e;e;e;e;a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;e;e;e;e;
-e;e;a;a;a;c;d;e;b;a;c;d;e;e;e;e;e;b;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;
-a;a;a;c;d;e;b;a;c;d;e;e;e;e;e;e;b;a;c;d;e;e;e;e;e;e;b;a;a;a;c;d;e;e;e;
-e;e;b;b;a;a;a;a;a;c;d;e;e;e;e;e;e;a;a;a;c;d;e;e;e;e;e;b;b;a;c;d;e;b;
-a;a;a;c;d;c;d;e;e;e;e;e;b;b;a;c;d;e;e;e;e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;
-a;a;a;a;a;c;d;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;d;e;b;a;c;
-d;e;e;e;a;a;a;c;d;e;b;a;c;d;e;b;a;a;a;a;a;c;d;e;e;e;e;e;e;b;a;a;a;a;c;
-d;e;b;a;c;d;e;e;a;c;d;e;b;a;c;d;e;e;b;a;a;c;d;c;d;e;e;e;e;e;b;b;a;c;d;e;e;e;
-e;e;e;a;a;a;a;c;d;e;e;e;e;e;b;a;a;a;a;a;c;d;c;d;e;b;a;c;d;e;b;a;c;d;e;b;
-a;c;d;e;b;a;c;d;e;b;a;c;d;e;b;a;c;d;e;b;a;c;eval $e
-
-$_=%{q,l= %w{Ruby\\ Quiz Loader}
-n,p,a= "\#{q.do#{%w{w a n c}.sort{|o,t|t<=>o}}se.d\x65l\x65t\x65(' ')}.com/",
-{"bmJzcA==\n".\x75np\x61ck("m")[0]=>" ","bHQ=\n".\x75np\x61ck((?n-1).chr)[0]=>
-:<,"Z3Q=\n".\x75np\x61ck("m")[0]=>:>,"YW1w\n".\x75np\x61ck((?l+1).chr)[0]=>:&},
-[[/^\\s+<\\/div>.+/m,""],[/^\\s+/,""],[/\n/,"\n\n"],[/<br \\/>/,"\n"],
-[/<hr \\/>/,"-="*40],[/<[^>]+>/,""],[/^ruby/,""],[/\n{3,}/,"\n\n"]];p\165ts"
-\#{l[0..-3]}ing...\n\n";send(Kernel.methods.find_all{|x|x[0]==?e}[-1],
-"re\#{q[5...8].downcase}re '111112101110-117114105'.scan(/-|\\\\d{3}/).
-inject(''){|m,v|v.length>1?m+v.to_i.chr: m+v}");o#{%w{e P}.sort.join.downcase
-}n("http://www.\#{n}"){|w|$F=w.read.sc\x61n(/li>.+?"([^"]+)..([^<]+)/)};\160uts\
-"\#{q}\n\n";$F.\145\141ch{|e|i=e[0][/\\d+/];s="%2s. %s"%[i,e[1]];i.to_i%2==0 ?
-\160ut\x73(s) : #{%w{s p}[-1]}rint("%-38s "%s)};p\x72\x69\x6et"\n? ";e\x76al(
-['puts"\n\#{l[0..3]}ing...\n\n"','$c=gets.chomp.to_i'].sort.join(";"));#{111.chr
-}pen("http://www.\#{n}"+$F[$c-1][0]){|n|$_=n.read[/^\\s+<span.+/m];#{('a'.."z").
-to_a[10-5*2]}.e\141ch{|(z,f)|\x67sub!(z,f)};\147sub!(/&(\\w+);/){|y|p.
-ke\171\077($1)?p[$1]:y};while$_=~/([^\n]{81,})/:z=$1.dup;f=$1.dup;f[f.rindex(
-" ",80),1]="\n";f.s\165b!(/\n[ \t]+/,"\n");s\165b!(/\#{R\x65g\x65xp.
-\x65scap\x65(z)}/,f)end};while\040\163ub!(/^(?:[^\n]*\n){20}/, ""):puts"\#$&
---\x4dO\x52E--";g=$_;g#{"\145"}ts;;#{"excited"[0..4].delete("c")}\040if$_[0]==?q
-$_=g;end;$_.d#{"Internet Service Provider".scan(/[A-Z]/).join.downcase
-}lay};eval$_
-
- d=[30644250780,9003106878,
- 30636278846,66641217692,4501790980,
- 671_24_603036,131_61973916,66_606629_920,
- 30642677916,30643069058];a,s=[],$*[0]
- s.each_byte{|b|a<<("%036b"%d[b.
- chr.to_i]).scan(/\d{6}/)}
- a.transpose.each{ |a|
- a.join.each_byte{\
- |i|print i==49?\
- ($*[1]||"#")\
- :32.chr}
- puts
- }
-
-#! /usr/bin/env ruby
-# License: If Ruby is licensed to the general public in a certain way, this is also licensed in that way.
-require'zlib';eval(Zlib::Inflate.inflate("x\332\355WKo\333F\020\276\367W\250\262\001\222\tM\357\246M\017\242\211\242h\200\036\212`\201\026\350\205`\f=h\233\301Zt%\273A-2\277\275\363\315\222\334\241,#v\214\366T\331\262\326\303y\3177\263\243M\371\347]\265)\203UuYnoO\257Wo\203\364>[T\353U\265\276L\257\353\325\235-'\277\226\233ui\323Uy1\251\027\027\341\253\371\346r\e\245u\366\216\205f\263\367\357\336&\353\362S\010zr=\277\3315w\315]r[\237o\333\344c]\255#>\343O\025\352\037\334\177\341\367\364\271\t\003\245\337|\027\304\364aM@:\363\260\316>\237\232\323(\326\252(\327\253\t\275\323\332h\253\224V\306d\247\037\362\371\311}\321\314f\356\363C\016\311\342\365\361ij\026\037\313\345\355\3577\363e\231\224\363\345\325y\315\204]\263l\3620\177\317\241\024M\376\263\235o\267Et\222/\223%\037\213\374D\323\373M\3214Kv-\373<\361\026\233&\\\304\253,\354\270\263\314)\232\3748\311\247]z\216v\3136\235\306\323\243\035\262\263\214\332\f\024\342\257\327\345\264\230\205\313o36\3122\254e2\260\236\2610\202\354\037\260\256 (f=/\313:Z\024\245\313\244Zoo\347\353ey~]\336^\325\253-\a\273k\252fqv6\235\333j\276\355\236tV\252\230\377F\276\n\333\277\257\241\345\206\262\323\306G\273\352\340\203t\332\246\2441`'\316\316\266\245\275H\0032\377l\253\017,=42E\002\360\236\246\345_s;Y\274^\305\367Q\233\036\233\276\016\312\2450=\256=\305U\202\230\254\"\222\265\004\217\237~\373\345\017\"h\243\210\307j\235\251\205V8\353\304X\372!1CGc-\251\240\337\020\317\361#\036\023\n\2556\254Cg3\002}\265\356s\235\202K[K\022\020 \243\206\216\241p3\33255\350\232\036\030q$\233\344!\363\204^},$\023Xg\235:\364r1\"1\344\277\261\207\031(\301DE\260\344\026Y\177\345\036\221\204mP\263\266Mk\305\366\210%3\220\302S\322\306IR\316\377!\203 S\336\310\216\215\203\315\002-\211 5D2\257\210\302\321p\234\364\205\222Jj\220\022E\321h\347\223RQ*94K\022\243\314H`4{LV\003\021N\f\333\364I\347l\327UR\305t\340\332i>\241x=Mu4R\245\373\223\244\251NB\211\247\236\3465\253^bx\332Yc\263\252M\220b\253\220\310\004\331\242\020,`\005T\021Y\251P@\020\365Ax\310z\364\264\240\265vj2\037?0\v\"en\244\374\251\032\225\253v\346\253\3712\215\032\322(o\206~A\006\010\f\324\22357\026\"\316\024\365\021\360@\277:\363.$\f\342\016$\200\v\341\302\230\020\340\341\201K\017\270+i\326-\312\313j\235\n[\376({\330u\254\266\334\034\031\367%:CK\210{\311h\aQH\333Q\023\250\210;e\360\322\362\213\202\247\216\266\340C&(p\274HT7\336&B\352\300\036z\206\204\375 \032z\304\233\217\034\267AK\207R\363\213\324u\334\203\272h\234 \304&\364S\302]|\024\233b\000\023E\034\005\300!\330\2274\026\205\316\363\203\364\"\316\245!\242\360Y?4\204b\023.\2009\036X\300\213p\200]\304\324\200$^\204\025\222D\325X \363\324\004\223\205\207\241M\245\352\341(s\3415\260w\226\313=\2422 \200\177\344\355\211\3350\004\341\217\207\215r%x\030\302\304\230\335{#\250#o\204h\327;\220\242\275B%j&\343e\005\226/\r\200\035\035\206K\243\027\216Z\230\323.\335\356^!\vF\002K\366\246kG\321\364E\301\362\250\275a\f\031\207i%\216\342&ie\205\260\324}\272\252ho\222\306\370\362!}6\364C\003\2717\206'!.\315\036mhMm\370\252\241\365\221g\275\326A\302\254\270X,\371\353\232:\222\321\253\025\217v%\222\023!\243r\272\364(\376\177\236\374\233\363\3048\330b\241xdTp\325\321\377\3428F\234\214\263\357\255f\324\306\226\257\022\"\000\354\003\024C\207\na\353\240&O\305\376\004ncy\350\f\276\357+Q|\201bBi\206\277\345u\251\273\310\367\242\303*\204d\n\271}\016\2345r8\034\201[\343:>\364*\242\266\025+HZ\263e\212\0247q\357\310X\267[\333(9_o}P\201\324>\266\364\000\217hh\352\225a\213q\260\031\334\022sg\360\e\206\234B=\246\2421\341e\364\270\321\224\347\0056L\267\227)\244\210\307\027\257<\343\257\000\303\264u{\235\326\352i\303^\332\200\n\236\243a\277\034J#~S\335'2\371\001q\3745$\356\027^\371\325\344\331\036\362\004\267\330\251<\212\237\257\345kr\371\302d\362r\376\344d\252C\311\374R6\017e\375\005\271yAV\363/\257\345\261(\340hW\020\222\a\027k)60\354\217\363\3501\263rt\0364\025\025|\265\031\355\276d\357\3159\367\225\025\223U\273n\027\324\321H\031\030\036\357\356\377\010\266\337\374\003\3375Q\335"))
-#include "ruby.h" /*
- /sLaSh *
- oBfUsCaTeD RuBy *
- cOpYrIgHt 2005 *
-bY SiMoN StRaNdGaArD *
- #{X=320;Y=200;Z=20} */
-
-#define GUN1 42:
-#define GUN2 43:
-#define bo do
-#define when(gun) /**/
-#define DATA "p 'Hello embedded world'"
-#define DIRTY(argc,argv)\
-argc,argv,char=eval(\
-"#{DATA.read}\n[3,2,1]"\
-);sun=O.new\
-if(0)
-
-int
-sun[]={12,9,16,9,2,1,7,1,3,9,27,4, 13,2,11,5,4,1,25,
-5,0,1,14,9,15,4,26,9,23,2,17,6,31, 6,10,8,22,9,21,1,
-24,8,20,8,18,9,29,5,9,5,1,1,28,8,8,1,30, 9,6,8, 5,1,
-19,9,36,19,43, 9,34,11,50,19,48,18,49,9, 35,8,42,18,
-51,8,44,11,32, 11,47,9,37,1,39,9,38,19, 45,8,40,12,
-41,9,46,12,33,1,57,1,85,5,88,28,83,4,87, 6,62,28,89,
-9,80,28,60,21,52,21,72,29,54,21,75,8,70,29,58,28,65,
-9,91,8,74,29,79,2,77,1,53,1,81,5, 69,2,64,21, 86,29,
-67,9,59,1,61,5,73,6,76,28,56,21,68,29,78,29,63,5,66,
-28,90,29, 71,4,55,9,84,28,82,29,101,5, 103,9, 98,35,
-97,1,94,35,93,1,100,35,92,31,99,5,96,39,95,5,102,35};
-
-void run(int gun=0) { // [gun]=[:GUN1,:GUN2]
- printf("run() %i\n", gun);
- switch(gun) {
- case GUN1 when(2)
- printf("when2\n");
- break; // end
- case GUN2 when(3)
- printf("when3\n");
- break; // end
- }
-}
-
-int main(int argc, char** argv) {
- printf("hello world. number of arguments=%i\n", argc);
- int fun=5;
- bo {
- fun -= 1; //.id - gun = fun
- run(fun);
- } while(fun>0);
- ruby_init();
- rb_eval_string(DATA);
- return 0;
-}
-
-#if 0 // nobody reads un-defined code
-def goto*s;$s=[];Y.times{s=[];X.times{s<<[0]*3};$s<< s}end;A=0.5
-include Math;def u g,h,i,j,k,l;f,*m=((j-h).abs>(k-i).abs)?[proc{
-|n,o| g[o] [n ]=l },[h ,i ],[j,k]]:[proc{
-|p,q| g[ p][ q] =l} ,[ i,h ], [k,j]];b,a=m.sort
-c,d=a [1 ]-b [1 ],a [0 ]-b [0 ];d.times{|e|f.
-call( e+b[ 0] ,c* e/d+b [1])};end;V=0;def bo&u
-$u||= V; ;$u += 1+V ;; return u.call if$u>1;q=128.0
-;x=(V .. 255 ). map {| y|f1,z =sin(y.to_f*PI/q),
-sin(( y. to_f + 200 )*PI/( q));[(f1*30.0+110.0).
-to_i,((f1+z)*10.0+40.0).to_i,(z*20.0+120.0).to_i]};Y.times{|i|X.
-times{|j|i1=((i*0.3+150)*(j*1.1+50)/50.0).to_i;i2=((i*0.8+510)*(
-j*0.9+1060)/51.0).to_i;$s[i][j]=x[(i1*i2)%255].clone}};$a=(0..25).
-inject([]){|a,i|a<<(V..3).inject([]){|r,j|r<<$c[i*4+j]}};u.call;end
-I=LocalJumpError;def run*a,&b;return if a.size==V;if a[V]==666;$b=b
-elsif$b;$b.call;end;end;def main s,&u;$m=V;u.call rescue I;end
-def rb_eval_string(*a);end # you promised not to look here
-def ruby_init;q=2.0;l=((X**q)*A+(Y**q)*A)**A;V.upto(Y-4){|s|V.
-upto(X-4){|q|d=((q-X/A)**q+(s-Y/A)**q)**A;e=(cos(d*PI/(l/q))/q
-+A)*3.0+1.0;v=2;f=v/e;a,p,b=$s[s],$s[s+1],$s[s+v];r=a[q][V]*e+
-p[q][V]+a[q+1][V]+b[q][V]+a[q+v][V]+b[q+v/v][V]+p[q+v][V]+b[q+
-v][V]*f;g=[a[q][V],b[q][V],a[q+v][V],b[q+v][V]];h=(g.max-g.min
-)*f;$s[s][q][V]=[[(r/(e+f+6.0)+A+(h*0.4)).to_i,255].min,V].max
-}};File.open("res.ppm","w+"){|f|f.write(# secret.greetings :-)
-"P3\n# res.ppm\n#{X} #{Y}\n255\n"+$s.map{|a|a.map{|b|b.join' '
-}.join(' ')+"\n"}.join)};end;def switch i,&b;b.call;return unless
-defined?($m);b=(X*0.01).to_i;d=1.0/40.0;e=0.09;c=(Y*0.01).to_i
-a=$a.map{|(f,g,h,j)|[f*d,g*e,h*d,j*e]};a.each{|(k,l,m,n)|u($s,(k*X
-).to_i+b+i,(l*Y).to_i+c+i,(m*X).to_i+b+i,(n*Y).to_i+c+i,[Z]*3)}
-a.each{|(o,q,r,s)|u($s,(o*(X-Z)).to_i+i,(q*(Y-Z)).to_i+i,(r*(X-
-Z)).to_i+i,(s*(Y-Z)).to_i+i,[(1<<8)-1]*3)};end;Q=Object;class
-Regexp;def []=(v,is);is.each{|s|Q.send(:remove_const,s)if Q.
-const_defined? s;Q.const_set(s,v)};end;end;def int*ptr;666
-end;class O;def []=(a,b=nil);$c=a;end;end;alias:void:goto
-#endif // pretend as if you havn't seen anything
-=end
-