/* Match a regexp and add the result to the items list * This function is recursive */ static void match_kw(regex_t *preg, const char *what, int len, POOLMEM **buf) { int rc, size; int nmatch=20; regmatch_t pmatch[20]; if (len <= 0) { return; } rc = regexec(preg, what, nmatch, pmatch, 0); if (rc == 0) { #if 0 Pmsg1(0, "\n\n%s\n0123456789012345678901234567890123456789\n 10 20 30\n", what); Pmsg2(0, "%i-%i\n", pmatch[0].rm_so, pmatch[0].rm_eo); Pmsg2(0, "%i-%i\n", pmatch[1].rm_so, pmatch[1].rm_eo); Pmsg2(0, "%i-%i\n", pmatch[2].rm_so, pmatch[2].rm_eo); Pmsg2(0, "%i-%i\n", pmatch[3].rm_so, pmatch[3].rm_eo); #endif size = pmatch[1].rm_eo - pmatch[1].rm_so; *buf = check_pool_memory_size(*buf, size + 1); memcpy(*buf, what+pmatch[1].rm_so, size); (*buf)[size] = 0; items->list.append(bstrdup(*buf)); /* We search for the next keyword in the line */ match_kw(preg, what + pmatch[1].rm_eo, len - pmatch[1].rm_eo, buf); } }
/* fill the items list with the output of the help command */ void get_arguments(const char *what) { regex_t preg; POOLMEM *buf; int rc; init_items(); rc = regcomp(&preg, "(([a-z_]+=)|([a-z]+)( |$))", REG_EXTENDED); if (rc != 0) { return; } buf = get_pool_memory(PM_MESSAGE); UA_sock->fsend(".help item=%s", what); while (UA_sock->recv() > 0) { strip_trailing_junk(UA_sock->msg); match_kw(&preg, UA_sock->msg, UA_sock->msglen, &buf); } free_pool_memory(buf); regfree(&preg); }
/* * Read a token from the input file, in the normal way (`normal' in * the sense that code paragraphs work a different way). */ token get_token(input * in) { int c; int nls; token ret; rdstring rs = { 0, 0, NULL }; filepos cpos; ret.cmd = c__invalid; ret.aux = FALSE; ret.text = NULL; /* default */ c = get(in, &cpos); ret.pos = cpos; if (iswhite(c)) { /* tok_white or tok_eop */ nls = 0; do { if (isnl(c)) nls++; } while ((c = get(in, &cpos)) != EOF && iswhite(c)); if (c == EOF) { ret.type = tok_eof; return ret; } unget(in, c, &cpos); ret.type = (nls > 1 ? tok_eop : tok_white); return ret; } else if (c == EOF) { /* tok_eof */ ret.type = tok_eof; return ret; } else if (c == '\\') { /* tok_cmd */ c = get(in, &cpos); if (c == '-' || c == '\\' || c == '_' || c == '#' || c == '{' || c == '}') { /* single-char command */ rdadd(&rs, (wchar_t)c); } else if (c == 'u') { int len = 0; do { rdadd(&rs, (wchar_t)c); len++; c = get(in, &cpos); } while (ishex(c) && len < 5); unget(in, c, &cpos); } else if (iscmd(c)) { do { rdadd(&rs, (wchar_t)c); c = get(in, &cpos); } while (iscmd(c)); unget(in, c, &cpos); } /* * Now match the command against the list of available * ones. */ ret.type = tok_cmd; ret.text = ustrdup(rs.text); match_kw(&ret); sfree(rs.text); return ret; } else if (c == '{') { /* tok_lbrace */ ret.type = tok_lbrace; return ret; } else if (c == '}') { /* tok_rbrace */ ret.type = tok_rbrace; return ret; } else { /* tok_word */ /* * Read a word: the longest possible contiguous sequence of * things other than whitespace, backslash, braces and * hyphen. A hyphen terminates the word but is returned as * part of it; everything else is pushed back for the next * token. The `aux' field contains TRUE if the word ends in * a hyphen. */ ret.aux = FALSE; /* assumed for now */ while (1) { if (iswhite(c) || c == '{' || c == '}' || c == '\\' || c == EOF) { /* Put back the character that caused termination */ unget(in, c, &cpos); break; } else { rdadd(&rs, (wchar_t)c); if (c == '-') { ret.aux = TRUE; break; /* hyphen terminates word */ } } c = get(in, &cpos); } ret.type = tok_word; ret.text = ustrdup(rs.text); sfree(rs.text); return ret; } }