コード例 #1
0
ファイル: rl_helper.c プロジェクト: vincekim/libbtctl
void rl_init(line_process_callback cb) {
    struct termios settings;

    /* disable echo */
    tcgetattr(0, &settings); /* read settings from stdin (0) */
    settings.c_lflag &= ~(ICANON | ECHO); /* disable canonical and echo flags */
    tcsetattr(0, TCSANOW, &settings); /* store new settings */

    rl_clear();
    line_cb = cb;
}
コード例 #2
0
ファイル: grammar.c プロジェクト: Shea690901/dgd
/*
 * NAME:	parse_grammar()
 * DESCRIPTION:	check the grammar, return a pre-processed version
 */
string *parse_grammar(string *gram)
{
    char buffer[STRINGSZ];
    hashtab *ruletab, *strtab;
    rschunk *rschunks;
    rlchunk *rlchunks;
    rule *rgxlist, *strlist, *estrlist, *prodlist, *tmplist, *rr, *rrl;
    int token, ruleno, nrgx, nstr, nestr, nprod;
    ssizet glen;
    unsigned int buflen;
    bool nomatch;
    rulesym **rs;
    rule *rl, **r;
    long size;
    unsigned int len;

# if MAX_STRLEN > 0xffffffL
    if (gram->len > 0xffffffL) {
	error("Grammar string too large");
    }
# endif

    /* initialize */
    ruletab = ht_new(PARSERULTABSZ, PARSERULHASHSZ, FALSE);
    strtab = ht_new(PARSERULTABSZ, PARSERULHASHSZ, FALSE);
    rschunks = (rschunk *) NULL;
    rlchunks = (rlchunk *) NULL;
    rgxlist = strlist = estrlist = prodlist = tmplist = (rule *) NULL;
    nrgx = nstr = nestr = nprod = 0;
    size = 17 + 8;	/* size of header + start rule */
    glen = gram->len;
    nomatch = FALSE;

    token = gramtok(gram, &glen, buffer, &buflen);
    for (ruleno = 1; ; ruleno++) {
	switch (token) {
	case TOK_TOKSYM:
	    /*
	     * token rule definition
	     */
	    r = (rule **) ht_lookup(ruletab, buffer, TRUE);
	    if (*r != (rule *) NULL) {
		if ((*r)->type == RULE_UNKNOWN) {
		    /* replace unknown rule */
		    rl = *r;
		    rl->type = RULE_REGEXP;
		    size += 4;
		    nrgx++;

		    if (rl->alt != (rule *) NULL) {
			rl->alt->next = rl->next;
		    } else {
			tmplist = rl->next;
		    }
		    if (rl->next != (rule *) NULL) {
			rl->next->alt = rl->alt;
		    }
		    rl->alt = (rule *) NULL;
		    rl->next = rgxlist;
		    rgxlist = rl;
		} else if ((*r)->type == RULE_REGEXP) {
		    /* new alternative regexp */
		    rl = rl_new(&rlchunks, RULE_REGEXP);

		    *((*r)->last) = rl;
		    (*r)->last = &rl->alt;
		} else {
		    sprintf(buffer,
			    "Rule %d previously defined as production rule",
			    ruleno);
		    goto err;
		}
	    } else {
		/* new rule */
		rl = rl_new(&rlchunks, RULE_REGEXP);
		str_ref(rl->symb = str_new(buffer, (long) buflen));
		rl->chain.name = rl->symb->text;
		rl->chain.next = (hte *) *r;
		*r = rl;
		size += 4;
		nrgx++;

		rl->next = rgxlist;
		rgxlist = rl;
	    }

	    switch (gramtok(gram, &glen, buffer, &buflen)) {
	    case TOK_REGEXP:
		str_ref(rl->u.rgx = str_new(buffer, (long) buflen));
		(*r)->num++;
		(*r)->len += buflen;
		size += buflen + 1;
		break;

	    case TOK_BADREGEXP:
		sprintf(buffer, "Rule %d: malformed regular expression",
			ruleno);
		goto err;

	    case TOK_TOOBIGRGX:
		sprintf(buffer, "Rule %d: regular expression too large",
			ruleno);
		goto err;

	    case TOK_SYMBOL:
		if (buflen == 7 && strcmp(buffer, "nomatch") == 0) {
		    if (nomatch) {
			sprintf(buffer, "Rule %d: extra nomatch rule", ruleno);
			goto err;
		    }
		    nomatch = TRUE;
		    rl->u.rgx = (string *) NULL;
		    break;
		}
		/* fall through */
	    default:
		sprintf(buffer, "Rule %d: regular expression expected", ruleno);
		goto err;
	    }

	    /* next token */
	    token = gramtok(gram, &glen, buffer, &buflen);
	    break;

	case TOK_PRODSYM:
	    /*
	     * production rule definition
	     */
	    r = (rule **) ht_lookup(ruletab, buffer, TRUE);
	    if (*r != (rule *) NULL) {
		if ((*r)->type == RULE_UNKNOWN) {
		    /* replace unknown rule */
		    rl = *r;
		    rl->type = RULE_PROD;
		    size += 4;
		    nprod++;

		    if (rl->alt != (rule *) NULL) {
			rl->alt->next = rl->next;
		    } else {
			tmplist = rl->next;
		    }
		    if (rl->next != (rule *) NULL) {
			rl->next->alt = rl->alt;
		    }
		    rl->alt = (rule *) NULL;
		    rl->next = prodlist;
		    prodlist = rl;
		} else if ((*r)->type == RULE_PROD) {
		    /* new alternative production */
		    rl = rl_new(&rlchunks, RULE_PROD);

		    *((*r)->last) = rl;
		    (*r)->last = &rl->alt;
		} else {
		    sprintf(buffer, "Rule %d previously defined as token rule",
			    ruleno);
		    goto err;
		}
	    } else {
		/* new rule */
		rl = rl_new(&rlchunks, RULE_PROD);
		str_ref(rl->symb = str_new(buffer, (long) buflen));
		rl->chain.name = rl->symb->text;
		rl->chain.next = (hte *) *r;
		*r = rl;
		size += 4;
		nprod++;

		rl->next = prodlist;
		prodlist = rl;
	    }

	    rr = *r;
	    rrl = rl;
	    rs = &rl->u.syms;
	    len = 0;
	    for (;;) {
		switch (token = gramtok(gram, &glen, buffer, &buflen)) {
		case TOK_SYMBOL:
		    /*
		     * symbol
		     */
		    r = (rule **) ht_lookup(ruletab, buffer, TRUE);
		    if (*r == (rule *) NULL) {
			/* new unknown rule */
			rl = rl_new(&rlchunks, RULE_UNKNOWN);
			str_ref(rl->symb = str_new(buffer, (long) buflen));
			rl->chain.name = rl->symb->text;
			rl->chain.next = (hte *) *r;
			*r = rl;

			rl->next = tmplist;
			if (tmplist != (rule *) NULL) {
			    tmplist->alt = rl;
			}
			tmplist = rl;
		    } else {
			/* previously known rule */
			rl = *r;
		    }
		    *rs = rs_new(&rschunks, rl);
		    rs = &(*rs)->next;
		    len += 2;
		    continue;

		case TOK_STRING:
		case TOK_ESTRING:
		    /*
		     * string
		     */
		    r = (rule **) ht_lookup(strtab, buffer, FALSE);
		    while (*r != (rule *) NULL) {
			if ((*r)->symb->len == buflen &&
			    memcmp((*r)->symb->text, buffer, buflen) == 0) {
			    break;
			}
			r = (rule **) &(*r)->chain.next;
		    }
		    if (*r == (rule *) NULL) {
			/* new string rule */
			rl = rl_new(&rlchunks, RULE_STRING);
			str_ref(rl->symb = str_new(buffer, (long) buflen));
			rl->chain.name = rl->symb->text;
			rl->chain.next = (hte *) *r;
			*r = rl;

			if (token == TOK_STRING) {
			    size += 4;
			    nstr++;
			    rl->len = gram->len - glen - buflen - 1;
			    rl->next = strlist;
			    strlist = rl;
			} else {
			    size += 3 + buflen;
			    nestr++;
			    rl->next = estrlist;
			    estrlist = rl;
			}
		    } else {
			/* existing string rule */
			rl = *r;
		    }
		    *rs = rs_new(&rschunks, rl);
		    rs = &(*rs)->next;
		    len += 2;
		    continue;

		case TOK_QUEST:
		    /*
		     * ? function
		     */
		    if (gramtok(gram, &glen, buffer, &buflen) != TOK_SYMBOL) {
			sprintf(buffer, "Rule %d: function name expected",
				ruleno);
			goto err;
		    }
		    str_ref(rrl->func = str_new(buffer, (long) buflen));
		    len += buflen + 1;

		    token = gramtok(gram, &glen, buffer, &buflen);
		    /* fall through */
		default:
		    break;
		}
		break;
	    }

	    if (len > 255) {
		sprintf(buffer, "Rule %d is too long", ruleno);
		goto err;
	    }
	    rr->num++;
	    rr->len += len;
	    size += len + 2;
	    break;

	case TOK_NULL:
	    /*
	     * end of grammar
	     */
	    if (tmplist != (rule *) NULL) {
		sprintf(buffer, "Undefined symbol %s", tmplist->symb->text);
		goto err;
	    }
	    if (rgxlist == (rule *) NULL) {
		strcpy(buffer, "No tokens");
		goto err;
	    }
	    if (prodlist == (rule *) NULL) {
		strcpy(buffer, "No starting rule");
		goto err;
	    }
	    if (size > (long) USHRT_MAX) {
		strcpy(buffer, "Grammar too large");
		goto err;
	    }
	    gram = make_grammar(rgxlist, strlist, estrlist, prodlist, nrgx,
				nstr, nestr, nprod, size);
	    rs_clear(rschunks);
	    rl_clear(rlchunks);
	    ht_del(strtab);
	    ht_del(ruletab);
	    return gram;

	case TOK_ERROR:
	    sprintf(buffer, "Rule %d: bad token", ruleno);
	    goto err;

	case TOK_BADREGEXP:
	    sprintf(buffer, "Rule %d: malformed regular expression", ruleno);
	    goto err;

	case TOK_TOOBIGRGX:
	    sprintf(buffer, "Rule %d: regular expression too large", ruleno);
	    goto err;

	case TOK_BADSTRING:
	    sprintf(buffer, "Rule %d: malformed string constant", ruleno);
	    goto err;

	case TOK_TOOBIGSTR:
	    sprintf(buffer, "Rule %d: string too long", ruleno);
	    goto err;

	case TOK_TOOBIGSYM:
	    sprintf(buffer, "Rule %d: symbol too long", ruleno);
	    goto err;

	default:
	    sprintf(buffer, "Rule %d: unexpected token", ruleno);
	    goto err;
	}
    }

err:
    rs_clear(rschunks);
    rl_clear(rlchunks);
    ht_del(strtab);
    ht_del(ruletab);
    error(buffer);
    return NULL;
}
コード例 #3
0
ファイル: rl_helper.c プロジェクト: vincekim/libbtctl
bool rl_feed(int c) {

    if (rl_parse_seq(&c))
        return true;

    switch (c) {
        case K_EOT:
            putchar('\n');
            return false;
        case K_TAB:
            if (tab_completer_cb) {
                const char *str = tab_completer_cb(lnbuf, pos);
                if (str) {
                    int len = strlen(str);
                    memmove(lnbuf + pos + len, lnbuf + pos,
                            sizeof(lnbuf) - pos - len);
                    strncpy(lnbuf + pos, str, len);
                    pos += len;
                    rl_reprint_prompt();
                }
            }
            break;
        case '\r':
        case '\n':
            if (strlen(lnbuf) > 0) {
                char *dup = strdup(lnbuf);
                /* alloc space in history buffer to new string pointer */
                hs_len++;
                history = realloc(history, hs_len * sizeof(history[0]));
                history[hs_len - 1] = strdup(lnbuf);
                putchar('\n');
                line_cb(dup); /* send a copy, so we can change it */
                free(dup);
            } else
                /* don't parse empty lines */
                putchar('\n');

            hs_cur = hs_len;
            rl_clear();
            rl_reprint_prompt();
            break;
        case K_ESC:
            break;
        case K_BACKSPACE:
            if (pos > 0) {
                memmove(lnbuf + pos - 1, lnbuf + pos, sizeof(lnbuf) - pos);
                pos--;
                rl_reprint_prompt();
            }
            break;
        case K_UP:
            if (hs_cur > 0) {
                /* we have more history commands up */
                hs_cur--;
                strcpy(lnbuf, history[hs_cur]);
                pos = strlen(history[hs_cur]);
                rl_reprint_prompt();
            }
            break;
        case K_DOWN:
            if (hs_cur < hs_len - 1) {
                /* we have more history commands down */
                hs_cur++;
                strcpy(lnbuf, history[hs_cur]);
                pos = strlen(history[hs_cur]);
                rl_reprint_prompt();
            } else if (hs_cur == hs_len - 1) {
                /* we don't have more commands down, let's clear the prompt */
                hs_cur++;
                rl_clear();
                rl_reprint_prompt();
            }
            break;
        case K_RIGHT:
            if (pos < strlen(lnbuf)) {
                pos++;
                rl_reprint_prompt();
            }
            break;
        case K_LEFT:
            if (pos > 0) {
                pos--;
                rl_reprint_prompt();
            }
            break;
        case K_END:
            pos = strlen(lnbuf);
            rl_reprint_prompt();
            break;
        case K_HOME:
            pos = 0;
            rl_reprint_prompt();
            break;
        case K_DELETE:
            memmove(lnbuf + pos, lnbuf + pos + 1, sizeof(lnbuf) - pos - 1);
            rl_reprint_prompt();
            break;
        default:
            if (isprint(c)) {
                if (pos < (sizeof(lnbuf) - 1)) {
                    /* shift everything to right and insert char at pos */
                    memmove(lnbuf + pos + 1, lnbuf + pos,
                            sizeof(lnbuf) - pos - 1);
                    lnbuf[pos++] = c;
                    rl_reprint_prompt();
                }
            } else
                printf(" %x ", c);
            break;
    }

    return true;
}
コード例 #4
0
ファイル: rl_helper.c プロジェクト: vincekim/libbtctl
void rl_quit() {

    rl_clear();
    rl_clear_line();
}