Changes in / [a0fc4be:e3e4a2c] in mainline
- Location:
- uspace
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/compl.c
ra0fc4be re3e4a2c 1 1 /* 2 2 * Copyright (c) 2011 Jiri Svoboda 3 * Copyright (c) 2011 Martin Sucha4 3 * All rights reserved. 5 4 * … … 38 37 #include "compl.h" 39 38 #include "exec.h" 40 #include "tok.h"41 39 42 40 static int compl_init(wchar_t *text, size_t pos, size_t *cstart, void **state); … … 90 88 { 91 89 compl_t *cs = NULL; 90 size_t p; 92 91 size_t pref_size; 93 92 char *stext = NULL; … … 97 96 static const char *dirlist_arg[] = { ".", NULL }; 98 97 int retval; 99 tokenizer_t tok;100 token_t tokens[WORD_MAX];101 unsigned int current_token;102 size_t tokens_length;103 98 104 99 cs = calloc(1, sizeof(compl_t)); … … 108 103 } 109 104 105 /* 106 * Copy token pointed to by caret from start up to the caret. 107 * XXX Ideally we would use the standard tokenizer. 108 */ 109 p = pos; 110 while (p > 0 && text[p - 1] != (wchar_t) ' ') 111 --p; 112 *cstart = p; 113 110 114 /* Convert text buffer to string */ 111 stext = wstr_to_astr(text );115 stext = wstr_to_astr(text + *cstart); 112 116 if (stext == NULL) { 113 117 retval = ENOMEM; 114 118 goto error; 115 119 } 116 117 /* Tokenize the input string */ 118 retval = tok_init(&tok, stext, tokens, WORD_MAX); 119 if (retval != EOK) { 120 goto error; 121 } 122 123 retval = tok_tokenize(&tok, &tokens_length); 124 if (retval != EOK) { 125 goto error; 126 } 127 128 /* Find the current token */ 129 for (current_token = 0; current_token < tokens_length; current_token++) { 130 token_t *t = &tokens[current_token]; 131 size_t end = t->char_start + t->char_length; 132 /* Check if the caret lies inside the token or immediately 133 * after it 134 */ 135 if (t->char_start <= pos && pos <= end) { 136 break; 137 } 138 } 139 140 if (tokens[current_token].type != TOKTYPE_SPACE) { 141 *cstart = tokens[current_token].char_start; 142 } 143 else { 144 *cstart = pos; 145 } 146 147 /* Extract the prefix being completed 148 * XXX: handle strings, etc. 149 */ 120 121 /* Extract the prefix being completed */ 150 122 pref_size = str_lsize(stext, pos - *cstart); 151 123 prefix = malloc(pref_size + 1); … … 155 127 } 156 128 157 str_ncpy(prefix, pref_size + 1, stext + 158 tokens[current_token].byte_start, pref_size); 129 str_ncpy(prefix, pref_size + 1, stext, pref_size); 159 130 160 131 /* … … 162 133 * We look at the previous token. If there is none or it is a pipe 163 134 * ('|'), it is a command, otherwise it is an argument. 135 * XXX Again we should use the standard tokenizer/parser. 164 136 */ 165 137 166 138 /* Skip any whitespace before current token */ 167 int prev_token = current_token - 1; 168 if (prev_token != -1 && tokens[prev_token].type == TOKTYPE_SPACE) { 169 prev_token--; 170 } 139 while (p > 0 && text[p - 1] == (wchar_t) ' ') 140 --p; 171 141 172 142 /* … … 174 144 * follows a pipe token. 175 145 */ 176 if (p rev_token == -1 || tokens[prev_token].type == TOKTYPE_SPACE)146 if (p == 0 || text[p - 1] == '|') 177 147 cs->is_command = true; 178 148 else … … 219 189 220 190 cs->prefix_len = str_length(cs->prefix); 221 222 tok_fini(&tok);223 191 224 192 *state = cs; … … 227 195 error: 228 196 /* Error cleanup */ 229 230 tok_fini(&tok);231 197 232 198 if (cs != NULL && cs->path_list != NULL) { -
uspace/app/bdsh/input.c
ra0fc4be re3e4a2c 2 2 * Copyright (c) 2008 Tim Post 3 3 * Copyright (c) 2011 Jiri Svoboda 4 * Copyright (c) 2011 Martin Sucha5 4 * All rights reserved. 6 5 * … … 68 67 { 69 68 char *cmd[WORD_MAX]; 70 token_t tokens_space[WORD_MAX];71 token_t *tokens = tokens_space;72 69 int rc = 0; 73 70 tokenizer_t tok; 74 unsigned int i, pipe_count, processed_pipes; 75 unsigned int pipe_pos[2]; 71 int i, pipe_count, processed_pipes; 72 int pipe_pos[2]; 73 char **actual_cmd; 76 74 char *redir_from = NULL; 77 75 char *redir_to = NULL; … … 80 78 return CL_EFAIL; 81 79 82 rc = tok_init(&tok, usr->line, tokens, WORD_MAX);80 rc = tok_init(&tok, usr->line, cmd, WORD_MAX); 83 81 if (rc != EOK) { 84 82 goto finit; 85 83 } 86 84 87 size_t tokens_length; 88 rc = tok_tokenize(&tok, &tokens_length); 85 rc = tok_tokenize(&tok); 89 86 if (rc != EOK) { 90 87 goto finit; 91 }92 93 if (tokens_length > 0 && tokens[0].type == TOKTYPE_SPACE) {94 tokens++;95 tokens_length--;96 }97 98 if (tokens_length > 0 && tokens[tokens_length-1].type == TOKTYPE_SPACE) {99 tokens_length--;100 88 } 101 89 … … 105 93 * First find the pipes and check that there are no more 106 94 */ 107 for (i = 0, pipe_count = 0; i < tokens_length; i++) { 108 if (tokens[i].type == TOKTYPE_PIPE) { 95 int cmd_length = 0; 96 for (i = 0, pipe_count = 0; cmd[i] != NULL; i++, cmd_length++) { 97 if (cmd[i][0] == '|') { 109 98 if (pipe_count >= 2) { 110 99 print_pipe_usage(); … … 117 106 } 118 107 119 unsigned int cmd_token_start = 0; 120 unsigned int cmd_token_end = tokens_length; 121 108 actual_cmd = cmd; 122 109 processed_pipes = 0; 123 110 124 111 /* Check if the first part (from <file> |) is present */ 125 if (pipe_count > 0 && (pipe_pos[0] == 3 || pipe_pos[0] == 4) && str_cmp(tokens[0].text, "from") == 0) {112 if (pipe_count > 0 && pipe_pos[0] == 2 && str_cmp(cmd[0], "from") == 0) { 126 113 /* Ignore the first three tokens (from, file, pipe) and set from */ 127 redir_from = tokens[2].text;128 cmd_token_start = pipe_pos[0]+1;114 redir_from = cmd[1]; 115 actual_cmd = cmd + 3; 129 116 processed_pipes++; 130 117 } … … 132 119 /* Check if the second part (| to <file>) is present */ 133 120 if ((pipe_count - processed_pipes) > 0 && 134 (pipe_pos[processed_pipes] == tokens_length - 4 || 135 (pipe_pos[processed_pipes] == tokens_length - 5 && 136 tokens[tokens_length-4].type == TOKTYPE_SPACE )) && 137 str_cmp(tokens[tokens_length-3].text, "to") == 0) { 121 pipe_pos[processed_pipes] == cmd_length - 3 && 122 str_cmp(cmd[cmd_length-2], "to") == 0) { 138 123 /* Ignore the last three tokens (pipe, to, file) and set to */ 139 redir_to = tokens[tokens_length-1].text; 140 cmd_token_end = pipe_pos[processed_pipes]; 124 redir_to = cmd[cmd_length-1]; 125 cmd[cmd_length-3] = NULL; 126 cmd_length -= 3; 141 127 processed_pipes++; 142 128 } … … 148 134 } 149 135 150 /* Convert tokens of the command to string array */ 151 unsigned int cmd_pos = 0; 152 for (i = cmd_token_start; i < cmd_token_end; i++) { 153 if (tokens[i].type != TOKTYPE_SPACE) { 154 cmd[cmd_pos++] = tokens[i].text; 155 } 156 } 157 cmd[cmd_pos++] = NULL; 158 159 if (cmd[0] == NULL) { 136 if (actual_cmd[0] == NULL) { 160 137 print_pipe_usage(); 161 138 rc = ENOTSUP; … … 193 170 } 194 171 195 rc = run_command( cmd, usr, &new_iostate);172 rc = run_command(actual_cmd, usr, &new_iostate); 196 173 197 174 finit_with_files: -
uspace/app/bdsh/tok.c
ra0fc4be re3e4a2c 42 42 static bool tok_pending_chars(tokenizer_t *); 43 43 static int tok_finish_string(tokenizer_t *); 44 static void tok_start_token(tokenizer_t *, token_type_t);45 44 46 45 /** Initialize the token parser … … 51 50 * @param max_tokens number of elements of the out_tokens array 52 51 */ 53 int tok_init(tokenizer_t *tok, char *input, token_t*out_tokens,52 int tok_init(tokenizer_t *tok, char *input, char **out_tokens, 54 53 size_t max_tokens) 55 54 { 56 55 tok->in = input; 57 56 tok->in_offset = 0; 58 tok->last_in_offset = 0;59 tok->in_char_offset = 0;60 tok->last_in_char_offset = 0;61 57 62 58 tok->outtok = out_tokens; 63 59 tok->outtok_offset = 0; 64 tok->outtok_size = max_tokens; 60 /* Leave one slot for a null terminator */ 61 assert(max_tokens > 0); 62 tok->outtok_size = max_tokens - 1; 65 63 66 64 /* Prepare a buffer where all the token strings will be stored */ … … 89 87 90 88 /** Tokenize the input string into the tokens */ 91 int tok_tokenize(tokenizer_t *tok , size_t *tokens_length)89 int tok_tokenize(tokenizer_t *tok) 92 90 { 93 91 int rc; 94 wchar_t next_char;92 wchar_t cur_char; 95 93 96 94 /* Read the input line char by char and append tokens */ 97 while ((next_char = tok_look_char(tok)) != 0) { 98 if (next_char == ' ') { 99 /* Push the token if there is any. 95 while ((cur_char = tok_get_char(tok)) != 0) { 96 if (cur_char == ' ') { 97 /* Spaces delimit tokens, but are not processed in any way 98 * Push the token if there is any. 100 99 * There may not be any pending char for a token in case 101 100 * there are several spaces in the input. … … 107 106 } 108 107 } 109 tok_start_token(tok, TOKTYPE_SPACE); 110 /* Eat all the spaces */ 111 while (tok_look_char(tok) == ' ') { 112 tok_push_char(tok, tok_get_char(tok)); 113 } 114 tok_push_token(tok); 115 116 } 117 else if (next_char == '|') { 118 /* Pipes are tokens that are delimiters and should be 119 * output as a separate token 108 } 109 else if (cur_char == '|') { 110 /* Pipes are tokens that are delimiters and should be output 111 * as a separate token 120 112 */ 121 113 if (tok_pending_chars(tok)) { … … 126 118 } 127 119 128 tok_start_token(tok, TOKTYPE_PIPE); 129 130 rc = tok_push_char(tok, tok_get_char(tok)); 120 rc = tok_push_char(tok, '|'); 131 121 if (rc != EOK) { 132 122 return rc; … … 138 128 } 139 129 } 140 else if ( next_char == '\'') {130 else if (cur_char == '\'') { 141 131 /* A string starts with a quote (') and ends again with a quote. 142 132 * A literal quote is written as '' 143 133 */ 144 tok_start_token(tok, TOKTYPE_TEXT);145 /* Eat the quote */146 tok_get_char(tok);147 134 rc = tok_finish_string(tok); 148 135 if (rc != EOK) { … … 151 138 } 152 139 else { 153 if (!tok_pending_chars(tok)) {154 tok_start_token(tok, TOKTYPE_TEXT);155 }156 140 /* If we are handling any other character, just append it to 157 141 * the current token. 158 142 */ 159 rc = tok_push_char(tok, tok_get_char(tok));143 rc = tok_push_char(tok, cur_char); 160 144 if (rc != EOK) { 161 145 return rc; … … 172 156 } 173 157 174 *tokens_length = tok->outtok_offset; 158 /* We always have a space for the terminator, as we 159 * reserved it in tok_init */ 160 tok->outtok[tok->outtok_offset] = 0; 175 161 176 162 return EOK; … … 181 167 { 182 168 int rc; 183 wchar_t next_char; 184 185 while ((next_char = tok_look_char(tok)) != 0) { 186 if (next_char == '\'') { 187 /* Eat the quote */ 188 tok_get_char(tok); 169 wchar_t cur_char; 170 171 while ((cur_char = tok_get_char(tok)) != 0) { 172 if (cur_char == '\'') { 189 173 if (tok_look_char(tok) == '\'') { 190 174 /* Encode a single literal quote */ … … 203 187 } 204 188 else { 205 rc = tok_push_char(tok, tok_get_char(tok));189 rc = tok_push_char(tok, cur_char); 206 190 if (rc != EOK) { 207 191 return rc; … … 217 201 wchar_t tok_get_char(tokenizer_t *tok) 218 202 { 219 tok->in_char_offset++;220 203 return str_decode(tok->in, &tok->in_offset, STR_NO_LIMIT); 221 204 } … … 224 207 wchar_t tok_look_char(tokenizer_t *tok) 225 208 { 226 unsigned int old_offset = tok->in_offset; 227 unsigned int old_char_offset = tok->in_char_offset; 209 size_t old_offset = tok->in_offset; 228 210 wchar_t ret = tok_get_char(tok); 229 211 tok->in_offset = old_offset; 230 tok->in_char_offset = old_char_offset;231 212 return ret; 232 213 } … … 238 219 } 239 220 240 void tok_start_token(tokenizer_t *tok, token_type_t type)241 {242 tok->current_type = type;243 }244 245 221 /** Push the current token to the output array */ 246 222 int tok_push_token(tokenizer_t *tok) … … 255 231 256 232 tok->outbuf[tok->outbuf_offset++] = 0; 257 token_t *tokinfo = &tok->outtok[tok->outtok_offset++]; 258 tokinfo->type = tok->current_type; 259 tokinfo->text = tok->outbuf + tok->outbuf_last_start; 260 tokinfo->byte_start = tok->last_in_offset; 261 tokinfo->byte_length = tok->in_offset - tok->last_in_offset; 262 tokinfo->char_start = tok->last_in_char_offset; 263 tokinfo->char_length = tok->in_char_offset - tok->last_in_char_offset; 233 tok->outtok[tok->outtok_offset++] = tok->outbuf + tok->outbuf_last_start; 264 234 tok->outbuf_last_start = tok->outbuf_offset; 265 266 /* We have consumed the first char of the next token already */267 tok->last_in_offset = tok->in_offset;268 tok->last_in_char_offset = tok->in_char_offset;269 235 270 236 return EOK; -
uspace/app/bdsh/tok.h
ra0fc4be re3e4a2c 30 30 #define TOK_H 31 31 32 typedef enum {33 TOKTYPE_TEXT,34 TOKTYPE_PIPE,35 TOKTYPE_SPACE36 } token_type_t;37 38 typedef struct {39 char *text;40 unsigned int byte_start;41 unsigned int char_start;42 size_t byte_length;43 size_t char_length;44 token_type_t type;45 } token_t;46 47 32 typedef struct { 48 33 char *in; 49 unsigned int in_offset; 50 unsigned int last_in_offset; 51 unsigned int in_char_offset; 52 unsigned int last_in_char_offset; 34 size_t in_offset; 53 35 54 36 char *outbuf; … … 57 39 size_t outbuf_last_start; 58 40 59 token_t *outtok; 60 token_type_t current_type; 41 char **outtok; 61 42 size_t outtok_offset; 62 43 size_t outtok_size; 63 44 } tokenizer_t; 64 45 65 extern int tok_init(tokenizer_t *, char *, token_t*, size_t);46 extern int tok_init(tokenizer_t *, char *, char **, size_t); 66 47 extern void tok_fini(tokenizer_t *); 67 extern int tok_tokenize(tokenizer_t * , size_t *);48 extern int tok_tokenize(tokenizer_t *); 68 49 69 50 #endif -
uspace/lib/clui/tinput.c
ra0fc4be re3e4a2c 591 591 } 592 592 593 /* Print a list of completions */594 static void tinput_show_completions(tinput_t *ti, char **compl, size_t cnum)595 {596 unsigned int i;597 /* Determine the maximum length of the completion in chars */598 size_t max_length = 0;599 for (i = 0; i < cnum; i++)600 max_length = max(max_length, str_length(compl[i]));601 602 unsigned int cols = max(1, (ti->con_cols + 1) / (max_length + 1));603 unsigned int col_width = ti->con_cols / cols;604 unsigned int rows = cnum / cols + ((cnum % cols) != 0);605 606 unsigned int row, col;607 608 for (row = 0; row < rows; row++) {609 bool wlc = false;610 for (col = 0; col < cols; col++) {611 size_t compl_idx = col * rows + row;612 if (compl_idx >= cnum)613 break;614 if (col)615 printf(" ");616 printf("%s", compl[compl_idx]);617 size_t compl_len = str_length(compl[compl_idx]);618 if (col == cols -1) {619 wlc = (compl_len == max_length);620 }621 else {622 for (i = compl_len; i < col_width; i++) {623 printf(" ");624 }625 }626 }627 if (!wlc) printf("\n");628 }629 }630 631 632 593 static void tinput_text_complete(tinput_t *ti) 633 594 { … … 715 676 716 677 tinput_jump_after(ti); 717 tinput_show_completions(ti, compl, cnum); 678 for (i = 0; i < cnum; i++) 679 printf("%s\n", compl[i]); 718 680 tinput_display(ti); 719 681 }
Note:
See TracChangeset
for help on using the changeset viewer.