From a61dc2074ae6cd00f1c166dc0102c491db056060 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 15 Apr 1999 18:06:33 +0000 Subject: zsh-3.1.5-pws-1 --- Src/Zle/compctl.c | 664 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 621 insertions(+), 43 deletions(-) (limited to 'Src/Zle/compctl.c') diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index 658cf4161..7104bfc6e 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -29,6 +29,9 @@ #include "compctl.mdh" #include "compctl.pro" +#define GLOBAL_PROTOTYPES +#include "zle_tricky.pro" +#undef GLOBAL_PROTOTYPES #define COMP_LIST (1<<0) /* -L */ #define COMP_COMMAND (1<<1) /* -C */ @@ -44,6 +47,328 @@ static int cclist; /* Mask for determining what to print */ static unsigned long showmask = 0; +/* This is a special return value for parse_cmatcher(), * + * signalling an error. */ + +#define pcm_err ((Cmatcher) 1) + +/* Copy a list of completion matchers. */ + +static Cmlist +cpcmlist(Cmlist l) +{ + Cmlist r = NULL, *p = &r, n; + + while (l) { + *p = n = (Cmlist) zalloc(sizeof(struct cmlist)); + n->next = NULL; + n->matcher = cpcmatcher(l->matcher); + n->str = ztrdup(l->str); + + p = &(n->next); + l = l->next; + } + return r; +} + +/* Copy a completion matcher list. */ + +/**/ +static Cmatcher +cpcmatcher(Cmatcher m) +{ + Cmatcher r = NULL, *p = &r, n; + + while (m) { + *p = n = (Cmatcher) zalloc(sizeof(struct cmatcher)); + + n->next = NULL; + n->flags = m->flags; + n->line = cpcpattern(m->line); + n->llen = m->llen; + n->word = cpcpattern(m->word); + n->wlen = m->wlen; + n->left = cpcpattern(m->left); + n->lalen = m->lalen; + n->right = cpcpattern(m->right); + n->ralen = m->ralen; + + p = &(n->next); + m = m->next; + } + return r; +} + +/* Copy a completion matcher pattern. */ + +/**/ +static Cpattern +cpcpattern(Cpattern o) +{ + Cpattern r = NULL, *p = &r, n; + + while (o) { + *p = n = (Cpattern) zalloc(sizeof(struct cpattern)); + + n->next = NULL; + memcpy(n->tab, o->tab, 256); + n->equiv = o->equiv; + + p = &(n->next); + o = o->next; + } + return r; +} + +/* Try to get the global matcher from the given compctl. */ + +/**/ +static int +get_gmatcher(char *name, char **argv) +{ + if (!strcmp(*argv, "-M")) { + char **p = ++argv; + Cmlist l = NULL, *q = &l, n; + Cmatcher m; + + while (*p) { + if (**p++ == '-') + return 0; + } + while (*argv) { + if ((m = parse_cmatcher(name, *argv)) == pcm_err) + return 2; + *q = n = (Cmlist) halloc(sizeof(struct cmlist)); + n->next = NULL; + n->matcher = m; + n->str = *argv++; + + q = &(n->next); + } + freecmlist(cmatcher); + PERMALLOC { + cmatcher = cpcmlist(l); + } LASTALLOC; + + return 1; + } + return 0; +} + +/* This prints the global matcher definitions. */ + +/**/ +static void +print_gmatcher(int ac) +{ + Cmlist p; + + if ((p = cmatcher)) { + printf((ac ? "compctl -M" : "MATCH")); + + while (p) { + printf(" \'%s\'", p->str); + + p = p->next; + } + putchar('\n'); + } +} + +/* Parse a string for matcher control, containing multiple matchers. */ + +/**/ +static Cmatcher +parse_cmatcher(char *name, char *s) +{ + Cmatcher ret = NULL, r, n; + Cpattern line, word, left, right; + int fl, ll, wl, lal, ral, err; + + if (!*s) + return NULL; + + while (*s) { + while (*s && inblank(*s)) s++; + + if (!*s) break; + + switch (*s) { + case 'l': fl = CMF_LEFT; break; + case 'r': fl = CMF_RIGHT; break; + case 'm': fl = 0; break; + case 'L': fl = CMF_LEFT | CMF_LINE; break; + case 'R': fl = CMF_RIGHT | CMF_LINE; break; + case 'M': fl = CMF_LINE; break; + default: + zwarnnam(name, "unknown match specification character `%c'", NULL, *s); + return pcm_err; + } + if (s[1] != ':') { + zwarnnam(name, "missing `:'", NULL, 0); + return pcm_err; + } + s += 2; + if (!*s) { + zwarnnam(name, "missing patterns", NULL, 0); + return pcm_err; + } + if (fl & CMF_LEFT) { + left = parse_pattern(name, &s, &lal, '|', &err); + if (err) + return pcm_err; + if (!*s || !*++s) { + zwarnnam(name, "missing line pattern", NULL, 0); + return pcm_err; + } + } else + left = NULL; + + line = parse_pattern(name, &s, &ll, ((fl & CMF_RIGHT) ? '|' : '='), + &err); + if (err) + return pcm_err; + if (!*s || !*++s) { + zwarnnam(name, ((fl & CMF_RIGHT) ? "missing right anchor" : "missing word pattern"), NULL, 0); + return pcm_err; + } + if (fl & CMF_RIGHT) { + right = parse_pattern(name, &s, &ral, '=', &err); + if (err) + return pcm_err; + if (!*s || !*++s) { + zwarnnam(name, "missing word pattern", NULL, 0); + return pcm_err; + } + } else + right = NULL; + + if (*s == '*') { + if (!(fl & (CMF_LEFT | CMF_RIGHT))) { + zwarnnam(name, "need anchor for `*'", NULL, 0); + return pcm_err; + } + word = NULL; + wl = -1; + s++; + } else { + word = parse_pattern(name, &s, &wl, 0, &err); + + if (!word && !line) { + zwarnnam(name, "need non-empty word or line pattern", NULL, 0); + return pcm_err; + } + } + if (err) + return pcm_err; + + n = (Cmatcher) zcalloc(sizeof(*ret)); + n->next = NULL; + n->flags = fl; + n->line = line; + n->llen = ll; + n->word = word; + n->wlen = wl; + n->left = left; + n->lalen = lal; + n->right = right; + n->ralen = ral; + + if (ret) r->next = n; + else ret = n; + + r = n; + } + return ret; +} + +/* Parse a pattern for matcher control. */ + +/**/ +static Cpattern +parse_pattern(char *name, char **sp, int *lp, char e, int *err) +{ + Cpattern ret = NULL, r, n; + unsigned char *s = (unsigned char *) *sp; + int l = 0; + + *err = 0; + + while (*s && (e ? (*s != e) : !inblank(*s))) { + n = (Cpattern) hcalloc(sizeof(*n)); + n->next = NULL; + n->equiv = 0; + + if (*s == '[') { + s = parse_class(n, s + 1, ']'); + if (!*s) { + *err = 1; + zwarnnam(name, "unterminated character class", NULL, 0); + return NULL; + } + } else if (*s == '{') { + n->equiv = 1; + s = parse_class(n, s + 1, '}'); + if (!*s) { + *err = 1; + zwarnnam(name, "unterminated character class", NULL, 0); + return NULL; + } + } else if (*s == '?') { + memset(n->tab, 1, 256); + } else if (*s == '*' || *s == '(' || *s == ')' || *s == '=') { + *err = 1; + zwarnnam(name, "invalid pattern character `%c'", NULL, *s); + return NULL; + } else { + if (*s == '\\' && s[1]) + s++; + + memset(n->tab, 0, 256); + n->tab[*s] = 1; + } + if (ret) + r->next = n; + else + ret = n; + + r = n; + + l++; + s++; + } + *sp = (char *) s; + *lp = l; + return ret; +} + +/* Parse a character class for matcher control. */ + +/**/ +static unsigned char * +parse_class(Cpattern p, unsigned char *s, unsigned char e) +{ + int n = 0, i = 1, j, eq = (e == '}'), k = 1; + + if (!eq && (*s == '!' || *s == '^') && s[1] != e) { n = 1; s++; } + + memset(p->tab, n, 256); + + n = !n; + while (*s && (k || *s != e)) { + if (s[1] == '-' && s[2] != e) { + /* a run of characters */ + for (j = (int) *s; j <= (int) s[2]; j++) + p->tab[j] = (eq ? i++ : n); + + s += 3; + } else + p->tab[*s++] = (eq ? i++ : n); + k = 0; + } + return s; +} + /* Parse the basic flags for `compctl' */ /**/ @@ -176,6 +501,44 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef) case '/': cct.mask |= CC_DIRS; break; + case 't': + { + char *p; + + if ((*argv)[1]) { + p = (*argv) + 1; + *argv = "" - 1; + } else if (!argv[1]) { + zwarnnam(name, "retry specification expected after -%c", NULL, + **argv); + return 1; + } else { + p = *++argv; + *argv = "" - 1; + } + while (*p) { + switch (*p) { + case '+': + cct.mask2 |= CC_XORCONT; + break; + case 'c': + cct.mask2 |= CC_CCCONT; + break; + case '-': + cct.mask2 |= CC_PATCONT; + break; + case 'x': + cct.mask2 |= CC_DEFCONT; + break; + default: + zwarnnam(name, "invalid retry specification character `%c'", + NULL, *p); + return 1; + } + p++; + } + } + break; case 'k': if ((*argv)[1]) { cct.keyvar = (*argv) + 1; @@ -307,6 +670,58 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef) *argv = "" - 1; } break; + case 'J': + if ((*argv)[1]) { + cct.gname = (*argv) + 1; + *argv = "" - 1; + } else if (!argv[1]) { + zwarnnam(name, "group name expected after -%c", NULL, + **argv); + return 1; + } else { + cct.gname = *++argv; + *argv = "" - 1; + } + break; + case 'V': + if ((*argv)[1]) { + cct.gname = (*argv) + 1; + *argv = "" - 1; + } else if (!argv[1]) { + zwarnnam(name, "group name expected after -%c", NULL, + **argv); + return 1; + } else { + cct.gname = *++argv; + *argv = "" - 1; + } + cct.mask2 |= CC_NOSORT; + break; + case 'M': + if ((*argv)[1]) { + if ((cct.matcher = + parse_cmatcher(name, (cct.mstr = (*argv) + 1))) == + pcm_err) { + cct.matcher = NULL; + cct.mstr = NULL; + return 1; + } + *argv = "" - 1; + } else if (!argv[1]) { + zwarnnam(name, "matching specification expected after -%c", NULL, + **argv); + return 1; + } else { + if ((cct.matcher = + parse_cmatcher(name, (cct.mstr = *++argv))) == + pcm_err) { + cct.matcher = NULL; + cct.mstr = NULL; + return 1; + } + *argv = "" - 1; + } + break; case 'H': if ((*argv)[1]) cct.hnum = atoi((*argv) + 1); @@ -600,27 +1015,34 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef) c->u.s.s[l] = ztrdup(tt); } else if (c->type == CCT_RANGESTR || c->type == CCT_RANGEPAT) { + int hc; + /* -r[..,..] or -R[..,..]: two strings expected */ - for (; *t && *t != '\201'; t++); + for (; *t && *t != '\201' && *t != '\200'; t++); if (!*t) { zwarnnam(name, "error in condition", NULL, 0); freecompcond(m); return 1; } + hc = (*t == '\201'); *t = '\0'; c->u.l.a[l] = ztrdup(tt); - tt = ++t; - /* any more commas are text, not active */ - for (; *t && *t != '\200'; t++) - if (*t == '\201') - *t = ','; - if (!*t) { - zwarnnam(name, "error in condition", NULL, 0); - freecompcond(m); - return 1; + if (hc) { + tt = ++t; + /* any more commas are text, not active */ + for (; *t && *t != '\200'; t++) + if (*t == '\201') + *t = ','; + if (!*t) { + zwarnnam(name, "error in condition", NULL, 0); + freecompcond(m); + return 1; + } + *t = '\0'; + c->u.l.b[l] = ztrdup(tt); } - *t = '\0'; - c->u.l.b[l] = ztrdup(tt); + else + c->u.l.b[l] = NULL; } else { /* remaining patterns are number followed by string */ for (; *t && *t != '\200' && *t != '\201'; t++); @@ -700,13 +1122,6 @@ cc_assign(char *name, Compctl *ccptr, Compctl cct, int reass) /* Copy over the details from the values in cct to those in *ccptr */ Compctl cc; - if (cct->subcmd && (cct->keyvar || cct->glob || cct->str || - cct->func || cct->explain || cct->ylist || - cct->prefix)) { - zwarnnam(name, "illegal combination of options", NULL, 0); - return 1; - } - /* Handle assignment of new default or command completion */ if (reass && !(cclist & COMP_LIST)) { /* if not listing */ @@ -746,11 +1161,15 @@ cc_assign(char *name, Compctl *ccptr, Compctl cct, int reass) zsfree(cc->subcmd); zsfree(cc->withd); zsfree(cc->hpat); - + zsfree(cc->gname); + zsfree(cc->mstr); + freecmatcher(cc->matcher); + /* and copy over the new stuff, (permanently) allocating * space for strings. */ cc->mask = cct->mask; + cc->mask2 = cct->mask2; cc->keyvar = ztrdup(cct->keyvar); cc->glob = ztrdup(cct->glob); cc->str = ztrdup(cct->str); @@ -761,8 +1180,13 @@ cc_assign(char *name, Compctl *ccptr, Compctl cct, int reass) cc->suffix = ztrdup(cct->suffix); cc->subcmd = ztrdup(cct->subcmd); cc->withd = ztrdup(cct->withd); + cc->gname = ztrdup(cct->gname); cc->hpat = ztrdup(cct->hpat); cc->hnum = cct->hnum; + PERMALLOC { + cc->matcher = cpcmatcher(cct->matcher); + } LASTALLOC; + cc->mstr = ztrdup(cct->mstr); /* careful with extended completion: it's already allocated */ cc->ext = cct->ext; @@ -790,16 +1214,62 @@ cc_reassign(Compctl cc) cc->ext = cc->xor = NULL; } +/* Check if the given string is a pattern. If so, return one and tokenize * + * it. If not, we just remove the backslashes. */ + +static int +compctl_name_pat(char **p) +{ + char *s = *p; + + tokenize(s = dupstring(s)); + remnulargs(s); + + if (haswilds(s)) { + *p = s; + return 1; + } else + *p = rembslash(*p); + + return 0; +} + +/* Delete the pattern compctl with the given name. */ + +static void +delpatcomp(char *n) +{ + Patcomp p, q; + + for (q = 0, p = patcomps; p; q = p, p = p->next) { + if (!strcmp(n, p->pat)) { + if (q) + q->next = p->next; + else + patcomps = p->next; + zsfree(p->pat); + freecompctl(p->cc); + free(p); + + break; + } + } +} + /**/ static void compctl_process_cc(char **s, Compctl cc) { Compctlp ccp; + char *n; if (cclist & COMP_REMOVE) { /* Delete entries for the commands listed */ for (; *s; s++) { - if ((ccp = (Compctlp) compctltab->removenode(compctltab, *s))) + n = *s; + if (compctl_name_pat(&n)) + delpatcomp(n); + else if ((ccp = (Compctlp) compctltab->removenode(compctltab, n))) compctltab->freenode((HashNode) ccp); } } else { @@ -807,10 +1277,23 @@ compctl_process_cc(char **s, Compctl cc) cc->refc = 0; for (; *s; s++) { + n = *s; + cc->refc++; - ccp = (Compctlp) zalloc(sizeof *ccp); - ccp->cc = cc; - compctltab->addnode(compctltab, ztrdup(*s), ccp); + if (compctl_name_pat(&n)) { + Patcomp pc; + + delpatcomp(n); + pc = zalloc(sizeof *pc); + pc->pat = ztrdup(n); + pc->cc = cc; + pc->next = patcomps; + patcomps = pc; + } else { + ccp = (Compctlp) zalloc(sizeof *ccp); + ccp->cc = cc; + compctltab->addnode(compctltab, ztrdup(n), ccp); + } } } } @@ -819,15 +1302,21 @@ compctl_process_cc(char **s, Compctl cc) /**/ static void -printcompctl(char *s, Compctl cc, int printflags) +printcompctl(char *s, Compctl cc, int printflags, int ispat) { Compctl cc2; char *css = "fcqovbAIFpEjrzBRGudeNOZUnQmw/"; char *mss = " pcCwWsSnNmrR"; unsigned long t = 0x7fffffff; - unsigned long flags = cc->mask; + unsigned long flags = cc->mask, flags2 = cc->mask2; unsigned long oldshowmask; + /* Printflags is used outside the standard compctl commands*/ + if (printflags & PRINT_LIST) + cclist |= COMP_LIST; + else if (printflags & PRINT_TYPE) + cclist &= ~COMP_LIST; + if ((flags & CC_EXCMDS) && !(flags & CC_DISCMDS)) flags &= ~CC_EXCMDS; @@ -851,8 +1340,13 @@ printcompctl(char *s, Compctl cc, int printflags) printf(" -D"); if (cc == &cc_first) printf(" -T"); + } else if (ispat) { + char *p = dupstring(s); + + untokenize(p); + quotedzputs(p, stdout); } else - quotedzputs(s, stdout); + quotedzputs(quotename(s, NULL, NULL, NULL), stdout); } /* loop through flags w/o args that are set, printing them if so */ @@ -868,9 +1362,23 @@ printcompctl(char *s, Compctl cc, int printflags) t >>= 1; } } - + if (flags2 & (CC_XORCONT | CC_CCCONT | CC_PATCONT | CC_DEFCONT)) { + printf(" -t"); + if (flags2 & CC_XORCONT) + putchar('+'); + if (flags2 & CC_CCCONT) + putchar('c'); + if (flags2 & CC_PATCONT) + putchar('-'); + if (flags2 & CC_DEFCONT) + putchar('x'); + } /* now flags with arguments */ - flags = cc->mask; + printif(cc->mstr, 'M'); + if (flags2 & CC_NOSORT) + printif(cc->gname, 'V'); + else + printif(cc->gname, 'J'); printif(cc->keyvar, 'k'); printif(cc->func, 'K'); printif(cc->explain, (cc->mask & CC_EXPANDEXPL) ? 'Y' : 'X'); @@ -940,7 +1448,7 @@ printcompctl(char *s, Compctl cc, int printflags) c = cc2->cond; cc2->cond = NULL; /* now print the flags for the current condition */ - printcompctl(NULL, cc2, 0); + printcompctl(NULL, cc2, 0, 0); cc2->cond = c; if ((cc2 = (Compctl) (cc2->next))) printf(" -"); @@ -952,7 +1460,7 @@ printcompctl(char *s, Compctl cc, int printflags) /* print xor'd (+) completions */ printf(" +"); if (cc->xor != &cc_default) - printcompctl(NULL, cc->xor, 0); + printcompctl(NULL, cc->xor, 0, 0); } if (s) { if ((cclist & COMP_LIST) && (cc != &cc_compos) @@ -960,7 +1468,17 @@ printcompctl(char *s, Compctl cc, int printflags) if(s[0] == '-' || s[0] == '+') printf(" -"); putchar(' '); - quotedzputs(s, stdout); + if (ispat) { + char *p = dupstring(s); + + untokenize(p); + quotedzputs(p, stdout); + } else { + char *p = dupstring(s); + + untokenize(p); + quotedzputs(quotename(p, NULL, NULL, NULL), stdout); + } } putchar('\n'); } @@ -975,7 +1493,7 @@ printcompctlp(HashNode hn, int printflags) Compctlp ccp = (Compctlp) hn; /* Function needed for use by scanhashtable() */ - printcompctl(ccp->nam, ccp->cc, printflags); + printcompctl(ccp->nam, ccp->cc, printflags, 0); } /* Main entry point for the `compctl' builtin */ @@ -991,8 +1509,14 @@ bin_compctl(char *name, char **argv, char *ops, int func) cclist = 0; showmask = 0; + instring = 0; + /* Parse all the arguments */ if (*argv) { + /* Let's see if this is a global matcher definition. */ + if ((ret = get_gmatcher(name, argv))) + return ret - 1; + cc = (Compctl) zcalloc(sizeof(*cc)); if (get_compctl(name, &argv, cc, 1, 0)) { freecompctl(cc); @@ -1013,10 +1537,16 @@ bin_compctl(char *name, char **argv, char *ops, int func) * If some flags (other than -C, -T, or -D) were given, then * * only print compctl containing those flags. */ if (!*argv && !(cclist & COMP_SPECIAL)) { + Patcomp pc; + + for (pc = patcomps; pc; pc = pc->next) + printcompctl(pc->pat, pc->cc, 0, 1); + scanhashtable(compctltab, 1, 0, 0, compctltab->printnode, 0); - printcompctl((cclist & COMP_LIST) ? "" : "COMMAND", &cc_compos, 0); - printcompctl((cclist & COMP_LIST) ? "" : "DEFAULT", &cc_default, 0); - printcompctl((cclist & COMP_LIST) ? "" : "FIRST", &cc_first, 0); + printcompctl((cclist & COMP_LIST) ? "" : "COMMAND", &cc_compos, 0, 0); + printcompctl((cclist & COMP_LIST) ? "" : "DEFAULT", &cc_default, 0, 0); + printcompctl((cclist & COMP_LIST) ? "" : "FIRST", &cc_first, 0, 0); + print_gmatcher((cclist & COMP_LIST)); return ret; } @@ -1024,23 +1554,35 @@ bin_compctl(char *name, char **argv, char *ops, int func) * or a COMP_SPECIAL flag (-D, -C, -T), so print only those. */ if (cclist & COMP_LIST) { HashNode hn; - char **ptr; + char **ptr, *n; showmask = 0; for (ptr = argv; *ptr; ptr++) { - if ((hn = compctltab->getnode(compctltab, *ptr))) { + n = *ptr; + if (compctl_name_pat(&n)) { + Patcomp pc; + + for (pc = patcomps; pc; pc = pc->next) + if (!strcmp(n, pc->pat)) { + printcompctl(pc->pat, pc->cc, 0, 1); + n = NULL; + break; + } + } else if ((hn = compctltab->getnode(compctltab, n))) { compctltab->printnode(hn, 0); - } else { - zwarnnam(name, "no compctl defined for %s", *ptr, 0); + n = NULL; + } + if (n) { + zwarnnam(name, "no compctl defined for %s", n, 0); ret = 1; } } if (cclist & COMP_COMMAND) - printcompctl("", &cc_compos, 0); + printcompctl("", &cc_compos, 0, 0); if (cclist & COMP_DEFAULT) - printcompctl("", &cc_default, 0); + printcompctl("", &cc_default, 0, 0); if (cclist & COMP_FIRST) - printcompctl("", &cc_first, 0); + printcompctl("", &cc_first, 0, 0); return ret; } @@ -1058,6 +1600,38 @@ bin_compctl(char *name, char **argv, char *ops, int func) return ret; } +/* Externally callable version of get_compctl. Used for completion widgets */ + +/**/ +static Compctl +compctl_widget(char *name, char **argv) +{ + Compctl cc = (Compctl) zcalloc(sizeof(*cc)); + cclist = 0; + showmask = 0; + + if (get_compctl(name, &argv, cc, 1, 0)) { + freecompctl(cc); + return NULL; + } + + if (cclist & COMP_REMOVE) { + zwarnnam(name, "use -D to delete widget", NULL, 0); + return NULL; + } else if (cclist) { + zwarnnam(name, "special options illegal in widget", NULL, 0); + freecompctl(cc); + return NULL; + } else if (*argv) { + zwarnnam(name, "command names illegal in widget", NULL, 0); + freecompctl(cc); + return NULL; + } + cc->refc++; + + return cc; +} + static struct builtin bintab[] = { BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL), }; @@ -1069,6 +1643,8 @@ boot_compctl(Module m) if(!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab))) return 1; compctltab->printnode = printcompctlp; + printcompctlptr = printcompctl; + compctl_widgetptr = compctl_widget; return 0; } @@ -1080,6 +1656,8 @@ cleanup_compctl(Module m) { compctltab->printnode = NULL; deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); + printcompctlptr = NULL; + compctl_widgetptr = NULL; return 0; } #endif -- cgit 1.4.1