Changeset a0fc4be in mainline
- Timestamp:
- 2011-08-20T06:51:43Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0f4532e, 5fb32c5, abf04a54
- Parents:
- e3e4a2c (diff), b2727f18 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- uspace
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/compl.c
re3e4a2c ra0fc4be 1 1 /* 2 2 * Copyright (c) 2011 Jiri Svoboda 3 * Copyright (c) 2011 Martin Sucha 3 4 * All rights reserved. 4 5 * … … 37 38 #include "compl.h" 38 39 #include "exec.h" 40 #include "tok.h" 39 41 40 42 static int compl_init(wchar_t *text, size_t pos, size_t *cstart, void **state); … … 88 90 { 89 91 compl_t *cs = NULL; 90 size_t p;91 92 size_t pref_size; 92 93 char *stext = NULL; … … 96 97 static const char *dirlist_arg[] = { ".", NULL }; 97 98 int retval; 99 tokenizer_t tok; 100 token_t tokens[WORD_MAX]; 101 unsigned int current_token; 102 size_t tokens_length; 98 103 99 104 cs = calloc(1, sizeof(compl_t)); … … 103 108 } 104 109 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 114 110 /* Convert text buffer to string */ 115 stext = wstr_to_astr(text + *cstart);111 stext = wstr_to_astr(text); 116 112 if (stext == NULL) { 117 113 retval = ENOMEM; 118 114 goto error; 119 115 } 120 121 /* Extract the prefix being completed */ 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 */ 122 150 pref_size = str_lsize(stext, pos - *cstart); 123 151 prefix = malloc(pref_size + 1); … … 127 155 } 128 156 129 str_ncpy(prefix, pref_size + 1, stext, pref_size); 157 str_ncpy(prefix, pref_size + 1, stext + 158 tokens[current_token].byte_start, pref_size); 130 159 131 160 /* … … 133 162 * We look at the previous token. If there is none or it is a pipe 134 163 * ('|'), it is a command, otherwise it is an argument. 135 * XXX Again we should use the standard tokenizer/parser.136 164 */ 137 165 138 166 /* Skip any whitespace before current token */ 139 while (p > 0 && text[p - 1] == (wchar_t) ' ') 140 --p; 167 int prev_token = current_token - 1; 168 if (prev_token != -1 && tokens[prev_token].type == TOKTYPE_SPACE) { 169 prev_token--; 170 } 141 171 142 172 /* … … 144 174 * follows a pipe token. 145 175 */ 146 if (p == 0 || text[p - 1] == '|')176 if (prev_token == -1 || tokens[prev_token].type == TOKTYPE_SPACE) 147 177 cs->is_command = true; 148 178 else … … 189 219 190 220 cs->prefix_len = str_length(cs->prefix); 221 222 tok_fini(&tok); 191 223 192 224 *state = cs; … … 195 227 error: 196 228 /* Error cleanup */ 229 230 tok_fini(&tok); 197 231 198 232 if (cs != NULL && cs->path_list != NULL) { -
uspace/app/bdsh/input.c
re3e4a2c ra0fc4be 2 2 * Copyright (c) 2008 Tim Post 3 3 * Copyright (c) 2011 Jiri Svoboda 4 * Copyright (c) 2011 Martin Sucha 4 5 * All rights reserved. 5 6 * … … 67 68 { 68 69 char *cmd[WORD_MAX]; 70 token_t tokens_space[WORD_MAX]; 71 token_t *tokens = tokens_space; 69 72 int rc = 0; 70 73 tokenizer_t tok; 71 int i, pipe_count, processed_pipes; 72 int pipe_pos[2]; 73 char **actual_cmd; 74 unsigned int i, pipe_count, processed_pipes; 75 unsigned int pipe_pos[2]; 74 76 char *redir_from = NULL; 75 77 char *redir_to = NULL; … … 78 80 return CL_EFAIL; 79 81 80 rc = tok_init(&tok, usr->line, cmd, WORD_MAX);82 rc = tok_init(&tok, usr->line, tokens, WORD_MAX); 81 83 if (rc != EOK) { 82 84 goto finit; 83 85 } 84 86 85 rc = tok_tokenize(&tok); 87 size_t tokens_length; 88 rc = tok_tokenize(&tok, &tokens_length); 86 89 if (rc != EOK) { 87 90 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--; 88 100 } 89 101 … … 93 105 * First find the pipes and check that there are no more 94 106 */ 95 int cmd_length = 0; 96 for (i = 0, pipe_count = 0; cmd[i] != NULL; i++, cmd_length++) { 97 if (cmd[i][0] == '|') { 107 for (i = 0, pipe_count = 0; i < tokens_length; i++) { 108 if (tokens[i].type == TOKTYPE_PIPE) { 98 109 if (pipe_count >= 2) { 99 110 print_pipe_usage(); … … 106 117 } 107 118 108 actual_cmd = cmd; 119 unsigned int cmd_token_start = 0; 120 unsigned int cmd_token_end = tokens_length; 121 109 122 processed_pipes = 0; 110 123 111 124 /* Check if the first part (from <file> |) is present */ 112 if (pipe_count > 0 && pipe_pos[0] == 2 && str_cmp(cmd[0], "from") == 0) {125 if (pipe_count > 0 && (pipe_pos[0] == 3 || pipe_pos[0] == 4) && str_cmp(tokens[0].text, "from") == 0) { 113 126 /* Ignore the first three tokens (from, file, pipe) and set from */ 114 redir_from = cmd[1];115 actual_cmd = cmd + 3;127 redir_from = tokens[2].text; 128 cmd_token_start = pipe_pos[0]+1; 116 129 processed_pipes++; 117 130 } … … 119 132 /* Check if the second part (| to <file>) is present */ 120 133 if ((pipe_count - processed_pipes) > 0 && 121 pipe_pos[processed_pipes] == cmd_length - 3 && 122 str_cmp(cmd[cmd_length-2], "to") == 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) { 123 138 /* Ignore the last three tokens (pipe, to, file) and set to */ 124 redir_to = cmd[cmd_length-1]; 125 cmd[cmd_length-3] = NULL; 126 cmd_length -= 3; 139 redir_to = tokens[tokens_length-1].text; 140 cmd_token_end = pipe_pos[processed_pipes]; 127 141 processed_pipes++; 128 142 } … … 134 148 } 135 149 136 if (actual_cmd[0] == NULL) { 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) { 137 160 print_pipe_usage(); 138 161 rc = ENOTSUP; … … 170 193 } 171 194 172 rc = run_command( actual_cmd, usr, &new_iostate);195 rc = run_command(cmd, usr, &new_iostate); 173 196 174 197 finit_with_files: -
uspace/app/bdsh/tok.c
re3e4a2c ra0fc4be 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); 44 45 45 46 /** Initialize the token parser … … 50 51 * @param max_tokens number of elements of the out_tokens array 51 52 */ 52 int tok_init(tokenizer_t *tok, char *input, char **out_tokens,53 int tok_init(tokenizer_t *tok, char *input, token_t *out_tokens, 53 54 size_t max_tokens) 54 55 { 55 56 tok->in = input; 56 57 tok->in_offset = 0; 58 tok->last_in_offset = 0; 59 tok->in_char_offset = 0; 60 tok->last_in_char_offset = 0; 57 61 58 62 tok->outtok = out_tokens; 59 63 tok->outtok_offset = 0; 60 /* Leave one slot for a null terminator */ 61 assert(max_tokens > 0); 62 tok->outtok_size = max_tokens - 1; 64 tok->outtok_size = max_tokens; 63 65 64 66 /* Prepare a buffer where all the token strings will be stored */ … … 87 89 88 90 /** Tokenize the input string into the tokens */ 89 int tok_tokenize(tokenizer_t *tok )91 int tok_tokenize(tokenizer_t *tok, size_t *tokens_length) 90 92 { 91 93 int rc; 92 wchar_t cur_char;94 wchar_t next_char; 93 95 94 96 /* Read the input line char by char and append tokens */ 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. 97 while ((next_char = tok_look_char(tok)) != 0) { 98 if (next_char == ' ') { 99 /* Push the token if there is any. 99 100 * There may not be any pending char for a token in case 100 101 * there are several spaces in the input. … … 106 107 } 107 108 } 108 } 109 else if (cur_char == '|') { 110 /* Pipes are tokens that are delimiters and should be output 111 * as a separate token 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 112 120 */ 113 121 if (tok_pending_chars(tok)) { … … 118 126 } 119 127 120 rc = tok_push_char(tok, '|'); 128 tok_start_token(tok, TOKTYPE_PIPE); 129 130 rc = tok_push_char(tok, tok_get_char(tok)); 121 131 if (rc != EOK) { 122 132 return rc; … … 128 138 } 129 139 } 130 else if ( cur_char == '\'') {140 else if (next_char == '\'') { 131 141 /* A string starts with a quote (') and ends again with a quote. 132 142 * A literal quote is written as '' 133 143 */ 144 tok_start_token(tok, TOKTYPE_TEXT); 145 /* Eat the quote */ 146 tok_get_char(tok); 134 147 rc = tok_finish_string(tok); 135 148 if (rc != EOK) { … … 138 151 } 139 152 else { 153 if (!tok_pending_chars(tok)) { 154 tok_start_token(tok, TOKTYPE_TEXT); 155 } 140 156 /* If we are handling any other character, just append it to 141 157 * the current token. 142 158 */ 143 rc = tok_push_char(tok, cur_char);159 rc = tok_push_char(tok, tok_get_char(tok)); 144 160 if (rc != EOK) { 145 161 return rc; … … 156 172 } 157 173 158 /* We always have a space for the terminator, as we 159 * reserved it in tok_init */ 160 tok->outtok[tok->outtok_offset] = 0; 174 *tokens_length = tok->outtok_offset; 161 175 162 176 return EOK; … … 167 181 { 168 182 int rc; 169 wchar_t cur_char; 170 171 while ((cur_char = tok_get_char(tok)) != 0) { 172 if (cur_char == '\'') { 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); 173 189 if (tok_look_char(tok) == '\'') { 174 190 /* Encode a single literal quote */ … … 187 203 } 188 204 else { 189 rc = tok_push_char(tok, cur_char);205 rc = tok_push_char(tok, tok_get_char(tok)); 190 206 if (rc != EOK) { 191 207 return rc; … … 201 217 wchar_t tok_get_char(tokenizer_t *tok) 202 218 { 219 tok->in_char_offset++; 203 220 return str_decode(tok->in, &tok->in_offset, STR_NO_LIMIT); 204 221 } … … 207 224 wchar_t tok_look_char(tokenizer_t *tok) 208 225 { 209 size_t old_offset = tok->in_offset; 226 unsigned int old_offset = tok->in_offset; 227 unsigned int old_char_offset = tok->in_char_offset; 210 228 wchar_t ret = tok_get_char(tok); 211 229 tok->in_offset = old_offset; 230 tok->in_char_offset = old_char_offset; 212 231 return ret; 213 232 } … … 219 238 } 220 239 240 void tok_start_token(tokenizer_t *tok, token_type_t type) 241 { 242 tok->current_type = type; 243 } 244 221 245 /** Push the current token to the output array */ 222 246 int tok_push_token(tokenizer_t *tok) … … 231 255 232 256 tok->outbuf[tok->outbuf_offset++] = 0; 233 tok->outtok[tok->outtok_offset++] = tok->outbuf + tok->outbuf_last_start; 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; 234 264 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; 235 269 236 270 return EOK; -
uspace/app/bdsh/tok.h
re3e4a2c ra0fc4be 30 30 #define TOK_H 31 31 32 typedef enum { 33 TOKTYPE_TEXT, 34 TOKTYPE_PIPE, 35 TOKTYPE_SPACE 36 } 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 32 47 typedef struct { 33 48 char *in; 34 size_t in_offset; 49 unsigned int in_offset; 50 unsigned int last_in_offset; 51 unsigned int in_char_offset; 52 unsigned int last_in_char_offset; 35 53 36 54 char *outbuf; … … 39 57 size_t outbuf_last_start; 40 58 41 char **outtok; 59 token_t *outtok; 60 token_type_t current_type; 42 61 size_t outtok_offset; 43 62 size_t outtok_size; 44 63 } tokenizer_t; 45 64 46 extern int tok_init(tokenizer_t *, char *, char **, size_t);65 extern int tok_init(tokenizer_t *, char *, token_t *, size_t); 47 66 extern void tok_fini(tokenizer_t *); 48 extern int tok_tokenize(tokenizer_t * );67 extern int tok_tokenize(tokenizer_t *, size_t *); 49 68 50 69 #endif -
uspace/lib/clui/tinput.c
re3e4a2c ra0fc4be 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 593 632 static void tinput_text_complete(tinput_t *ti) 594 633 { … … 676 715 677 716 tinput_jump_after(ti); 678 for (i = 0; i < cnum; i++) 679 printf("%s\n", compl[i]); 717 tinput_show_completions(ti, compl, cnum); 680 718 tinput_display(ti); 681 719 }
Note:
See TracChangeset
for help on using the changeset viewer.