|
Karsten Hopp |
b5df12 |
To: vim_dev@googlegroups.com
|
|
Karsten Hopp |
b5df12 |
Subject: Patch 7.3.1191
|
|
Karsten Hopp |
b5df12 |
Fcc: outbox
|
|
Karsten Hopp |
b5df12 |
From: Bram Moolenaar <Bram@moolenaar.net>
|
|
Karsten Hopp |
b5df12 |
Mime-Version: 1.0
|
|
Karsten Hopp |
b5df12 |
Content-Type: text/plain; charset=UTF-8
|
|
Karsten Hopp |
b5df12 |
Content-Transfer-Encoding: 8bit
|
|
Karsten Hopp |
b5df12 |
------------
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
Patch 7.3.1191
|
|
Karsten Hopp |
b5df12 |
Problem: Backreference to previous line doesn't work. (Lech Lorens)
|
|
Karsten Hopp |
b5df12 |
Solution: Implement looking in another line.
|
|
Karsten Hopp |
b5df12 |
Files: src/regexp.c, src/regexp_nfa.c, src/testdir/test64.in,
|
|
Karsten Hopp |
b5df12 |
src/testdir/test64.ok
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
*** ../vim-7.3.1190/src/regexp.c 2013-06-08 18:19:39.000000000 +0200
|
|
Karsten Hopp |
b5df12 |
--- src/regexp.c 2013-06-14 20:23:33.000000000 +0200
|
|
Karsten Hopp |
b5df12 |
***************
|
|
Karsten Hopp |
b5df12 |
*** 3519,3524 ****
|
|
Karsten Hopp |
b5df12 |
--- 3519,3525 ----
|
|
Karsten Hopp |
b5df12 |
*(pp) = (savep)->se_u.ptr; }
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
static int re_num_cmp __ARGS((long_u val, char_u *scan));
|
|
Karsten Hopp |
b5df12 |
+ static int match_with_backref __ARGS((linenr_T start_lnum, colnr_T start_col, linenr_T end_lnum, colnr_T end_col, int *bytelen));
|
|
Karsten Hopp |
b5df12 |
static int regmatch __ARGS((char_u *prog));
|
|
Karsten Hopp |
b5df12 |
static int regrepeat __ARGS((char_u *p, long maxcount));
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
***************
|
|
Karsten Hopp |
b5df12 |
*** 4979,4987 ****
|
|
Karsten Hopp |
b5df12 |
case BACKREF + 9:
|
|
Karsten Hopp |
b5df12 |
{
|
|
Karsten Hopp |
b5df12 |
int len;
|
|
Karsten Hopp |
b5df12 |
- linenr_T clnum;
|
|
Karsten Hopp |
b5df12 |
- colnr_T ccol;
|
|
Karsten Hopp |
b5df12 |
- char_u *p;
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
no = op - BACKREF;
|
|
Karsten Hopp |
b5df12 |
cleanup_subexpr();
|
|
Karsten Hopp |
b5df12 |
--- 4980,4985 ----
|
|
Karsten Hopp |
b5df12 |
***************
|
|
Karsten Hopp |
b5df12 |
*** 5023,5089 ****
|
|
Karsten Hopp |
b5df12 |
{
|
|
Karsten Hopp |
b5df12 |
/* Messy situation: Need to compare between two
|
|
Karsten Hopp |
b5df12 |
* lines. */
|
|
Karsten Hopp |
b5df12 |
! ccol = reg_startpos[no].col;
|
|
Karsten Hopp |
b5df12 |
! clnum = reg_startpos[no].lnum;
|
|
Karsten Hopp |
b5df12 |
! for (;;)
|
|
Karsten Hopp |
b5df12 |
! {
|
|
Karsten Hopp |
b5df12 |
! /* Since getting one line may invalidate
|
|
Karsten Hopp |
b5df12 |
! * the other, need to make copy. Slow! */
|
|
Karsten Hopp |
b5df12 |
! if (regline != reg_tofree)
|
|
Karsten Hopp |
b5df12 |
! {
|
|
Karsten Hopp |
b5df12 |
! len = (int)STRLEN(regline);
|
|
Karsten Hopp |
b5df12 |
! if (reg_tofree == NULL
|
|
Karsten Hopp |
b5df12 |
! || len >= (int)reg_tofreelen)
|
|
Karsten Hopp |
b5df12 |
! {
|
|
Karsten Hopp |
b5df12 |
! len += 50; /* get some extra */
|
|
Karsten Hopp |
b5df12 |
! vim_free(reg_tofree);
|
|
Karsten Hopp |
b5df12 |
! reg_tofree = alloc(len);
|
|
Karsten Hopp |
b5df12 |
! if (reg_tofree == NULL)
|
|
Karsten Hopp |
b5df12 |
! {
|
|
Karsten Hopp |
b5df12 |
! status = RA_FAIL; /* outof memory!*/
|
|
Karsten Hopp |
b5df12 |
! break;
|
|
Karsten Hopp |
b5df12 |
! }
|
|
Karsten Hopp |
b5df12 |
! reg_tofreelen = len;
|
|
Karsten Hopp |
b5df12 |
! }
|
|
Karsten Hopp |
b5df12 |
! STRCPY(reg_tofree, regline);
|
|
Karsten Hopp |
b5df12 |
! reginput = reg_tofree
|
|
Karsten Hopp |
b5df12 |
! + (reginput - regline);
|
|
Karsten Hopp |
b5df12 |
! regline = reg_tofree;
|
|
Karsten Hopp |
b5df12 |
! }
|
|
Karsten Hopp |
b5df12 |
!
|
|
Karsten Hopp |
b5df12 |
! /* Get the line to compare with. */
|
|
Karsten Hopp |
b5df12 |
! p = reg_getline(clnum);
|
|
Karsten Hopp |
b5df12 |
! if (clnum == reg_endpos[no].lnum)
|
|
Karsten Hopp |
b5df12 |
! len = reg_endpos[no].col - ccol;
|
|
Karsten Hopp |
b5df12 |
! else
|
|
Karsten Hopp |
b5df12 |
! len = (int)STRLEN(p + ccol);
|
|
Karsten Hopp |
b5df12 |
!
|
|
Karsten Hopp |
b5df12 |
! if (cstrncmp(p + ccol, reginput, &len) != 0)
|
|
Karsten Hopp |
b5df12 |
! {
|
|
Karsten Hopp |
b5df12 |
! status = RA_NOMATCH; /* doesn't match */
|
|
Karsten Hopp |
b5df12 |
! break;
|
|
Karsten Hopp |
b5df12 |
! }
|
|
Karsten Hopp |
b5df12 |
! if (clnum == reg_endpos[no].lnum)
|
|
Karsten Hopp |
b5df12 |
! break; /* match and at end! */
|
|
Karsten Hopp |
b5df12 |
! if (reglnum >= reg_maxline)
|
|
Karsten Hopp |
b5df12 |
! {
|
|
Karsten Hopp |
b5df12 |
! status = RA_NOMATCH; /* text too short */
|
|
Karsten Hopp |
b5df12 |
! break;
|
|
Karsten Hopp |
b5df12 |
! }
|
|
Karsten Hopp |
b5df12 |
!
|
|
Karsten Hopp |
b5df12 |
! /* Advance to next line. */
|
|
Karsten Hopp |
b5df12 |
! reg_nextline();
|
|
Karsten Hopp |
b5df12 |
! ++clnum;
|
|
Karsten Hopp |
b5df12 |
! ccol = 0;
|
|
Karsten Hopp |
b5df12 |
! if (got_int)
|
|
Karsten Hopp |
b5df12 |
! {
|
|
Karsten Hopp |
b5df12 |
! status = RA_FAIL;
|
|
Karsten Hopp |
b5df12 |
! break;
|
|
Karsten Hopp |
b5df12 |
! }
|
|
Karsten Hopp |
b5df12 |
! }
|
|
Karsten Hopp |
b5df12 |
!
|
|
Karsten Hopp |
b5df12 |
! /* found a match! Note that regline may now point
|
|
Karsten Hopp |
b5df12 |
! * to a copy of the line, that should not matter. */
|
|
Karsten Hopp |
b5df12 |
}
|
|
Karsten Hopp |
b5df12 |
}
|
|
Karsten Hopp |
b5df12 |
}
|
|
Karsten Hopp |
b5df12 |
--- 5021,5032 ----
|
|
Karsten Hopp |
b5df12 |
{
|
|
Karsten Hopp |
b5df12 |
/* Messy situation: Need to compare between two
|
|
Karsten Hopp |
b5df12 |
* lines. */
|
|
Karsten Hopp |
b5df12 |
! status = match_with_backref(
|
|
Karsten Hopp |
b5df12 |
! reg_startpos[no].lnum,
|
|
Karsten Hopp |
b5df12 |
! reg_startpos[no].col,
|
|
Karsten Hopp |
b5df12 |
! reg_endpos[no].lnum,
|
|
Karsten Hopp |
b5df12 |
! reg_endpos[no].col,
|
|
Karsten Hopp |
b5df12 |
! NULL);
|
|
Karsten Hopp |
b5df12 |
}
|
|
Karsten Hopp |
b5df12 |
}
|
|
Karsten Hopp |
b5df12 |
}
|
|
Karsten Hopp |
b5df12 |
***************
|
|
Karsten Hopp |
b5df12 |
*** 6505,6510 ****
|
|
Karsten Hopp |
b5df12 |
--- 6448,6522 ----
|
|
Karsten Hopp |
b5df12 |
return val == n;
|
|
Karsten Hopp |
b5df12 |
}
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
+ /*
|
|
Karsten Hopp |
b5df12 |
+ * Check whether a backreference matches.
|
|
Karsten Hopp |
b5df12 |
+ * Returns RA_FAIL, RA_NOMATCH or RA_MATCH.
|
|
Karsten Hopp |
b5df12 |
+ * If "bytelen" is not NULL, it is set to the bytelength of the whole match.
|
|
Karsten Hopp |
b5df12 |
+ */
|
|
Karsten Hopp |
b5df12 |
+ static int
|
|
Karsten Hopp |
b5df12 |
+ match_with_backref(start_lnum, start_col, end_lnum, end_col, bytelen)
|
|
Karsten Hopp |
b5df12 |
+ linenr_T start_lnum;
|
|
Karsten Hopp |
b5df12 |
+ colnr_T start_col;
|
|
Karsten Hopp |
b5df12 |
+ linenr_T end_lnum;
|
|
Karsten Hopp |
b5df12 |
+ colnr_T end_col;
|
|
Karsten Hopp |
b5df12 |
+ int *bytelen;
|
|
Karsten Hopp |
b5df12 |
+ {
|
|
Karsten Hopp |
b5df12 |
+ linenr_T clnum = start_lnum;
|
|
Karsten Hopp |
b5df12 |
+ colnr_T ccol = start_col;
|
|
Karsten Hopp |
b5df12 |
+ int len;
|
|
Karsten Hopp |
b5df12 |
+ char_u *p;
|
|
Karsten Hopp |
b5df12 |
+
|
|
Karsten Hopp |
b5df12 |
+ if (bytelen != NULL)
|
|
Karsten Hopp |
b5df12 |
+ *bytelen = 0;
|
|
Karsten Hopp |
b5df12 |
+ for (;;)
|
|
Karsten Hopp |
b5df12 |
+ {
|
|
Karsten Hopp |
b5df12 |
+ /* Since getting one line may invalidate the other, need to make copy.
|
|
Karsten Hopp |
b5df12 |
+ * Slow! */
|
|
Karsten Hopp |
b5df12 |
+ if (regline != reg_tofree)
|
|
Karsten Hopp |
b5df12 |
+ {
|
|
Karsten Hopp |
b5df12 |
+ len = (int)STRLEN(regline);
|
|
Karsten Hopp |
b5df12 |
+ if (reg_tofree == NULL || len >= (int)reg_tofreelen)
|
|
Karsten Hopp |
b5df12 |
+ {
|
|
Karsten Hopp |
b5df12 |
+ len += 50; /* get some extra */
|
|
Karsten Hopp |
b5df12 |
+ vim_free(reg_tofree);
|
|
Karsten Hopp |
b5df12 |
+ reg_tofree = alloc(len);
|
|
Karsten Hopp |
b5df12 |
+ if (reg_tofree == NULL)
|
|
Karsten Hopp |
b5df12 |
+ return RA_FAIL; /* out of memory!*/
|
|
Karsten Hopp |
b5df12 |
+ reg_tofreelen = len;
|
|
Karsten Hopp |
b5df12 |
+ }
|
|
Karsten Hopp |
b5df12 |
+ STRCPY(reg_tofree, regline);
|
|
Karsten Hopp |
b5df12 |
+ reginput = reg_tofree + (reginput - regline);
|
|
Karsten Hopp |
b5df12 |
+ regline = reg_tofree;
|
|
Karsten Hopp |
b5df12 |
+ }
|
|
Karsten Hopp |
b5df12 |
+
|
|
Karsten Hopp |
b5df12 |
+ /* Get the line to compare with. */
|
|
Karsten Hopp |
b5df12 |
+ p = reg_getline(clnum);
|
|
Karsten Hopp |
b5df12 |
+ if (clnum == end_lnum)
|
|
Karsten Hopp |
b5df12 |
+ len = end_col - ccol;
|
|
Karsten Hopp |
b5df12 |
+ else
|
|
Karsten Hopp |
b5df12 |
+ len = (int)STRLEN(p + ccol);
|
|
Karsten Hopp |
b5df12 |
+
|
|
Karsten Hopp |
b5df12 |
+ if (cstrncmp(p + ccol, reginput, &len) != 0)
|
|
Karsten Hopp |
b5df12 |
+ return RA_NOMATCH; /* doesn't match */
|
|
Karsten Hopp |
b5df12 |
+ if (bytelen != NULL)
|
|
Karsten Hopp |
b5df12 |
+ *bytelen += len;
|
|
Karsten Hopp |
b5df12 |
+ if (clnum == end_lnum)
|
|
Karsten Hopp |
b5df12 |
+ break; /* match and at end! */
|
|
Karsten Hopp |
b5df12 |
+ if (reglnum >= reg_maxline)
|
|
Karsten Hopp |
b5df12 |
+ return RA_NOMATCH; /* text too short */
|
|
Karsten Hopp |
b5df12 |
+
|
|
Karsten Hopp |
b5df12 |
+ /* Advance to next line. */
|
|
Karsten Hopp |
b5df12 |
+ reg_nextline();
|
|
Karsten Hopp |
b5df12 |
+ ++clnum;
|
|
Karsten Hopp |
b5df12 |
+ ccol = 0;
|
|
Karsten Hopp |
b5df12 |
+ if (got_int)
|
|
Karsten Hopp |
b5df12 |
+ return RA_FAIL;
|
|
Karsten Hopp |
b5df12 |
+ }
|
|
Karsten Hopp |
b5df12 |
+
|
|
Karsten Hopp |
b5df12 |
+ /* found a match! Note that regline may now point to a copy of the line,
|
|
Karsten Hopp |
b5df12 |
+ * that should not matter. */
|
|
Karsten Hopp |
b5df12 |
+ return RA_MATCH;
|
|
Karsten Hopp |
b5df12 |
+ }
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
#ifdef BT_REGEXP_DUMP
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
*** ../vim-7.3.1190/src/regexp_nfa.c 2013-06-13 22:59:25.000000000 +0200
|
|
Karsten Hopp |
b5df12 |
--- src/regexp_nfa.c 2013-06-14 20:19:59.000000000 +0200
|
|
Karsten Hopp |
b5df12 |
***************
|
|
Karsten Hopp |
b5df12 |
*** 4367,4380 ****
|
|
Karsten Hopp |
b5df12 |
if (sub->list.multi[subidx].start.lnum < 0
|
|
Karsten Hopp |
b5df12 |
|| sub->list.multi[subidx].end.lnum < 0)
|
|
Karsten Hopp |
b5df12 |
goto retempty;
|
|
Karsten Hopp |
b5df12 |
! /* TODO: line breaks */
|
|
Karsten Hopp |
b5df12 |
! len = sub->list.multi[subidx].end.col
|
|
Karsten Hopp |
b5df12 |
! - sub->list.multi[subidx].start.col;
|
|
Karsten Hopp |
b5df12 |
! if (cstrncmp(regline + sub->list.multi[subidx].start.col,
|
|
Karsten Hopp |
b5df12 |
! reginput, &len) == 0)
|
|
Karsten Hopp |
b5df12 |
{
|
|
Karsten Hopp |
b5df12 |
! *bytelen = len;
|
|
Karsten Hopp |
b5df12 |
! return TRUE;
|
|
Karsten Hopp |
b5df12 |
}
|
|
Karsten Hopp |
b5df12 |
}
|
|
Karsten Hopp |
b5df12 |
else
|
|
Karsten Hopp |
b5df12 |
--- 4367,4393 ----
|
|
Karsten Hopp |
b5df12 |
if (sub->list.multi[subidx].start.lnum < 0
|
|
Karsten Hopp |
b5df12 |
|| sub->list.multi[subidx].end.lnum < 0)
|
|
Karsten Hopp |
b5df12 |
goto retempty;
|
|
Karsten Hopp |
b5df12 |
! if (sub->list.multi[subidx].start.lnum == reglnum
|
|
Karsten Hopp |
b5df12 |
! && sub->list.multi[subidx].end.lnum == reglnum)
|
|
Karsten Hopp |
b5df12 |
{
|
|
Karsten Hopp |
b5df12 |
! len = sub->list.multi[subidx].end.col
|
|
Karsten Hopp |
b5df12 |
! - sub->list.multi[subidx].start.col;
|
|
Karsten Hopp |
b5df12 |
! if (cstrncmp(regline + sub->list.multi[subidx].start.col,
|
|
Karsten Hopp |
b5df12 |
! reginput, &len) == 0)
|
|
Karsten Hopp |
b5df12 |
! {
|
|
Karsten Hopp |
b5df12 |
! *bytelen = len;
|
|
Karsten Hopp |
b5df12 |
! return TRUE;
|
|
Karsten Hopp |
b5df12 |
! }
|
|
Karsten Hopp |
b5df12 |
! }
|
|
Karsten Hopp |
b5df12 |
! else
|
|
Karsten Hopp |
b5df12 |
! {
|
|
Karsten Hopp |
b5df12 |
! if (match_with_backref(
|
|
Karsten Hopp |
b5df12 |
! sub->list.multi[subidx].start.lnum,
|
|
Karsten Hopp |
b5df12 |
! sub->list.multi[subidx].start.col,
|
|
Karsten Hopp |
b5df12 |
! sub->list.multi[subidx].end.lnum,
|
|
Karsten Hopp |
b5df12 |
! sub->list.multi[subidx].end.col,
|
|
Karsten Hopp |
b5df12 |
! bytelen) == RA_MATCH)
|
|
Karsten Hopp |
b5df12 |
! return TRUE;
|
|
Karsten Hopp |
b5df12 |
}
|
|
Karsten Hopp |
b5df12 |
}
|
|
Karsten Hopp |
b5df12 |
else
|
|
Karsten Hopp |
b5df12 |
*** ../vim-7.3.1190/src/testdir/test64.in 2013-06-13 20:19:35.000000000 +0200
|
|
Karsten Hopp |
b5df12 |
--- src/testdir/test64.in 2013-06-14 20:01:56.000000000 +0200
|
|
Karsten Hopp |
b5df12 |
***************
|
|
Karsten Hopp |
b5df12 |
*** 486,491 ****
|
|
Karsten Hopp |
b5df12 |
--- 486,497 ----
|
|
Karsten Hopp |
b5df12 |
:.yank
|
|
Karsten Hopp |
b5df12 |
Go?p:"
|
|
Karsten Hopp |
b5df12 |
:"
|
|
Karsten Hopp |
b5df12 |
+ :" Check using a backref matching in a previous line
|
|
Karsten Hopp |
b5df12 |
+ /^Backref:
|
|
Karsten Hopp |
b5df12 |
+ /\v.*\/(.*)\n.*\/\1$
|
|
Karsten Hopp |
b5df12 |
+ :.yank
|
|
Karsten Hopp |
b5df12 |
+ Go?p:"
|
|
Karsten Hopp |
b5df12 |
+ :"
|
|
Karsten Hopp |
b5df12 |
:" Check a pattern with a look beind crossing a line boundary
|
|
Karsten Hopp |
b5df12 |
/^Behind:
|
|
Karsten Hopp |
b5df12 |
/\(<\_[xy]\+\)\@3<=start
|
|
Karsten Hopp |
b5df12 |
***************
|
|
Karsten Hopp |
b5df12 |
*** 566,571 ****
|
|
Karsten Hopp |
b5df12 |
--- 572,584 ----
|
|
Karsten Hopp |
b5df12 |
b
|
|
Karsten Hopp |
b5df12 |
c
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
+ Backref:
|
|
Karsten Hopp |
b5df12 |
+ ./Dir1/Dir2/zyxwvuts.txt
|
|
Karsten Hopp |
b5df12 |
+ ./Dir1/Dir2/abcdefgh.bat
|
|
Karsten Hopp |
b5df12 |
+
|
|
Karsten Hopp |
b5df12 |
+ ./Dir1/Dir2/file1.txt
|
|
Karsten Hopp |
b5df12 |
+ ./OtherDir1/OtherDir2/file1.txt
|
|
Karsten Hopp |
b5df12 |
+
|
|
Karsten Hopp |
b5df12 |
Behind:
|
|
Karsten Hopp |
b5df12 |
asdfasd
|
|
Karsten Hopp |
b5df12 |
xxstart1
|
|
Karsten Hopp |
b5df12 |
*** ../vim-7.3.1190/src/testdir/test64.ok 2013-06-13 20:19:35.000000000 +0200
|
|
Karsten Hopp |
b5df12 |
--- src/testdir/test64.ok 2013-06-14 20:02:44.000000000 +0200
|
|
Karsten Hopp |
b5df12 |
***************
|
|
Karsten Hopp |
b5df12 |
*** 920,925 ****
|
|
Karsten Hopp |
b5df12 |
--- 920,927 ----
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
c
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
+ ./Dir1/Dir2/file1.txt
|
|
Karsten Hopp |
b5df12 |
+
|
|
Karsten Hopp |
b5df12 |
xxstart3
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
thexE thE thExethe
|
|
Karsten Hopp |
b5df12 |
*** ../vim-7.3.1190/src/version.c 2013-06-14 19:15:52.000000000 +0200
|
|
Karsten Hopp |
b5df12 |
--- src/version.c 2013-06-14 20:30:34.000000000 +0200
|
|
Karsten Hopp |
b5df12 |
***************
|
|
Karsten Hopp |
b5df12 |
*** 730,731 ****
|
|
Karsten Hopp |
b5df12 |
--- 730,733 ----
|
|
Karsten Hopp |
b5df12 |
{ /* Add new patch number below this line */
|
|
Karsten Hopp |
b5df12 |
+ /**/
|
|
Karsten Hopp |
b5df12 |
+ 1191,
|
|
Karsten Hopp |
b5df12 |
/**/
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
--
|
|
Karsten Hopp |
b5df12 |
hundred-and-one symptoms of being an internet addict:
|
|
Karsten Hopp |
b5df12 |
198. You read all the quotes at Netaholics Anonymous and keep thinking
|
|
Karsten Hopp |
b5df12 |
"What's wrong with that?"
|
|
Karsten Hopp |
b5df12 |
|
|
Karsten Hopp |
b5df12 |
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
|
|
Karsten Hopp |
b5df12 |
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
|
|
Karsten Hopp |
b5df12 |
\\\ an exciting new programming language -- http://www.Zimbu.org ///
|
|
Karsten Hopp |
b5df12 |
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|