1        -:    0:Source:readline.c
2        -:    1:/* readline.c -- functions to control the behaviour of readline,
3        -:    2: * specially completions. It also introduces the suggestions system
4        -:    3: * via my_rl_getc function */
5        -:    4:
6        -:    5:/*
7        -:    6: * This file is part of CliFM
8        -:    7: *
9        -:    8: * Copyright (C) 2016-2021, L. Abramovich <johndoe.arch@outlook.com>
10        -:    9: * All rights reserved.
11        -:   10:
12        -:   11: * CliFM is free software; you can redistribute it and/or modify
13        -:   12: * it under the terms of the GNU General Public License as published by
14        -:   13: * the Free Software Foundation; either version 2 of the License, or
15        -:   14: * (at your option) any later version.
16        -:   15: *
17        -:   16: * CliFM is distributed in the hope that it will be useful,
18        -:   17: * but WITHOUT ANY WARRANTY; without even the implied warranty of
19        -:   18: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20        -:   19: * GNU General Public License for more details.
21        -:   20: *
22        -:   21: * You should have received a copy of the GNU General Public License
23        -:   22: * along with this program; if not, write to the Free Software
24        -:   23: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25        -:   24: * MA 02110-1301, USA.
26        -:   25:*/
27        -:   26:
28        -:   27:#include "helpers.h"
29        -:   28:
30        -:   29:#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
31        -:   30:#include <sys/stat.h>
32        -:   31:#endif
33        -:   32:#include <dirent.h>
34        -:   33:#include <fcntl.h>
35        -:   34:#include <stdio.h>
36        -:   35:#include <string.h>
37        -:   36:#ifdef __OpenBSD__
38        -:   37:#include <strings.h>
39        -:   38:#endif
40        -:   39:#include <unistd.h>
41        -:   40:#include <errno.h>
42        -:   41:
43        -:   42:#ifdef __OpenBSD__
44        -:   43:typedef char *rl_cpvfunc_t;
45        -:   44:#include <ereadline/readline/readline.h>
46        -:   45:#include <ereadline/readline/history.h>
47        -:   46:#else
48        -:   47:#include <readline/readline.h>
49        -:   48:#include <readline/history.h>
50        -:   49:#endif
51        -:   50:
52        -:   51:#include "misc.h"
53        -:   52:#include "aux.h"
54        -:   53:#include "checks.h"
55        -:   54:#include "keybinds.h"
56        -:   55:#include "navigation.h"
57        -:   56:#include "readline.h"
58        -:   57:#ifndef _NO_SUGGESTIONS
59        -:   58:#include "suggestions.h"
60        -:   59:#endif
61        -:   60:
62        -:   61:#if !defined(_NO_SUGGESTIONS) && defined(__FreeBSD__)
63        -:   62:int freebsd_sc_console = 0;
64        -:   63:#endif /* __FreeBSD__ */
65        -:   64:
66        -:   65:/*
67        -:   66:#ifndef _NO_HIGHLIGHT
68        -:   67:#define _SINGLE 0
69        -:   68:#define _DOUBLE 1
70        -:   69:
71        -:   70:static char *
72        -:   71:get_cur_color(const int point)
73        -:   72:{
74        -:   73:	int m = point;
75        -:   74:	int sep = -1, sp = -1, t = -1;
76        -:   75:	char *c = (char *)NULL;
77        -:   76:	m--;
78        -:   77:
79        -:   78:
80        -:   79:	while (m >= 0) {
81        -:   80:		switch(rl_line_buffer[m]) {
82        -:   81:		case ' ': sp = m; break;
83        -:   82:		case '&': // fallthrough
84        -:   83:		case '|': // fallthrough
85        -:   84:		case ';': sep = m; break;
86        -:   85:		case '\'': // fallthrough
87        -:   86:		case '"': c = hq_c; t = m; break;
88        -:   87:		case '-': c = hp_c; t = m; break;
89        -:   88:		case '#': c = hc_c; t = m; break;
90        -:   89:		case '$': c = hv_c; t = m; break;
91        -:   90:		default: c = df_c; break;
92        -:   91:		}
93        -:   92:
94        -:   93:		if (t != -1)
95        -:   94:			break;
96        -:   95:
97        -:   96:		--m;
98        -:   97:	}
99        -:   98:
100        -:   99:	if (t != -1) {
101        -:  100:		if (c == hc_c || c == hq_c) {
102        -:  101:			if (t > sep)
103        -:  102:				return c;
104        -:  103:			else
105        -:  104:				return df_c;
106        -:  105:		} else {
107        -:  106:			if (t > sep && t > sp)
108        -:  107:				return c;
109        -:  108:			else
110        -:  109:				return df_c;
111        -:  110:		}
112        -:  111:	}
113        -:  112:
114        -:  113:	return df_c;
115        -:  114:}
116        -:  115:
117        -:  116:static char *
118        -:  117:get_highlight_color(const char c, const size_t *qn, const int point)
119        -:  118:{
120        -:  119:	if (c >= '0' && c <= '9')
121        -:  120:		return hn_c;
122        -:  121:
123        -:  122:	char *cl = cur_color;
124        -:  123:	char *p = (char *)NULL;
125        -:  124:	static int open_quote = 0;
126        -:  125:
127        -:  126:	switch(c) {
128        -:  127:	case '{': // fallthrough
129        -:  128:	case '}': // fallthrough
130        -:  129:	case '(': // fallthrough
131        -:  130:	case ')': // fallthrough
132        -:  131:	case '[': // fallthrough
133        -:  132:	case ']': p = hb_c; break;
134        -:  133:
135        -:  134:	case '#': p = hc_c; break;
136        -:  135:	case '~': // fallthrough
137        -:  136:	case '*': p = he_c; break;
138        -:  137:	case '-': p = hp_c; break;
139        -:  138:
140        -:  139:	case '\'':
141        -:  140:	case '"':
142        -:  141:		if ((qn[(c == '\'' ? _SINGLE : _DOUBLE)] + 1) % 2 == 0) {
143        -:  142:			open_quote = 0;
144        -:  143:			p = df_c;
145        -:  144:		} else {
146        -:  145:			p = hq_c;
147        -:  146:			open_quote = 1;
148        -:  147:		}
149        -:  148:		break;
150        -:  149:
151        -:  150:	case '>': p = hr_c; break;
152        -:  151:	case '|': // fallthrough
153        -:  152:	case ';': // fallthrough
154        -:  153:	case '&': p = hs_c; break;
155        -:  154:	case '$': p = hv_c; break;
156        -:  155:
157        -:  156:	case ENTER: p = df_c; break;
158        -:  157:
159        -:  158:	case ' ': return (char *)NULL;
160        -:  159:		// It works, but open_quote should be !open_quote
161        -:  160:		if (open_quote && cl != hc_c)
162        -:  161:			p = df_c;
163        -:  162:		break;
164        -:  163:
165        -:  164:	default:
166        -:  165:		if (point < rl_end)
167        -:  166:			p = get_cur_color(point);
168        -:  167:		else if (open_quote && cl != hv_c && cl != hp_c && cl != hc_c)
169        -:  168:			p = df_c;
170        -:  169:		break;
171        -:  170:	}
172        -:  171:
173        -:  172:	return p;
174        -:  173:}
175        -:  174:
176        -:  175:static void
177        -:  176:rl_highlight(const char c)
178        -:  177:{
179        -:  178:	if (rl_readline_state & RL_STATE_MOREINPUT)
180        -:  179:		return;
181        -:  180:
182        -:  181:	if (c < 32 && c != BS && c != ENTER)
183        -:  182:		return;
184        -:  183:
185        -:  184:	if (rl_end == 1 && (c == BS || c == 127)) {
186        -:  185:		cur_color = df_c;
187        -:  186:		return;
188        -:  187:	}
189        -:  188:
190        -:  189:	int m = rl_point;
191        -:  190:	size_t qn[2] = {0};
192        -:  191:	m--;
193        -:  192:
194        -:  193:	while (m >= 0) {
195        -:  194:		if (rl_line_buffer[m] == '\'')
196        -:  195:			qn[_SINGLE]++;
197        -:  196:		else if (rl_line_buffer[m] == '"')
198        -:  197:			qn[_DOUBLE]++;
199        -:  198:		--m;
200        -:  199:	}
201        -:  200:
202        -:  201:	char *p = rl_line_buffer;
203        -:  202:	char *cl = (char *)NULL;
204        -:  203:	int bk = rl_point;
205        -:  204:	rl_point = 0;
206        -:  205:
207        -:  206:	for (rl_point = 0; p[rl_point]; rl_point++)
208        -:  207:		cl = get_highlight_color(p[rl_point], qn, bk);
209        -:  208:
210        -:  209:	cl = get_highlight_color(c, qn, bk);
211        -:  210:
212        -:  211:	rl_point = bk;
213        -:  212:
214        -:  213:	int skip = 0;
215        -:  214:	if ((c == '\'' && qn[_SINGLE] % 2 != 0)
216        -:  215:	|| (c == '"' && qn[_DOUBLE] % 2 != 0))
217        -:  216:		skip = 1;
218        -:  217:
219        -:  218:	if (!skip && cl) {
220        -:  219:		cur_color = cl;
221        -:  220:		fputs(cl, stdout);
222        -:  221:	}
223        -:  222:
224        -:  223:	return;
225        -:  224:} */
226        -:  225:
227        -:  226:/*
228        -:  227:static void
229        -:  228:rl_highlight(const char ch)
230        -:  229:{
231        -:  230:	char *c = cur_color;
232        -:  231:	static int skip = 0, open_quote = 0;
233        -:  232:	int d = 0;
234        -:  233:
235        -:  234:	if (rl_readline_state & RL_STATE_MOREINPUT)
236        -:  235:		return;
237        -:  236:
238        -:  237:	if (ch < 32 && ch != BS && ch != ENTER)
239        -:  238:		return;
240        -:  239:
241        -:  240:	if (rl_point == rl_end) {
242        -:  241:		if (ch >= '0' && ch <= '9') {
243        -:  242:			fputs(hn_c, stdout);
244        -:  243:			fflush(stdout);
245        -:  244:			cur_color = hn_c;
246        -:  245:			return;
247        -:  246:		}
248        -:  247:
249        -:  248:		switch(ch) {
250        -:  249:		case '(': // fallthrough
251        -:  250:		case ')': // fallthrough
252        -:  251:		case '[': // fallthrough
253        -:  252:		case ']': // fallthrough
254        -:  253:		case '{': // fallthrough
255        -:  254:		case '}': c = hb_c;  skip = 0; d = 2; break;
256        -:  255:
257        -:  256:		case '#': c = hc_c; d = 1; skip = 0; break;
258        -:  257:
259        -:  258:		case '-': c = hp_c; d = 1; skip = 0; break;
260        -:  259:
261        -:  260:		case '"': // fallthrough
262        -:  261:		case '\'':
263        -:  262:			c = hq_c;
264        -:  263:			size_t n = 0;
265        -:  264:			char *p = rl_line_buffer;
266        -:  265:			while (*p) {
267        -:  266:				if (*p == ch)
268        -:  267:					n++;
269        -:  268:				p++;
270        -:  269:			}
271        -:  270:			if (++n % 2 != 0) { // Opening quote
272        -:  271:				// Keep color until closing quote is entered
273        -:  272:				skip = 0;
274        -:  273:				d = 1;
275        -:  274:				open_quote = 1;
276        -:  275:			} else { // Closing quote
277        -:  276:				// Reset to default color
278        -:  277:				c = df_c;
279        -:  278:				skip = 1;
280        -:  279:				d = 2;
281        -:  280:				open_quote = 0;
282        -:  281:			}
283        -:  282:			break;
284        -:  283:
285        -:  284:		case '~': // fallthrough
286        -:  285:		case '*': c = he_c;  skip = 0; d = 2; break;
287        -:  286:
288        -:  287:		case '$': c = hv_c; d = 1; skip = 0; break;
289        -:  288:
290        -:  289:		case '>': c = hr_c; skip = 0; d = 2; break;
291        -:  290:
292        -:  291:		case '&': // fallthrough
293        -:  292:		case ';': // fallthrough
294        -:  293:		case '|': c = hs_c; skip = 0; d = 2; break;
295        -:  294:
296        -:  295:		case ENTER: c = df_c; skip = 0; break;
297        -:  296:		case ' ':
298        -:  297:			if (!open_quote && c != hc_c) {
299        -:  298:				c = df_c;
300        -:  299:				skip = 0;
301        -:  300:			}
302        -:  301:			break;
303        -:  302:		default:
304        -:  303:			if (c != hv_c && !open_quote)
305        -:  304:				c = df_c;
306        -:  305:			break;
307        -:  306:		}
308        -:  307:
309        -:  308:		if (rl_end == 1 && (ch == BS || ch == 127))
310        -:  309:			c = df_c;
311        -:  310:
312        -:  311:		goto END;
313        -:  312:	}
314        -:  313:
315        -:  314:	int m = rl_point;
316        -:  315:	int separator = -1;
317        -:  316:	int t = -1;
318        -:  317:	size_t q_count[2] = {0}, single = 0, _double = 1;
319        -:  318:	skip = 0;
320        -:  319:	m--;
321        -:  320:
322        -:  321:	while (m >= 0) {
323        -:  322:		if (rl_line_buffer[m] == '\'')
324        -:  323:			q_count[single]++;
325        -:  324:		if (rl_line_buffer[m] == '"')
326        -:  325:			q_count[_double]++;
327        -:  326:		--m;
328        -:  327:	}
329        -:  328:
330        -:  329:	m = rl_point;
331        -:  330:	if (rl_line_buffer[m] != '"' && rl_line_buffer[m] != '\'')
332        -:  331:		--m;
333        -:  332:	while (m >= 0) {
334        -:  333:		switch(rl_line_buffer[m]) {
335        -:  334:		case ' ': separator = m; break;
336        -:  335:
337        -:  336:		case '&': // fallthrough
338        -:  337:		case ';': // fallthrough
339        -:  338:		case '|': d = 1; c = df_c; break;
340        -:  339:
341        -:  340:		case '#': c = hc_c; d = 1; t = m; break;
342        -:  341:		case '\'':
343        -:  342:			if (q_count[single] % 2 != 0) {
344        -:  343:				c = hq_c;
345        -:  344:				d = 1;
346        -:  345:				t = m;
347        -:  346:			}
348        -:  347:			break;
349        -:  348:		case '"':
350        -:  349:			if (q_count[_double] % 2 != 0) {
351        -:  350:				c = hq_c;
352        -:  351:				d = 1;
353        -:  352:				t = m;
354        -:  353:			}
355        -:  354:			break;
356        -:  355:		case '$': c = hv_c; d = 1; t = m; break;
357        -:  356:		case '-': c = hp_c; d = 1; t = m; break;
358        -:  357:		default: c = df_c; break;
359        -:  358:		}
360        -:  359:		--m;
361        -:  360:
362        -:  361:		if (d && c != hc_c && c != hq_c && separator > t) {
363        -:  362:			c = df_c;
364        -:  363:			continue;
365        -:  364:		}
366        -:  365:
367        -:  366:		if (d)
368        -:  367:			break;
369        -:  368:	}
370        -:  369:
371        -:  370:	if (rl_end == 1 && (ch == BS || ch == 127))
372        -:  371:		c = df_c;
373        -:  372:
374        -:  373:	if (t != -1)
375        -:  374:		goto END;
376        -:  375:
377        -:  376:	d = 0;
378        -:  377:	switch(ch) {
379        -:  378:	case '0': // fallthrough
380        -:  379:	case '1': // fallthrough
381        -:  380:	case '2': // fallthrough
382        -:  381:	case '3': // fallthrough
383        -:  382:	case '4': // fallthrough
384        -:  383:	case '5': // fallthrough
385        -:  384:	case '6': // fallthrough
386        -:  385:	case '7': // fallthrough
387        -:  386:	case '8': // fallthrough
388        -:  387:	case '9': c = hn_c;  skip = 0; d = 2; break;
389        -:  388:	case ' ': return;
390        -:  389:	case '(': // fallthrough
391        -:  390:	case ')': // fallthrough
392        -:  391:	case '[': // fallthrough
393        -:  392:	case ']': // fallthrough
394        -:  393:	case '{': // fallthrough
395        -:  394:	case '}': c = hb_c;  skip = 0; d = 2; break;
396        -:  395:	case '~': // fallthrough
397        -:  396:	case '*': c = he_c;  skip = 0; d = 2; break;
398        -:  397:	case '>': c = hr_c; skip = 0; d = 2; break;
399        -:  398:	case '&': // fallthrough
400        -:  399:	case ';': // fallthrough
401        -:  400:	case '|': c = hs_c; skip = 0; d = 2; break;
402        -:  401:	}
403        -:  402:
404        -:  403:	if (rl_end == 1 && (ch == BS || ch == 127))
405        -:  404:		c = df_c;
406        -:  405:
407        -:  406:END:
408        -:  407:	if (!skip) {
409        -:  408:		fputs(c, stdout);
410        -:  409:		fflush(stdout);
411        -:  410:	}
412        -:  411:
413        -:  412:	if (d == 1) {
414        -:  413:		skip = 1;
415        -:  414:	} else if (d == 2) {
416        -:  415:		skip = 0;
417        -:  416:		c = df_c;
418        -:  417:	}
419        -:  418:
420        -:  419:	cur_color = c;
421        -:  420:	return;
422        -:  421:}
423        -:  422:#endif */
424        -:  423:
425        -:  424:/* This function is automatically called by readline() to handle input.
426        -:  425: * Taken from Bash 1.14.7 and modified to fit our needs. Used
427        -:  426: * to introduce the suggestions system */
428        -:  427:static int
429function my_rl_getc called 2984 returned 100% blocks executed 34%
430     3004:  428:my_rl_getc(FILE *stream)
431        -:  429:{
432        -:  430:	int result;
433        -:  431:	unsigned char c;
434        -:  432:
435        -:  433:#if defined(__GO32__)
436        -:  434:	if (isatty(0))
437        -:  435:		return (getkey() & 0x7F);
438        -:  436:#endif /* __GO32__ */
439        -:  437:
440        -:  438:	while(1) {
441     3004:  439:		result = (int)read(fileno(stream), &c, sizeof(unsigned char));
442     3004:  439-block  0
443call    0 returned 3004
444call    1 returned 3004
445     3004:  440:		if (result == sizeof(unsigned char)) {
446branch  0 taken 3004 (fallthrough)
447branch  1 taken 0
448        -:  441:/*#ifndef _NO_HIGHLIGHT
449        -:  442:			if (highlight)
450        -:  443:				rl_highlight(c);
451        -:  444:#endif // _NO_HIGHLIGHT */
452        -:  445:
453        -:  446:#ifndef _NO_SUGGESTIONS
454     3004:  447:			if (suggestions) {
455     3004:  447-block  0
456branch  0 taken 2893 (fallthrough)
457branch  1 taken 111
458        -:  448:				/* rl_suggestions returns -1 is C was inserted before
459        -:  449:				 * the end of the current line, in which case we don't
460        -:  450:				 * want to return it here (otherwise, it would be added
461        -:  451:				 * to rl_line_buffer) */
462        -:  452:#ifdef __FreeBSD__
463        -:  453:			/* For the time being, suggestions do not work on the FreeBSD
464        -:  454:			 * console (vt). The escape code to retrieve the current cursor
465        -:  455:			 * position doesn't seem to work. Switching the console to 'sc'
466        -:  456:			 * solves the issue */
467        -:  457:				if (flags & GUI) {
468        -:  458:					if (rl_suggestions(c) == -1) {
469        -:  459:						rl_redisplay();
470        -:  460:						continue;
471        -:  461:					}
472        -:  462:				} else if (freebsd_sc_console && rl_suggestions(c) == -1) {
473        -:  463:					rl_redisplay();
474        -:  464:					continue;
475        -:  465:				}
476        -:  466:#else
477     2893:  467:				if (rl_suggestions(c) == -1) {
478     2893:  467-block  0
479call    0 returned 2893
480branch  1 taken 20 (fallthrough)
481branch  2 taken 2873
482       20:  468:					rl_redisplay();
483       20:  468-block  0
484call    0 returned 20
485       20:  469:					continue;
486unconditional  0 taken 20
487        -:  470:				}
488        -:  471:#endif /* __FreeBSD__ */
489        -:  472:			}
490        -:  473:#endif /* _NO_SUGGESTIONS */
491     2984:  474:			return (c);
492     2984:  474-block  0
493unconditional  0 taken 2984
494        -:  475:		}
495        -:  476:		/* If zero characters are returned, then the file that we are
496        -:  477:		reading from is empty!  Return EOF in that case. */
497    #####:  478:		if (result == 0)
498    %%%%%:  478-block  0
499branch  0 never executed
500branch  1 never executed
501    #####:  479:			return (EOF);
502    %%%%%:  479-block  0
503unconditional  0 never executed
504        -:  480:
505        -:  481:#if defined(EWOULDBLOCK)
506    #####:  482:		if (errno == EWOULDBLOCK) {
507    %%%%%:  482-block  0
508branch  0 never executed
509branch  1 never executed
510        -:  483:			int xflags;
511        -:  484:
512    #####:  485:			if ((xflags = fcntl(fileno(stream), F_GETFL, 0)) < 0)
513    %%%%%:  485-block  0
514call    0 never executed
515call    1 never executed
516branch  2 never executed
517branch  3 never executed
518    #####:  486:				return (EOF);
519    %%%%%:  486-block  0
520unconditional  0 never executed
521    #####:  487:			if (xflags & O_NDELAY) {
522    %%%%%:  487-block  0
523branch  0 never executed
524branch  1 never executed
525        -:  488:/*				xflags &= ~O_NDELAY; */
526    #####:  489:				fcntl(fileno(stream), F_SETFL, flags);
527    %%%%%:  489-block  0
528call    0 never executed
529call    1 never executed
530    #####:  490:				continue;
531unconditional  0 never executed
532        -:  491:			}
533    #####:  492:			continue;
534    %%%%%:  492-block  0
535unconditional  0 never executed
536        -:  493:		}
537        -:  494:#endif /* EWOULDBLOCK */
538        -:  495:
539        -:  496:#if defined(_POSIX_VERSION) && defined(EAGAIN) && defined(O_NONBLOCK)
540    #####:  497:		if (errno == EAGAIN) {
541    %%%%%:  497-block  0
542branch  0 never executed
543branch  1 never executed
544        -:  498:			int xflags;
545        -:  499:
546    #####:  500:			if ((xflags = fcntl(fileno(stream), F_GETFL, 0)) < 0)
547    %%%%%:  500-block  0
548call    0 never executed
549call    1 never executed
550branch  2 never executed
551branch  3 never executed
552    #####:  501:				return (EOF);
553    %%%%%:  501-block  0
554unconditional  0 never executed
555    #####:  502:			if (xflags & O_NONBLOCK) {
556    %%%%%:  502-block  0
557branch  0 never executed
558branch  1 never executed
559        -:  503://				xflags &= ~O_NONBLOCK;
560    #####:  504:				fcntl(fileno(stream), F_SETFL, flags);
561    %%%%%:  504-block  0
562call    0 never executed
563call    1 never executed
564    #####:  505:				continue;
565unconditional  0 never executed
566        -:  506:			}
567        -:  507:		}
568        -:  508:#endif /* _POSIX_VERSION && EAGAIN && O_NONBLOCK */
569        -:  509:
570        -:  510:#if !defined(__GO32__)
571        -:  511:      /* If the error that we received was SIGINT, then try again,
572        -:  512:	 this is simply an interrupted system call to read ().
573        -:  513:	 Otherwise, some error ocurred, also signifying EOF. */
574    #####:  514:		if (errno != EINTR)
575    %%%%%:  514-block  0
576branch  0 never executed
577branch  1 never executed
578    #####:  515:			return (EOF);
579    %%%%%:  515-block  0
580unconditional  0 never executed
581        -:  516:#endif /* !__GO32__ */
582        -:  517:	}
583        -:  518:}
584        -:  519:
585        -:  520:/* Simply check a single chartacter (c) against the quoting characters
586        -:  521: * list defined in the qc global array (which takes its values from
587        -:  522: * rl_filename_quote_characters */
588        -:  523:int
589function is_quote_char called 2622 returned 100% blocks executed 89%
590     2622:  524:is_quote_char(const char c)
591        -:  525:{
592     2622:  526:	if (c == '\0' || !qc)
593     2622:  526-block  0
594branch  0 taken 2622 (fallthrough)
595branch  1 taken 0
596     2622:  526-block  1
597branch  2 taken 0 (fallthrough)
598branch  3 taken 2622
599    #####:  527:		return -1;
600    %%%%%:  527-block  0
601unconditional  0 never executed
602        -:  528:
603     2622:  529:	char *p = qc;
604        -:  530:
605    70785:  531:	while (*p) {
606     2622:  531-block  0
607unconditional  0 taken 2622
608    70785:  531-block  1
609branch  1 taken 68164
610branch  2 taken 2621 (fallthrough)
611    68164:  532:		if (c == *(p++))
612    68164:  532-block  0
613branch  0 taken 1 (fallthrough)
614branch  1 taken 68163
615        1:  533:			return 1;
616        1:  533-block  0
617unconditional  0 taken 1
618        -:  534:	}
619        -:  535:
620     2621:  536:	return 0;
621     2621:  536-block  0
622unconditional  0 taken 2621
623        -:  537:}
624        -:  538:
625        -:  539:char *
626function rl_no_hist called 37 returned 100% blocks executed 79%
627       37:  540:rl_no_hist(const char *prompt)
628        -:  541:{
629       37:  542:	int bk = suggestions;
630       37:  543:	suggestions = 0;
631       37:  544:	stifle_history(0); /* Prevent readline from using the history
632       37:  544-block  0
633call    0 returned 37
634        -:  545:	setting */
635       37:  546:	char *input = readline(prompt);
636call    0 returned 37
637       37:  547:	unstifle_history();	 /* Reenable history */
638call    0 returned 37
639       37:  548:	read_history(hist_file); /* Reload history lines from file */
640call    0 returned 37
641       37:  549:	suggestions = bk;
642        -:  550:
643       37:  551:	if (input) {
644branch  0 taken 37 (fallthrough)
645branch  1 taken 0
646        -:  552:		/* Make sure input isn't empty string */
647       37:  553:		if (!*input) {
648       37:  553-block  0
649branch  0 taken 0 (fallthrough)
650branch  1 taken 37
651    #####:  554:			free(input);
652    #####:  555:			return (char *)NULL;
653    %%%%%:  555-block  0
654unconditional  0 never executed
655        -:  556:		}
656        -:  557:
657        -:  558:		/* Check we have some non-blank char */
658       37:  559:		int no_blank = 0;
659       37:  560:		char *p = input;
660        -:  561:
661       37:  562:		while (*p) {
662       37:  562-block  0
663unconditional  0 taken 37
664       37:  562-block  1
665branch  1 taken 37
666branch  2 taken 0 (fallthrough)
667       37:  563:			if (*p != ' ' && *p != '\n' && *p != '\t') {
668       37:  563-block  0
669branch  0 taken 37 (fallthrough)
670branch  1 taken 0
671       37:  563-block  1
672branch  2 taken 37 (fallthrough)
673branch  3 taken 0
674       37:  563-block  2
675branch  4 taken 37 (fallthrough)
676branch  5 taken 0
677       37:  564:				no_blank = 1;
678       37:  565:				break;
679       37:  565-block  0
680unconditional  0 taken 37
681        -:  566:			}
682    #####:  567:			p++;
683    %%%%%:  567-block  0
684unconditional  0 never executed
685        -:  568:		}
686        -:  569:
687       37:  570:		if (!no_blank) {
688       37:  570-block  0
689branch  0 taken 0 (fallthrough)
690branch  1 taken 37
691    #####:  571:			free(input);
692    #####:  572:			return (char *)NULL;
693    %%%%%:  572-block  0
694unconditional  0 never executed
695        -:  573:		}
696        -:  574:
697       37:  575:		return input;
698       37:  575-block  0
699unconditional  0 taken 37
700        -:  576:	}
701        -:  577:
702    #####:  578:	return (char *)NULL;
703    %%%%%:  578-block  0
704unconditional  0 never executed
705        -:  579:}
706        -:  580:
707        -:  581:/* Used by readline to check if a char in the string being completed is
708        -:  582: * quoted or not */
709        -:  583:static int
710function quote_detector called 0 returned 0% blocks executed 0%
711    #####:  584:quote_detector(char *line, int index)
712        -:  585:{
713    #####:  586:	if (index > 0 && line[index - 1] == '\\' && !quote_detector(line, index - 1))
714    %%%%%:  586-block  0
715branch  0 never executed
716branch  1 never executed
717    %%%%%:  586-block  1
718branch  2 never executed
719branch  3 never executed
720    %%%%%:  586-block  2
721call    4 never executed
722branch  5 never executed
723branch  6 never executed
724    #####:  587:		return 1;
725    %%%%%:  587-block  0
726unconditional  0 never executed
727        -:  588:
728    #####:  589:	return 0;
729    %%%%%:  589-block  0
730unconditional  0 never executed
731        -:  590:}
732        -:  591:
733        -:  592:/* Performs bash-style filename quoting for readline (put a backslash
734        -:  593: * before any char listed in rl_filename_quote_characters.
735        -:  594: * Modified version of:
736        -:  595: * https://utcc.utoronto.ca/~cks/space/blog/programming/ReadlineQuotingExample*/
737        -:  596:static char *
738function my_rl_quote called 0 returned 0% blocks executed 0%
739    #####:  597:my_rl_quote(char *text, int mt, char *qp)
740        -:  598:{
741        -:  599:	/* NOTE: mt and qp arguments are not used here, but are required by
742        -:  600:	 * rl_filename_quoting_function */
743        -:  601:	UNUSED(mt); UNUSED(qp);
744        -:  602:
745        -:  603:	/*
746        -:  604:	 * How it works: P and R are pointers to the same memory location
747        -:  605:	 * initialized (calloced) twice as big as the line that needs to be
748        -:  606:	 * quoted (in case all chars in the line need to be quoted); TP is a
749        -:  607:	 * pointer to TEXT, which contains the string to be quoted. We move
750        -:  608:	 * through TP to find all chars that need to be quoted ("a's" becomes
751        -:  609:	 * "a\'s", for example). At this point we cannot return P, since this
752        -:  610:	 * pointer is at the end of the string, so that we return R instead,
753        -:  611:	 * which is at the beginning of the same string pointed to by P.
754        -:  612:	 * */
755    #####:  613:	char *r = (char *)NULL, *p = (char *)NULL, *tp = (char *)NULL;
756        -:  614:
757    #####:  615:	size_t text_len = strlen(text);
758        -:  616:	/* Worst case: every character of text needs to be escaped. In this
759        -:  617:	 * case we need 2x text's bytes plus the NULL byte. */
760    #####:  618:	p = (char *)xnmalloc((text_len * 2) + 1, sizeof(char));
761    %%%%%:  618-block  0
762call    0 never executed
763    #####:  619:	r = p;
764        -:  620:
765    #####:  621:	if (r == NULL)
766branch  0 never executed
767branch  1 never executed
768    #####:  622:		return (char *)NULL;
769    %%%%%:  622-block  0
770unconditional  0 never executed
771        -:  623:
772        -:  624:	/* Escape whatever char that needs to be escaped */
773    #####:  625:	for (tp = text; *tp; tp++) {
774    %%%%%:  625-block  0
775unconditional  0 never executed
776    %%%%%:  625-block  1
777branch  1 never executed
778branch  2 never executed
779    #####:  626:		if (is_quote_char(*tp))
780    %%%%%:  626-block  0
781call    0 never executed
782branch  1 never executed
783branch  2 never executed
784    #####:  627:			*p++ = '\\';
785    %%%%%:  627-block  0
786unconditional  0 never executed
787        -:  628:
788    #####:  629:		*p++ = *tp;
789    %%%%%:  629-block  0
790unconditional  0 never executed
791        -:  630:	}
792        -:  631:
793        -:  632:	/* Add a final null byte to the string */
794    #####:  633:	*p = '\0';
795    #####:  634:	return r;
796    %%%%%:  634-block  0
797unconditional  0 never executed
798        -:  635:}
799        -:  636:
800        -:  637:/* This is the filename_completion_function() function of an old Bash
801        -:  638: * release (1.14.7) modified to fit CliFM needs */
802        -:  639:static char *
803function my_rl_path_completion called 4523 returned 100% blocks executed 48%
804     4523:  640:my_rl_path_completion(const char *text, int state)
805        -:  641:{
806     4523:  642:	if (!text || !*text)
807     4523:  642-block  0
808branch  0 taken 4523 (fallthrough)
809branch  1 taken 0
810     4523:  642-block  1
811branch  2 taken 9 (fallthrough)
812branch  3 taken 4514
813        9:  643:		return (char *)NULL;
814        9:  643-block  0
815unconditional  0 taken 9
816        -:  644:	/* state is zero before completion, and 1 ... n after getting
817        -:  645:	 * possible completions. Example:
818        -:  646:	 * cd Do[TAB] -> state 0
819        -:  647:	 * cuments/ -> state 1
820        -:  648:	 * wnloads/ -> state 2
821        -:  649:	 * */
822        -:  650:
823        -:  651:	/* Dequote string to be completed (text), if necessary */
824        -:  652:	static char *tmp_text = (char *)NULL;
825        -:  653:
826     4514:  654:	if (strchr(text, '\\')) {
827     4514:  654-block  0
828branch  0 taken 0 (fallthrough)
829branch  1 taken 4514
830    #####:  655:		char *p = savestring(text, strlen(text));
831    %%%%%:  655-block  0
832call    0 never executed
833    #####:  656:		tmp_text = dequote_str(p, 0);
834call    0 never executed
835    #####:  657:		free(p);
836    #####:  658:		p = (char *)NULL;
837    #####:  659:		if (!tmp_text)
838branch  0 never executed
839branch  1 never executed
840    #####:  660:			return (char *)NULL;
841    %%%%%:  660-block  0
842unconditional  0 never executed
843        -:  661:	}
844        -:  662:
845     4514:  663:	if (*text == '.' && text[1] == '.' && text[2] == '.') {
846     4514:  663-block  0
847branch  0 taken 6 (fallthrough)
848branch  1 taken 4508
849        6:  663-block  1
850branch  2 taken 2 (fallthrough)
851branch  3 taken 4
852        2:  663-block  2
853branch  4 taken 2 (fallthrough)
854branch  5 taken 0
855        2:  664:		char *p = savestring(text, strlen(text));
856        2:  664-block  0
857call    0 returned 2
858        2:  665:		tmp_text = fastback(p);
859call    0 returned 2
860        -:  666:
861        2:  667:		free(p);
862        2:  668:		p = (char *)NULL;
863        -:  669:
864        2:  670:		if (!tmp_text)
865branch  0 taken 0 (fallthrough)
866branch  1 taken 2
867    #####:  671:			return (char *)NULL;
868    %%%%%:  671-block  0
869unconditional  0 never executed
870        -:  672:	}
871        -:  673:
872        -:  674:/*	int rl_complete_with_tilde_expansion = 0; */
873        -:  675:	/* ~/Doc -> /home/user/Doc */
874        -:  676:
875        -:  677:	static DIR *directory;
876        -:  678:	static char *filename = (char *)NULL;
877        -:  679:	static char *dirname = (char *)NULL;
878        -:  680:	static char *users_dirname = (char *)NULL;
879        -:  681:	static size_t filename_len;
880        -:  682:	static int match, ret;
881     4514:  683:	struct dirent *ent = (struct dirent *)NULL;
882        -:  684:	static int exec = 0, exec_path = 0;
883        -:  685:	static char *dir_tmp = (char *)NULL;
884        -:  686:	static char tmp[PATH_MAX];
885        -:  687:
886        -:  688:	/* If we don't have any state, then do some initialization. */
887     4514:  689:	if (!state) {
888     4514:  689-block  0
889branch  0 taken 401 (fallthrough)
890branch  1 taken 4113
891        -:  690:		char *temp;
892        -:  691:
893      401:  692:		if (dirname)
894      401:  692-block  0
895branch  0 taken 0 (fallthrough)
896branch  1 taken 401
897    #####:  693:			free(dirname);
898    %%%%%:  693-block  0
899unconditional  0 never executed
900      401:  694:		if (filename)
901      401:  694-block  0
902branch  0 taken 0 (fallthrough)
903branch  1 taken 401
904    #####:  695:			free(filename);
905    %%%%%:  695-block  0
906unconditional  0 never executed
907      401:  696:		if (users_dirname)
908      401:  696-block  0
909branch  0 taken 0 (fallthrough)
910branch  1 taken 401
911    #####:  697:			free(users_dirname);
912    %%%%%:  697-block  0
913unconditional  0 never executed
914        -:  698:
915        -:  699:		/* tmp_text is true whenever text was dequoted */
916      401:  700:		size_t text_len = strlen((tmp_text) ? tmp_text : text);
917      401:  700-block  0
918branch  0 taken 1 (fallthrough)
919branch  1 taken 400
920        1:  700-block  1
921unconditional  2 taken 1
922      400:  700-block  2
923unconditional  3 taken 400
924      401:  701:		if (text_len)
925      401:  701-block  0
926branch  0 taken 401 (fallthrough)
927branch  1 taken 0
928      401:  702:			filename = savestring((tmp_text) ? tmp_text : text, text_len);
929      401:  702-block  0
930branch  0 taken 1 (fallthrough)
931branch  1 taken 400
932        1:  702-block  1
933unconditional  2 taken 1
934      400:  702-block  2
935unconditional  3 taken 400
936      401:  702-block  3
937call    4 returned 401
938unconditional  5 taken 401
939        -:  703:		else
940    #####:  704:			filename = savestring("", 1);
941    %%%%%:  704-block  0
942call    0 never executed
943unconditional  1 never executed
944        -:  705:
945      401:  706:		if (!*text)
946      401:  706-block  0
947branch  0 taken 0 (fallthrough)
948branch  1 taken 401
949    #####:  707:			text = ".";
950    %%%%%:  707-block  0
951unconditional  0 never executed
952        -:  708:
953      401:  709:		if (text_len)
954      401:  709-block  0
955branch  0 taken 401 (fallthrough)
956branch  1 taken 0
957      401:  710:			dirname = savestring((tmp_text) ? tmp_text : text, text_len);
958      401:  710-block  0
959branch  0 taken 1 (fallthrough)
960branch  1 taken 400
961        1:  710-block  1
962unconditional  2 taken 1
963      400:  710-block  2
964unconditional  3 taken 400
965      401:  710-block  3
966call    4 returned 401
967unconditional  5 taken 401
968        -:  711:		else
969    #####:  712:			dirname = savestring("", 1);
970    %%%%%:  712-block  0
971call    0 never executed
972unconditional  1 never executed
973        -:  713:
974      401:  714:		if (dirname[0] == '.' && dirname[1] == '/')
975      401:  714-block  0
976branch  0 taken 3 (fallthrough)
977branch  1 taken 398
978        3:  714-block  1
979branch  2 taken 0 (fallthrough)
980branch  3 taken 3
981    #####:  715:			exec = 1;
982    %%%%%:  715-block  0
983unconditional  0 never executed
984        -:  716:		else
985      401:  717:			exec = 0;
986      401:  717-block  0
987unconditional  0 taken 401
988        -:  718:
989        -:  719:		/* Get everything after last slash */
990      401:  720:		temp = strrchr(dirname, '/');
991        -:  721:
992      401:  722:		if (temp) {
993      401:  722-block  0
994branch  0 taken 40 (fallthrough)
995branch  1 taken 361
996       40:  723:			strcpy(filename, ++temp);
997       40:  724:			*temp = '\0';
998       40:  724-block  0
999unconditional  0 taken 40
1000        -:  725:		} else {
1001      361:  726:			strcpy(dirname, ".");
1002      361:  726-block  0
1003unconditional  0 taken 361
1004        -:  727:		}
1005        -:  728:
1006        -:  729:		/* We aren't done yet.  We also support the "~user" syntax. */
1007        -:  730:
1008        -:  731:		/* Save the version of the directory that the user typed. */
1009      401:  732:		size_t dirname_len = strlen(dirname);
1010        -:  733:
1011      401:  734:		users_dirname = savestring(dirname, dirname_len);
1012      401:  734-block  0
1013call    0 returned 401
1014        -:  735:		/*      { */
1015        -:  736:		char *temp_dirname;
1016        -:  737:		int replace_dirname;
1017        -:  738:
1018      401:  739:		temp_dirname = tilde_expand(dirname);
1019call    0 returned 401
1020      401:  740:		free(dirname);
1021      401:  741:		dirname = temp_dirname;
1022        -:  742:
1023      401:  743:		replace_dirname = 0;
1024        -:  744:
1025      401:  745:		if (rl_directory_completion_hook)
1026branch  0 taken 0 (fallthrough)
1027branch  1 taken 401
1028    #####:  746:			replace_dirname = (*rl_directory_completion_hook)(&dirname);
1029    %%%%%:  746-block  0
1030call    0 never executed
1031unconditional  1 never executed
1032        -:  747:
1033      401:  748:		if (replace_dirname) {
1034      401:  748-block  0
1035branch  0 taken 0 (fallthrough)
1036branch  1 taken 401
1037    #####:  749:			free(users_dirname);
1038    #####:  750:			users_dirname = savestring(dirname, dirname_len);
1039    %%%%%:  750-block  0
1040call    0 never executed
1041unconditional  1 never executed
1042        -:  751:		}
1043        -:  752:		/*      } */
1044      401:  753:		directory = opendir(dirname);
1045      401:  753-block  0
1046call    0 returned 401
1047      401:  754:		filename_len = strlen(filename);
1048        -:  755:
1049      401:  756:		rl_filename_completion_desired = 1;
1050unconditional  0 taken 401
1051        -:  757:	}
1052        -:  758:
1053     4514:  759:	if (tmp_text) {
1054     4514:  759-block  0
1055branch  0 taken 2 (fallthrough)
1056branch  1 taken 4512
1057        2:  760:		free(tmp_text);
1058        2:  761:		tmp_text = (char *)NULL;
1059        2:  761-block  0
1060unconditional  0 taken 2
1061        -:  762:	}
1062        -:  763:
1063        -:  764:	/* Now that we have some state, we can read the directory. If we found
1064        -:  765:	 * a match among files in dir, break the loop and print the match */
1065        -:  766:
1066     4514:  767:	match = 0;
1067        -:  768:
1068     4514:  769:	size_t dirname_len = 0;
1069     4514:  770:	if (dirname)
1070     4514:  770-block  0
1071branch  0 taken 4514 (fallthrough)
1072branch  1 taken 0
1073     4514:  771:		dirname_len = strlen(dirname);
1074     4514:  771-block  0
1075unconditional  0 taken 4514
1076        -:  772:
1077        -:  773:	/* This block is used only in case of "/path/./" to remove the
1078        -:  774:	 * ending "./" from dirname and to be able to perform thus the
1079        -:  775:	 * executable check via access() */
1080     4514:  776:	exec_path = 0;
1081        -:  777:
1082     4514:  778:	if (dirname_len > 2) {
1083     4514:  778-block  0
1084branch  0 taken 4118 (fallthrough)
1085branch  1 taken 396
1086        -:  779:
1087    4118*:  780:		if (dirname[dirname_len - 3] == '/' && dirname[dirname_len - 2] == '.'
1088     4118:  780-block  0
1089branch  0 taken 0 (fallthrough)
1090branch  1 taken 4118
1091    %%%%%:  780-block  1
1092branch  2 never executed
1093branch  3 never executed
1094    #####:  781:		&& dirname[dirname_len - 1] == '/') {
1095    %%%%%:  781-block  0
1096branch  0 never executed
1097branch  1 never executed
1098    #####:  782:			dir_tmp = savestring(dirname, dirname_len);
1099    %%%%%:  782-block  0
1100call    0 never executed
1101        -:  783:
1102    #####:  784:			if (dir_tmp) {
1103branch  0 never executed
1104branch  1 never executed
1105    #####:  785:				dir_tmp[dirname_len - 2] = '\0';
1106    #####:  786:				exec_path = 1;
1107    %%%%%:  786-block  0
1108unconditional  0 never executed
1109        -:  787:			}
1110        -:  788:		}
1111        -:  789:	}
1112        -:  790:
1113        -:  791:	/* ############### COMPLETION FILTER ################## */
1114        -:  792:	/* #        This is the heart of the function         #
1115        -:  793:	 * #################################################### */
1116        -:  794:	mode_t type;
1117        -:  795:
1118    75929:  796:	while (directory && (ent = readdir(directory))) {
1119     4514:  796-block  0
1120unconditional  0 taken 4514
1121    75929:  796-block  1
1122branch  1 taken 75923 (fallthrough)
1123branch  2 taken 6
1124    75923:  796-block  2
1125call    3 returned 75923
1126branch  4 taken 75528
1127branch  5 taken 395 (fallthrough)
1128        -:  797:#if !defined(_DIRENT_HAVE_D_TYPE)
1129        -:  798:		struct stat attr;
1130        -:  799:		if (!dirname || (*dirname == '.' && !*(dirname + 1)))
1131        -:  800:			xstrsncpy(tmp, ent->d_name, PATH_MAX);
1132        -:  801:		else
1133        -:  802:			snprintf(tmp, PATH_MAX, "%s%s", dirname, ent->d_name);
1134        -:  803:
1135        -:  804:		if (lstat(tmp, &attr) == -1) {
1136        -:  805:			continue;
1137        -:  806:		}
1138        -:  807:
1139        -:  808:		switch (attr.st_mode & S_IFMT) {
1140        -:  809:		case S_IFBLK: type = DT_BLK; break;
1141        -:  810:		case S_IFCHR: type = DT_CHR; break;
1142        -:  811:		case S_IFDIR: type = DT_DIR; break;
1143        -:  812:		case S_IFIFO: type = DT_FIFO; break;
1144        -:  813:		case S_IFLNK: type = DT_LNK; break;
1145        -:  814:		case S_IFREG: type = DT_REG; break;
1146        -:  815:		case S_IFSOCK: type = DT_SOCK; break;
1147        -:  816:		default: type = DT_UNKNOWN; break;
1148        -:  817:		}
1149        -:  818:#else
1150    75528:  819:		type = ent->d_type;
1151        -:  820:#endif /* !_DIRENT_HAVE_D_TYPE */
1152        -:  821:
1153        -:  822:		/* If the user entered nothing before TAB (ex: "cd [TAB]") */
1154    75528:  823:		if (!filename_len) {
1155    75528:  823-block  0
1156branch  0 taken 3561 (fallthrough)
1157branch  1 taken 71967
1158        -:  824:			/* Exclude "." and ".." as possible completions */
1159     3561:  825:			if (SELFORPARENT(ent->d_name))
1160     3561:  825-block  0
1161branch  0 taken 2 (fallthrough)
1162branch  1 taken 3559
1163        2:  825-block  1
1164branch  2 taken 1 (fallthrough)
1165branch  3 taken 1
1166        1:  825-block  2
1167branch  4 taken 1 (fallthrough)
1168branch  5 taken 0
1169        1:  825-block  3
1170branch  6 taken 1 (fallthrough)
1171branch  7 taken 0
1172        2:  826:				continue;
1173        2:  826-block  0
1174unconditional  0 taken 2
1175        -:  827:
1176        -:  828:			/* If 'cd', match only dirs or symlinks to dir */
1177     3559:  829:			if (*rl_line_buffer == 'c'
1178     3559:  829-block  0
1179branch  0 taken 0 (fallthrough)
1180branch  1 taken 3559
1181    #####:  830:			&& strncmp(rl_line_buffer, "cd ", 3) == 0) {
1182    %%%%%:  830-block  0
1183branch  0 never executed
1184branch  1 never executed
1185    #####:  831:				ret = -1;
1186        -:  832:
1187    #####:  833:				switch (type) {
1188    %%%%%:  833-block  0
1189branch  0 never executed
1190branch  1 never executed
1191branch  2 never executed
1192    #####:  834:				case DT_LNK:
1193    #####:  835:					if (dirname[0] == '.' && !dirname[1]) {
1194    %%%%%:  835-block  0
1195branch  0 never executed
1196branch  1 never executed
1197    %%%%%:  835-block  1
1198branch  2 never executed
1199branch  3 never executed
1200    #####:  836:						ret = get_link_ref(ent->d_name);
1201    %%%%%:  836-block  0
1202call    0 never executed
1203unconditional  1 never executed
1204        -:  837:					} else {
1205    #####:  838:						snprintf(tmp, PATH_MAX, "%s%s", dirname, ent->d_name);
1206    #####:  839:						ret = get_link_ref(tmp);
1207    %%%%%:  839-block  0
1208call    0 never executed
1209unconditional  1 never executed
1210        -:  840:					}
1211        -:  841:
1212    #####:  842:					if (ret == S_IFDIR)
1213    %%%%%:  842-block  0
1214branch  0 never executed
1215branch  1 never executed
1216    #####:  843:						match = 1;
1217    %%%%%:  843-block  0
1218unconditional  0 never executed
1219        -:  844:
1220    #####:  845:					break;
1221    %%%%%:  845-block  0
1222unconditional  0 never executed
1223        -:  846:
1224    #####:  847:				case DT_DIR:
1225    #####:  848:					match = 1;
1226    #####:  849:					break;
1227    %%%%%:  849-block  0
1228unconditional  0 never executed
1229        -:  850:
1230    #####:  851:				default:
1231    #####:  852:					break;
1232    %%%%%:  852-block  0
1233unconditional  0 never executed
1234        -:  853:				}
1235        -:  854:			}
1236        -:  855:
1237        -:  856:			/* If 'open', allow only reg files, dirs, and symlinks */
1238     3559:  857:			else if (*rl_line_buffer == 'o'
1239     3559:  857-block  0
1240branch  0 taken 0 (fallthrough)
1241branch  1 taken 3559
1242    #####:  858:			&& (strncmp(rl_line_buffer, "o ", 2) == 0
1243    %%%%%:  858-block  0
1244branch  0 never executed
1245branch  1 never executed
1246    #####:  859:			|| strncmp(rl_line_buffer, "open ", 5) == 0)) {
1247    %%%%%:  859-block  0
1248branch  0 never executed
1249branch  1 never executed
1250    #####:  860:				ret = -1;
1251        -:  861:
1252    #####:  862:				switch (type) {
1253    %%%%%:  862-block  0
1254branch  0 never executed
1255branch  1 never executed
1256branch  2 never executed
1257    #####:  863:				case DT_LNK:
1258    #####:  864:					if (dirname[0] == '.' && !dirname[1]) {
1259    %%%%%:  864-block  0
1260branch  0 never executed
1261branch  1 never executed
1262    %%%%%:  864-block  1
1263branch  2 never executed
1264branch  3 never executed
1265    #####:  865:						ret = get_link_ref(ent->d_name);
1266    %%%%%:  865-block  0
1267call    0 never executed
1268unconditional  1 never executed
1269        -:  866:					} else {
1270    #####:  867:						snprintf(tmp, PATH_MAX, "%s%s", dirname, ent->d_name);
1271    #####:  868:						ret = get_link_ref(tmp);
1272    %%%%%:  868-block  0
1273call    0 never executed
1274unconditional  1 never executed
1275        -:  869:					}
1276        -:  870:
1277    #####:  871:					if (ret == S_IFDIR || ret == S_IFREG)
1278    %%%%%:  871-block  0
1279branch  0 never executed
1280branch  1 never executed
1281    %%%%%:  871-block  1
1282branch  2 never executed
1283branch  3 never executed
1284    #####:  872:						match = 1;
1285    %%%%%:  872-block  0
1286unconditional  0 never executed
1287        -:  873:
1288    #####:  874:					break;
1289    %%%%%:  874-block  0
1290unconditional  0 never executed
1291        -:  875:
1292    #####:  876:				case DT_REG: /* fallthrough */
1293    #####:  877:				case DT_DIR: match = 1; break;
1294    %%%%%:  877-block  0
1295unconditional  0 never executed
1296        -:  878:
1297    #####:  879:				default: break;
1298    %%%%%:  879-block  0
1299unconditional  0 never executed
1300        -:  880:				}
1301        -:  881:			}
1302        -:  882:
1303        -:  883:			/* If 'trash', allow only reg files, dirs, symlinks, pipes
1304        -:  884:			 * and sockets. You should not trash a block or a character
1305        -:  885:			 * device */
1306     3559:  886:			else if (*rl_line_buffer == 't'
1307     3559:  886-block  0
1308branch  0 taken 0 (fallthrough)
1309branch  1 taken 3559
1310    #####:  887:			&& (strncmp(rl_line_buffer, "t ", 2) == 0
1311    %%%%%:  887-block  0
1312branch  0 never executed
1313branch  1 never executed
1314    #####:  888:			|| strncmp(rl_line_buffer, "tr ", 2) == 0
1315    %%%%%:  888-block  0
1316branch  0 never executed
1317branch  1 never executed
1318    #####:  889:			|| strncmp(rl_line_buffer, "trash ", 6) == 0)) {
1319    %%%%%:  889-block  0
1320branch  0 never executed
1321branch  1 never executed
1322        -:  890:
1323    #####:  891:				if (type != DT_BLK && type != DT_CHR)
1324    %%%%%:  891-block  0
1325branch  0 never executed
1326branch  1 never executed
1327    %%%%%:  891-block  1
1328branch  2 never executed
1329branch  3 never executed
1330    #####:  892:					match = 1;
1331    %%%%%:  892-block  0
1332unconditional  0 never executed
1333        -:  893:			}
1334        -:  894:
1335        -:  895:			/* If "./", list only executable regular files */
1336     3559:  896:			else if (exec) {
1337     3559:  896-block  0
1338branch  0 taken 0 (fallthrough)
1339branch  1 taken 3559
1340    #####:  897:				if (type == DT_REG && access(ent->d_name, X_OK) == 0)
1341    %%%%%:  897-block  0
1342branch  0 never executed
1343branch  1 never executed
1344    %%%%%:  897-block  1
1345call    2 never executed
1346branch  3 never executed
1347branch  4 never executed
1348    #####:  898:					match = 1;
1349    %%%%%:  898-block  0
1350unconditional  0 never executed
1351        -:  899:			}
1352        -:  900:
1353        -:  901:			/* If "/path/./", list only executable regular files */
1354     3559:  902:			else if (exec_path) {
1355     3559:  902-block  0
1356branch  0 taken 0 (fallthrough)
1357branch  1 taken 3559
1358    #####:  903:				if (type == DT_REG) {
1359    %%%%%:  903-block  0
1360branch  0 never executed
1361branch  1 never executed
1362        -:  904:					/* dir_tmp is dirname less "./", already
1363        -:  905:					 * allocated before the while loop */
1364    #####:  906:					snprintf(tmp, PATH_MAX, "%s%s", dir_tmp, ent->d_name);
1365        -:  907:
1366    #####:  908:					if (access(tmp, X_OK) == 0)
1367    %%%%%:  908-block  0
1368call    0 never executed
1369branch  1 never executed
1370branch  2 never executed
1371    #####:  909:						match = 1;
1372    %%%%%:  909-block  0
1373unconditional  0 never executed
1374        -:  910:				}
1375        -:  911:			}
1376        -:  912:
1377        -:  913:			/* No filter for everything else. Just print whatever is
1378        -:  914:			 * there */
1379        -:  915:			else
1380     3559:  916:				match = 1;
1381     3559:  916-block  0
1382unconditional  0 taken 3559
1383        -:  917:		}
1384        -:  918:
1385        -:  919:		/* If there is at least one char to complete (ex: "cd .[TAB]") */
1386        -:  920:		else {
1387        -:  921:			/* Check if possible completion match up to the length of
1388        -:  922:			 * filename. */
1389    71967:  923:			if (case_sens_path_comp) {
1390    71967:  923-block  0
1391branch  0 taken 7 (fallthrough)
1392branch  1 taken 71960
1393        7:  924:				if (*ent->d_name != *filename
1394        7:  924-block  0
1395branch  0 taken 0 (fallthrough)
1396branch  1 taken 7
1397    #####:  925:				|| (strncmp(filename, ent->d_name, filename_len) != 0))
1398    %%%%%:  925-block  0
1399branch  0 never executed
1400branch  1 never executed
1401        7:  926:					continue;
1402        7:  926-block  0
1403unconditional  0 taken 7
1404        -:  927:			} else {
1405    71960:  928:				if (TOUPPER(*ent->d_name) != TOUPPER(*filename)
1406    71960:  928-block  0
1407branch  0 taken 69903 (fallthrough)
1408branch  1 taken 2057
1409    69903:  928-block  1
1410branch  2 taken 69903 (fallthrough)
1411branch  3 taken 0
1412    69903:  928-block  2
1413unconditional  4 taken 69903
1414     2057:  928-block  3
1415unconditional  5 taken 2057
1416    71960:  928-block  4
1417branch  6 taken 60573 (fallthrough)
1418branch  7 taken 11387
1419    60573:  928-block  5
1420branch  8 taken 60573 (fallthrough)
1421branch  9 taken 0
1422    60573:  928-block  6
1423unconditional 10 taken 60573
1424    11387:  928-block  7
1425unconditional 11 taken 11387
1426    71960:  928-block  8
1427branch 12 taken 2049 (fallthrough)
1428branch 13 taken 69911
1429     2049:  929:				|| (strncasecmp(filename, ent->d_name, filename_len) != 0))
1430     2049:  929-block  0
1431branch  0 taken 1495 (fallthrough)
1432branch  1 taken 554
1433    71406:  930:					continue;
1434    71406:  930-block  0
1435unconditional  0 taken 71406
1436        -:  931:			}
1437        -:  932:
1438      554:  933:			if (*rl_line_buffer == 'c'
1439      554:  933-block  0
1440branch  0 taken 0 (fallthrough)
1441branch  1 taken 554
1442    #####:  934:			&& strncmp(rl_line_buffer, "cd ", 3) == 0) {
1443    %%%%%:  934-block  0
1444branch  0 never executed
1445branch  1 never executed
1446    #####:  935:				ret = -1;
1447        -:  936:
1448    #####:  937:				switch (type) {
1449    %%%%%:  937-block  0
1450branch  0 never executed
1451branch  1 never executed
1452branch  2 never executed
1453    #####:  938:				case DT_LNK:
1454    #####:  939:					if (dirname[0] == '.' && !dirname[1]) {
1455    %%%%%:  939-block  0
1456branch  0 never executed
1457branch  1 never executed
1458    %%%%%:  939-block  1
1459branch  2 never executed
1460branch  3 never executed
1461    #####:  940:						ret = get_link_ref(ent->d_name);
1462    %%%%%:  940-block  0
1463call    0 never executed
1464unconditional  1 never executed
1465        -:  941:					} else {
1466    #####:  942:						snprintf(tmp, PATH_MAX, "%s%s", dirname, ent->d_name);
1467    #####:  943:						ret = get_link_ref(tmp);
1468    %%%%%:  943-block  0
1469call    0 never executed
1470unconditional  1 never executed
1471        -:  944:					}
1472        -:  945:
1473    #####:  946:					if (ret == S_IFDIR)
1474    %%%%%:  946-block  0
1475branch  0 never executed
1476branch  1 never executed
1477    #####:  947:						match = 1;
1478    %%%%%:  947-block  0
1479unconditional  0 never executed
1480    #####:  948:					break;
1481    %%%%%:  948-block  0
1482unconditional  0 never executed
1483        -:  949:
1484    #####:  950:				case DT_DIR: match = 1; break;
1485    %%%%%:  950-block  0
1486unconditional  0 never executed
1487        -:  951:
1488    #####:  952:				default: break;
1489    %%%%%:  952-block  0
1490unconditional  0 never executed
1491        -:  953:				}
1492        -:  954:			}
1493        -:  955:
1494      554:  956:			else if (*rl_line_buffer == 'o'
1495      554:  956-block  0
1496branch  0 taken 0 (fallthrough)
1497branch  1 taken 554
1498    #####:  957:			&& (strncmp(rl_line_buffer, "o ", 2) == 0
1499    %%%%%:  957-block  0
1500branch  0 never executed
1501branch  1 never executed
1502    #####:  958:			|| strncmp(rl_line_buffer, "open ", 5) == 0)) {
1503    %%%%%:  958-block  0
1504branch  0 never executed
1505branch  1 never executed
1506    #####:  959:				ret = -1;
1507        -:  960:
1508    #####:  961:				switch (type) {
1509    %%%%%:  961-block  0
1510branch  0 never executed
1511branch  1 never executed
1512branch  2 never executed
1513    #####:  962:				case DT_REG: /* fallthrough */
1514    #####:  963:				case DT_DIR: match = 1; break;
1515    %%%%%:  963-block  0
1516unconditional  0 never executed
1517        -:  964:
1518    #####:  965:				case DT_LNK:
1519    #####:  966:					if (dirname[0] == '.' && !dirname[1]) {
1520    %%%%%:  966-block  0
1521branch  0 never executed
1522branch  1 never executed
1523    %%%%%:  966-block  1
1524branch  2 never executed
1525branch  3 never executed
1526    #####:  967:						ret = get_link_ref(ent->d_name);
1527    %%%%%:  967-block  0
1528call    0 never executed
1529unconditional  1 never executed
1530        -:  968:					} else {
1531    #####:  969:						snprintf(tmp, PATH_MAX, "%s%s", dirname, ent->d_name);
1532    #####:  970:						ret = get_link_ref(tmp);
1533    %%%%%:  970-block  0
1534call    0 never executed
1535unconditional  1 never executed
1536        -:  971:					}
1537        -:  972:
1538    #####:  973:					if (ret == S_IFDIR || ret == S_IFREG)
1539    %%%%%:  973-block  0
1540branch  0 never executed
1541branch  1 never executed
1542    %%%%%:  973-block  1
1543branch  2 never executed
1544branch  3 never executed
1545    #####:  974:						match = 1;
1546    %%%%%:  974-block  0
1547unconditional  0 never executed
1548    #####:  975:					break;
1549    %%%%%:  975-block  0
1550unconditional  0 never executed
1551        -:  976:
1552    #####:  977:				default: break;
1553    %%%%%:  977-block  0
1554unconditional  0 never executed
1555        -:  978:				}
1556        -:  979:			}
1557        -:  980:
1558      554:  981:			else if (*rl_line_buffer == 't'
1559      554:  981-block  0
1560branch  0 taken 0 (fallthrough)
1561branch  1 taken 554
1562    #####:  982:			&& (strncmp(rl_line_buffer, "t ", 2) == 0
1563    %%%%%:  982-block  0
1564branch  0 never executed
1565branch  1 never executed
1566    #####:  983:			|| strncmp(rl_line_buffer, "tr ", 3) == 0
1567    %%%%%:  983-block  0
1568branch  0 never executed
1569branch  1 never executed
1570    #####:  984:			|| strncmp(rl_line_buffer, "trash ", 6) == 0)) {
1571    %%%%%:  984-block  0
1572branch  0 never executed
1573branch  1 never executed
1574    #####:  985:				if (type != DT_BLK && type != DT_CHR)
1575    %%%%%:  985-block  0
1576branch  0 never executed
1577branch  1 never executed
1578    %%%%%:  985-block  1
1579branch  2 never executed
1580branch  3 never executed
1581    #####:  986:					match = 1;
1582    %%%%%:  986-block  0
1583unconditional  0 never executed
1584        -:  987:			}
1585        -:  988:
1586      554:  989:			else if (exec) {
1587      554:  989-block  0
1588branch  0 taken 0 (fallthrough)
1589branch  1 taken 554
1590    #####:  990:				if (type == DT_REG && access(ent->d_name, X_OK) == 0)
1591    %%%%%:  990-block  0
1592branch  0 never executed
1593branch  1 never executed
1594    %%%%%:  990-block  1
1595call    2 never executed
1596branch  3 never executed
1597branch  4 never executed
1598    #####:  991:					match = 1;
1599    %%%%%:  991-block  0
1600unconditional  0 never executed
1601        -:  992:			}
1602        -:  993:
1603      554:  994:			else if (exec_path) {
1604      554:  994-block  0
1605branch  0 taken 0 (fallthrough)
1606branch  1 taken 554
1607    #####:  995:				if (type == DT_REG) {
1608    %%%%%:  995-block  0
1609branch  0 never executed
1610branch  1 never executed
1611    #####:  996:					snprintf(tmp, PATH_MAX, "%s%s", dir_tmp, ent->d_name);
1612    #####:  997:					if (access(tmp, X_OK) == 0)
1613    %%%%%:  997-block  0
1614call    0 never executed
1615branch  1 never executed
1616branch  2 never executed
1617    #####:  998:						match = 1;
1618    %%%%%:  998-block  0
1619unconditional  0 never executed
1620        -:  999:				}
1621        -: 1000:			}
1622        -: 1001:
1623        -: 1002:			else
1624      554: 1003:				match = 1;
1625      554: 1003-block  0
1626unconditional  0 taken 554
1627        -: 1004:		}
1628        -: 1005:
1629     4113: 1006:		if (match)
1630     4113: 1006-block  0
1631branch  0 taken 4113 (fallthrough)
1632branch  1 taken 0
1633     4113: 1007:			break;
1634     4113: 1007-block  0
1635unconditional  0 taken 4113
1636        -: 1008:	}
1637        -: 1009:
1638     4514: 1010:	if (dir_tmp) { /* == exec_path */
1639     4514: 1010-block  0
1640branch  0 taken 0 (fallthrough)
1641branch  1 taken 4514
1642    #####: 1011:		free(dir_tmp);
1643    #####: 1012:		dir_tmp = (char *)NULL;
1644    %%%%%: 1012-block  0
1645unconditional  0 never executed
1646        -: 1013:	}
1647        -: 1014:
1648        -: 1015:	/* readdir() returns NULL on reaching the end of directory stream.
1649        -: 1016:	 * So that if entry is NULL, we have no matches */
1650        -: 1017:
1651     4514: 1018:	if (!ent) { /* == !match */
1652     4514: 1018-block  0
1653branch  0 taken 401 (fallthrough)
1654branch  1 taken 4113
1655      401: 1019:		if (directory) {
1656      401: 1019-block  0
1657branch  0 taken 395 (fallthrough)
1658branch  1 taken 6
1659      395: 1020:			closedir(directory);
1660      395: 1020-block  0
1661call    0 returned 395
1662      395: 1021:			directory = (DIR *)NULL;
1663unconditional  0 taken 395
1664        -: 1022:		}
1665        -: 1023:
1666      401: 1024:		if (dirname) {
1667      401: 1024-block  0
1668branch  0 taken 401 (fallthrough)
1669branch  1 taken 0
1670      401: 1025:			free(dirname);
1671      401: 1026:			dirname = (char *)NULL;
1672      401: 1026-block  0
1673unconditional  0 taken 401
1674        -: 1027:		}
1675        -: 1028:
1676      401: 1029:		if (filename) {
1677      401: 1029-block  0
1678branch  0 taken 401 (fallthrough)
1679branch  1 taken 0
1680      401: 1030:			free(filename);
1681      401: 1031:			filename = (char *)NULL;
1682      401: 1031-block  0
1683unconditional  0 taken 401
1684        -: 1032:		}
1685        -: 1033:
1686      401: 1034:		if (users_dirname) {
1687      401: 1034-block  0
1688branch  0 taken 401 (fallthrough)
1689branch  1 taken 0
1690      401: 1035:			free(users_dirname);
1691      401: 1036:			users_dirname = (char *)NULL;
1692      401: 1036-block  0
1693unconditional  0 taken 401
1694        -: 1037:		}
1695        -: 1038:
1696      401: 1039:		return (char *)NULL;
1697      401: 1039-block  0
1698unconditional  0 taken 401
1699        -: 1040:	}
1700        -: 1041:
1701        -: 1042:	/* We have a match */
1702        -: 1043:	else {
1703     4113: 1044:		char *temp = (char *)NULL;
1704        -: 1045:
1705        -: 1046:		/* dirname && (strcmp(dirname, ".") != 0) */
1706     4113: 1047:		if (dirname && (dirname[0] != '.' || dirname[1])) {
1707     4113: 1047-block  0
1708branch  0 taken 4113 (fallthrough)
1709branch  1 taken 0
1710     4113: 1047-block  1
1711branch  2 taken 4 (fallthrough)
1712branch  3 taken 4109
1713        4: 1047-block  2
1714branch  4 taken 1 (fallthrough)
1715branch  5 taken 3
1716        -: 1048:/*			if (rl_complete_with_tilde_expansion && *users_dirname == '~') {
1717        -: 1049:				size_t dirlen = strlen(dirname);
1718        -: 1050:				temp = (char *)xnmalloc(dirlen + strlen(ent->d_name) + 2,
1719        -: 1051:									sizeof(char));
1720        -: 1052:				strcpy(temp, dirname);
1721        -: 1053:				// Canonicalization cuts off any final slash present.
1722        -: 1054:				// We need to add it back.
1723        -: 1055:
1724        -: 1056:				if (dirname[dirlen - 1] != '/') {
1725        -: 1057:					temp[dirlen] = '/';
1726        -: 1058:					temp[dirlen + 1] = '\0';
1727        -: 1059:				}
1728        -: 1060:			} else { */
1729     4110: 1061:			temp = (char *)xnmalloc(strlen(users_dirname) +
1730     4110: 1062:					strlen(ent->d_name) + 1, sizeof(char));
1731     4110: 1062-block  0
1732call    0 returned 4110
1733     4110: 1063:			strcpy(temp, users_dirname);
1734        -: 1064:/*			} */
1735     4110: 1065:			strcat(temp, ent->d_name);
1736unconditional  0 taken 4110
1737        -: 1066:		} else {
1738        3: 1067:			temp = savestring(ent->d_name, strlen(ent->d_name));
1739        3: 1067-block  0
1740call    0 returned 3
1741unconditional  1 taken 3
1742        -: 1068:		}
1743        -: 1069:
1744     4113: 1070:		return (temp);
1745     4113: 1070-block  0
1746unconditional  0 taken 4113
1747        -: 1071:	}
1748        -: 1072:}
1749        -: 1073:
1750        -: 1074:/* Used by bookmarks completion */
1751        -: 1075:static char *
1752function bookmarks_generator called 41 returned 100% blocks executed 91%
1753       41: 1076:bookmarks_generator(const char *text, int state)
1754        -: 1077:{
1755       41: 1078:	if (!bookmark_names)
1756       41: 1078-block  0
1757branch  0 taken 0 (fallthrough)
1758branch  1 taken 41
1759    #####: 1079:		return (char *)NULL;
1760    %%%%%: 1079-block  0
1761unconditional  0 never executed
1762        -: 1080:
1763        -: 1081:	static int i;
1764        -: 1082:	static size_t len;
1765        -: 1083:	char *name;
1766        -: 1084:
1767       41: 1085:	if (!state) {
1768       41: 1085-block  0
1769branch  0 taken 3 (fallthrough)
1770branch  1 taken 38
1771        3: 1086:		i = 0;
1772        3: 1087:		len = strlen(text);
1773        3: 1087-block  0
1774unconditional  0 taken 3
1775        -: 1088:	}
1776        -: 1089:
1777        -: 1090:	/* Look for bookmarks in bookmark names for a match */
1778       60: 1091:	while ((name = bookmark_names[i++]) != NULL) {
1779       41: 1091-block  0
1780unconditional  0 taken 41
1781       60: 1091-block  1
1782branch  1 taken 57
1783branch  2 taken 3 (fallthrough)
1784       57: 1092:		if (strncmp(name, text, len) == 0)
1785       57: 1092-block  0
1786branch  0 taken 38 (fallthrough)
1787branch  1 taken 19
1788       38: 1093:			return strdup(name);
1789       38: 1093-block  0
1790call    0 returned 38
1791unconditional  1 taken 38
1792        -: 1094:	}
1793        -: 1095:
1794        3: 1096:	return (char *)NULL;
1795        3: 1096-block  0
1796unconditional  0 taken 3
1797        -: 1097:}
1798        -: 1098:
1799        -: 1099:/* Used by history completion */
1800        -: 1100:static char *
1801function hist_generator called 0 returned 0% blocks executed 0%
1802    #####: 1101:hist_generator(const char *text, int state)
1803        -: 1102:{
1804    #####: 1103:	if (!history)
1805    %%%%%: 1103-block  0
1806branch  0 never executed
1807branch  1 never executed
1808    #####: 1104:		return (char *)NULL;
1809    %%%%%: 1104-block  0
1810unconditional  0 never executed
1811        -: 1105:
1812        -: 1106:	static int i;
1813        -: 1107:	static size_t len;
1814        -: 1108:	char *name;
1815        -: 1109:
1816    #####: 1110:	if (!state) {
1817    %%%%%: 1110-block  0
1818branch  0 never executed
1819branch  1 never executed
1820    #####: 1111:		i = 0;
1821    #####: 1112:		len = strlen(text);
1822    %%%%%: 1112-block  0
1823unconditional  0 never executed
1824        -: 1113:	}
1825        -: 1114:
1826        -: 1115:	/* Look for cmd history entries for a match */
1827    #####: 1116:	while ((name = history[i++]) != NULL) {
1828    %%%%%: 1116-block  0
1829unconditional  0 never executed
1830    %%%%%: 1116-block  1
1831branch  1 never executed
1832branch  2 never executed
1833    #####: 1117:		if (strncmp(name, text, len) == 0)
1834    %%%%%: 1117-block  0
1835branch  0 never executed
1836branch  1 never executed
1837    #####: 1118:			return strdup(name);
1838    %%%%%: 1118-block  0
1839call    0 never executed
1840unconditional  1 never executed
1841        -: 1119:	}
1842        -: 1120:
1843    #####: 1121:	return (char *)NULL;
1844    %%%%%: 1121-block  0
1845unconditional  0 never executed
1846        -: 1122:}
1847        -: 1123:
1848        -: 1124:/* Expand string into matching path in the jump database. Used by
1849        -: 1125: * j, jc, and jp commands */
1850        -: 1126:static char *
1851function jump_generator called 18 returned 100% blocks executed 75%
1852       18: 1127:jump_generator(const char *text, int state)
1853        -: 1128:{
1854        -: 1129:	static int i;
1855        -: 1130:	char *name;
1856        -: 1131:
1857       18: 1132:	if (!state)
1858       18: 1132-block  0
1859branch  0 taken 1 (fallthrough)
1860branch  1 taken 17
1861        1: 1133:		i = 0;
1862        1: 1133-block  0
1863unconditional  0 taken 1
1864        -: 1134:
1865       18: 1135:	if (!jump_db)
1866       18: 1135-block  0
1867branch  0 taken 0 (fallthrough)
1868branch  1 taken 18
1869    #####: 1136:		return (char *)NULL;
1870    %%%%%: 1136-block  0
1871unconditional  0 never executed
1872        -: 1137:
1873        -: 1138:	/* Look for matches in the dirhist list */
1874       48: 1139:	while ((name = jump_db[i++].path) != NULL) {
1875       18: 1139-block  0
1876unconditional  0 taken 18
1877       48: 1139-block  1
1878branch  1 taken 47
1879branch  2 taken 1 (fallthrough)
1880        -: 1140:		/* Exclude CWD */
1881       47: 1141:		if (name[1] == ws[cur_ws].path[1] && strcmp(name, ws[cur_ws].path) == 0)
1882       47: 1141-block  0
1883branch  0 taken 36 (fallthrough)
1884branch  1 taken 11
1885       36: 1141-block  1
1886branch  2 taken 1 (fallthrough)
1887branch  3 taken 35
1888        1: 1142:			continue;
1889        1: 1142-block  0
1890unconditional  0 taken 1
1891        -: 1143:		/* Filter by parent */
1892       46: 1144:		if (rl_line_buffer[1] == 'p') {
1893       46: 1144-block  0
1894branch  0 taken 0 (fallthrough)
1895branch  1 taken 46
1896    #####: 1145:			if (!strstr(ws[cur_ws].path, name))
1897    %%%%%: 1145-block  0
1898branch  0 never executed
1899branch  1 never executed
1900    #####: 1146:				continue;
1901    %%%%%: 1146-block  0
1902unconditional  0 never executed
1903        -: 1147:		}
1904        -: 1148:		/* Filter by child */
1905       46: 1149:		else if (rl_line_buffer[1] == 'c') {
1906       46: 1149-block  0
1907branch  0 taken 0 (fallthrough)
1908branch  1 taken 46
1909    #####: 1150:			if (!strstr(name, ws[cur_ws].path))
1910    %%%%%: 1150-block  0
1911branch  0 never executed
1912branch  1 never executed
1913    #####: 1151:				continue;
1914    %%%%%: 1151-block  0
1915unconditional  0 never executed
1916        -: 1152:		}
1917        -: 1153:
1918       46: 1154:		if (strstr(name, text))
1919       46: 1154-block  0
1920branch  0 taken 17 (fallthrough)
1921branch  1 taken 29
1922       17: 1155:			return strdup(name);
1923       17: 1155-block  0
1924call    0 returned 17
1925unconditional  1 taken 17
1926        -: 1156:	}
1927        -: 1157:
1928        1: 1158:	return (char *)NULL;
1929        1: 1158-block  0
1930unconditional  0 taken 1
1931        -: 1159:}
1932        -: 1160:
1933        -: 1161:/* Expand jump order number into the corresponding path. Used by the
1934        -: 1162: * jo command */
1935        -: 1163:static char *
1936function jump_entries_generator called 0 returned 0% blocks executed 0%
1937    #####: 1164:jump_entries_generator(const char *text, int state)
1938        -: 1165:{
1939        -: 1166:	static size_t i;
1940        -: 1167:	char *name;
1941        -: 1168:
1942    #####: 1169:	if (!state)
1943    %%%%%: 1169-block  0
1944branch  0 never executed
1945branch  1 never executed
1946    #####: 1170:		i = 0;
1947    %%%%%: 1170-block  0
1948unconditional  0 never executed
1949        -: 1171:
1950    #####: 1172:	int num_text = atoi(text);
1951        -: 1173:
1952        -: 1174:	/* Check list of jump entries for a match */
1953    #####: 1175:	while (i <= jump_n && (name = jump_db[i++].path) != NULL)
1954    %%%%%: 1175-block  0
1955unconditional  0 never executed
1956    %%%%%: 1175-block  1
1957branch  1 never executed
1958branch  2 never executed
1959    %%%%%: 1175-block  2
1960branch  3 never executed
1961branch  4 never executed
1962    #####: 1176:		if (*name == *jump_db[num_text - 1].path && strcmp(name,
1963    %%%%%: 1176-block  0
1964branch  0 never executed
1965branch  1 never executed
1966    #####: 1177:					jump_db[num_text - 1].path) == 0)
1967    %%%%%: 1177-block  0
1968branch  0 never executed
1969branch  1 never executed
1970    #####: 1178:			return strdup(name);
1971    %%%%%: 1178-block  0
1972call    0 never executed
1973unconditional  1 never executed
1974        -: 1179:
1975    #####: 1180:	return (char *)NULL;
1976    %%%%%: 1180-block  0
1977unconditional  0 never executed
1978        -: 1181:}
1979        -: 1182:
1980        -: 1183:static char *
1981function cschemes_generator called 21 returned 100% blocks executed 91%
1982       21: 1184:cschemes_generator(const char *text, int state)
1983        -: 1185:{
1984       21: 1186:	if (!color_schemes)
1985       21: 1186-block  0
1986branch  0 taken 0 (fallthrough)
1987branch  1 taken 21
1988    #####: 1187:		return (char *)NULL;
1989    %%%%%: 1187-block  0
1990unconditional  0 never executed
1991        -: 1188:
1992        -: 1189:	static int i;
1993        -: 1190:	static size_t len;
1994        -: 1191:	char *name;
1995        -: 1192:
1996       21: 1193:	if (!state) {
1997       21: 1193-block  0
1998branch  0 taken 1 (fallthrough)
1999branch  1 taken 20
2000        1: 1194:		i = 0;
2001        1: 1195:		len = strlen(text);
2002        1: 1195-block  0
2003unconditional  0 taken 1
2004        -: 1196:	} /* The state variable is zero only the first time the function is
2005        -: 1197:	called, and a non-zero positive in later calls. This means that i
2006        -: 1198:	and len will be necessarilly initialized the first time */
2007        -: 1199:
2008        -: 1200:	/* Look for color schemes in color_schemes for a match */
2009       21: 1201:	while ((name = color_schemes[i++]) != NULL) {
2010       21: 1201-block  0
2011unconditional  0 taken 21
2012       21: 1201-block  1
2013branch  1 taken 20
2014branch  2 taken 1 (fallthrough)
2015       20: 1202:		if (strncmp(name, text, len) == 0)
2016       20: 1202-block  0
2017branch  0 taken 20 (fallthrough)
2018branch  1 taken 0
2019       20: 1203:			return strdup(name);
2020       20: 1203-block  0
2021call    0 returned 20
2022unconditional  1 taken 20
2023        -: 1204:	}
2024        -: 1205:
2025        1: 1206:	return (char *)NULL;
2026        1: 1206-block  0
2027unconditional  0 taken 1
2028        -: 1207:}
2029        -: 1208:
2030        -: 1209:/* Used by profiles completion */
2031        -: 1210:static char *
2032function profiles_generator called 8 returned 100% blocks executed 91%
2033        8: 1211:profiles_generator(const char *text, int state)
2034        -: 1212:{
2035        8: 1213:	if (!profile_names)
2036        8: 1213-block  0
2037branch  0 taken 0 (fallthrough)
2038branch  1 taken 8
2039    #####: 1214:		return (char *)NULL;
2040    %%%%%: 1214-block  0
2041unconditional  0 never executed
2042        -: 1215:
2043        -: 1216:	static int i;
2044        -: 1217:	static size_t len;
2045        -: 1218:	char *name;
2046        -: 1219:
2047        8: 1220:	if (!state) {
2048        8: 1220-block  0
2049branch  0 taken 2 (fallthrough)
2050branch  1 taken 6
2051        2: 1221:		i = 0;
2052        2: 1222:		len = strlen(text);
2053        2: 1222-block  0
2054unconditional  0 taken 2
2055        -: 1223:	} /* The state variable is zero only the first time the function is
2056        -: 1224:	called, and a non-zero positive in later calls. This means that i
2057        -: 1225:	and len will be necessarilly initialized the first time */
2058        -: 1226:
2059        -: 1227:	/* Look for profiles in profile_names for a match */
2060       13: 1228:	while ((name = profile_names[i++]) != NULL) {
2061        8: 1228-block  0
2062unconditional  0 taken 8
2063       13: 1228-block  1
2064branch  1 taken 11
2065branch  2 taken 2 (fallthrough)
2066       11: 1229:		if (strncmp(name, text, len) == 0)
2067       11: 1229-block  0
2068branch  0 taken 6 (fallthrough)
2069branch  1 taken 5
2070        6: 1230:			return strdup(name);
2071        6: 1230-block  0
2072call    0 returned 6
2073unconditional  1 taken 6
2074        -: 1231:	}
2075        -: 1232:
2076        2: 1233:	return (char *)NULL;
2077        2: 1233-block  0
2078unconditional  0 taken 2
2079        -: 1234:}
2080        -: 1235:
2081        -: 1236:/* Used by ELN expansion */
2082        -: 1237:static char *
2083function filenames_gen_text called 7 returned 100% blocks executed 92%
2084        7: 1238:filenames_gen_text(const char *text, int state)
2085        -: 1239:{
2086        -: 1240:	static size_t i, len = 0;
2087        -: 1241:	char *name;
2088        7: 1242:	rl_filename_completion_desired = 1;
2089        -: 1243:	/* According to the GNU readline documention: "If it is set to a
2090        -: 1244:	 * non-zero value, directory names have a slash appended and
2091        -: 1245:	 * Readline attempts to quote completed file names if they contain
2092        -: 1246:	 * any embedded word break characters." To make the quoting part
2093        -: 1247:	 * work I had to specify a custom quoting function (my_rl_quote) */
2094        7: 1248:	if (!state) { /* state is zero only the first time readline is
2095        7: 1248-block  0
2096branch  0 taken 4 (fallthrough)
2097branch  1 taken 3
2098        -: 1249:	executed */
2099        4: 1250:		i = 0;
2100        4: 1251:		len = strlen(text);
2101        4: 1251-block  0
2102unconditional  0 taken 4
2103        -: 1252:	}
2104        -: 1253:
2105        -: 1254:	/* Check list of currently displayed files for a match */
2106      132: 1255:	while (i < files && (name = file_info[i++].name) != NULL)
2107        7: 1255-block  0
2108unconditional  0 taken 7
2109      132: 1255-block  1
2110branch  1 taken 128 (fallthrough)
2111branch  2 taken 4
2112      128: 1255-block  2
2113branch  3 taken 128
2114branch  4 taken 0 (fallthrough)
2115     256*: 1256:		if (case_sens_path_comp ? strncmp(name, text, len) == 0
2116      128: 1256-block  0
2117branch  0 taken 0 (fallthrough)
2118branch  1 taken 128
2119    %%%%%: 1256-block  1
2120unconditional  2 never executed
2121      128: 1256-block  2
2122branch  3 taken 3 (fallthrough)
2123branch  4 taken 125
2124      128: 1257:		: strncasecmp(name, text, len) == 0)
2125      128: 1257-block  0
2126unconditional  0 taken 128
2127        3: 1258:			return strdup(name);
2128        3: 1258-block  0
2129call    0 returned 3
2130unconditional  1 taken 3
2131        -: 1259:
2132        4: 1260:	return (char *)NULL;
2133        4: 1260-block  0
2134unconditional  0 taken 4
2135        -: 1261:}
2136        -: 1262:
2137        -: 1263:/* Used by ELN expansion */
2138        -: 1264:static char *
2139function filenames_gen_eln called 0 returned 0% blocks executed 0%
2140    #####: 1265:filenames_gen_eln(const char *text, int state)
2141        -: 1266:{
2142        -: 1267:	static size_t i;
2143        -: 1268:	char *name;
2144    #####: 1269:	rl_filename_completion_desired = 1;
2145        -: 1270:
2146    #####: 1271:	if (!state)
2147    %%%%%: 1271-block  0
2148branch  0 never executed
2149branch  1 never executed
2150    #####: 1272:		i = 0;
2151    %%%%%: 1272-block  0
2152unconditional  0 never executed
2153        -: 1273:
2154    #####: 1274:	int num_text = atoi(text);
2155        -: 1275:
2156        -: 1276:	/* Check list of currently displayed files for a match */
2157    #####: 1277:	while (i < files && (name = file_info[i++].name) != NULL) {
2158    %%%%%: 1277-block  0
2159unconditional  0 never executed
2160    %%%%%: 1277-block  1
2161branch  1 never executed
2162branch  2 never executed
2163    %%%%%: 1277-block  2
2164branch  3 never executed
2165branch  4 never executed
2166    #####: 1278:		if (*name == *file_info[num_text - 1].name
2167    %%%%%: 1278-block  0
2168branch  0 never executed
2169branch  1 never executed
2170    #####: 1279:		&& strcmp(name, file_info[num_text - 1].name) == 0) {
2171    %%%%%: 1279-block  0
2172branch  0 never executed
2173branch  1 never executed
2174        -: 1280:#ifndef _NO_SUGGESTIONS
2175    #####: 1281:			if (suggestion_buf)
2176    %%%%%: 1281-block  0
2177branch  0 never executed
2178branch  1 never executed
2179    #####: 1282:				clear_suggestion();
2180    %%%%%: 1282-block  0
2181call    0 never executed
2182unconditional  1 never executed
2183        -: 1283:#endif
2184    #####: 1284:			return strdup(name);
2185    %%%%%: 1284-block  0
2186call    0 never executed
2187unconditional  1 never executed
2188        -: 1285:		}
2189        -: 1286:	}
2190        -: 1287:
2191    #####: 1288:	return (char *)NULL;
2192    %%%%%: 1288-block  0
2193unconditional  0 never executed
2194        -: 1289:}
2195        -: 1290:
2196        -: 1291:/* Used by commands completion */
2197        -: 1292:static char *
2198function bin_cmd_generator called 2 returned 100% blocks executed 92%
2199        2: 1293:bin_cmd_generator(const char *text, int state)
2200        -: 1294:{
2201        2: 1295:	if (!bin_commands)
2202        2: 1295-block  0
2203branch  0 taken 0 (fallthrough)
2204branch  1 taken 2
2205    #####: 1296:		return (char *)NULL;
2206    %%%%%: 1296-block  0
2207unconditional  0 never executed
2208        -: 1297:
2209        -: 1298:	static int i;
2210        -: 1299:	static size_t len;
2211        -: 1300:	char *name;
2212        -: 1301:
2213        2: 1302:	if (!state) {
2214        2: 1302-block  0
2215branch  0 taken 1 (fallthrough)
2216branch  1 taken 1
2217        1: 1303:		i = 0;
2218        1: 1304:		len = strlen(text);
2219        1: 1304-block  0
2220unconditional  0 taken 1
2221        -: 1305:	}
2222        -: 1306:
2223     3746: 1307:	while ((name = bin_commands[i++]) != NULL) {
2224        2: 1307-block  0
2225unconditional  0 taken 2
2226     3746: 1307-block  1
2227branch  1 taken 3745
2228branch  2 taken 1 (fallthrough)
2229     3745: 1308:		if (*text == *name && strncmp(name, text, len) == 0)
2230     3745: 1308-block  0
2231branch  0 taken 60 (fallthrough)
2232branch  1 taken 3685
2233       60: 1308-block  1
2234branch  2 taken 1 (fallthrough)
2235branch  3 taken 59
2236        1: 1309:			return strdup(name);
2237        1: 1309-block  0
2238call    0 returned 1
2239unconditional  1 taken 1
2240        -: 1310:	}
2241        -: 1311:
2242        1: 1312:	return (char *)NULL;
2243        1: 1312-block  0
2244unconditional  0 taken 1
2245        -: 1313:}
2246        -: 1314:
2247        -: 1315:static char *
2248function sort_num_generator called 0 returned 0% blocks executed 0%
2249    #####: 1316:sort_num_generator(const char *text, int state)
2250        -: 1317:{
2251        -: 1318:	static size_t i;
2252        -: 1319:	char *name;
2253    #####: 1320:	rl_filename_completion_desired = 1;
2254        -: 1321:
2255    #####: 1322:	if (!state)
2256    %%%%%: 1322-block  0
2257branch  0 never executed
2258branch  1 never executed
2259    #####: 1323:		i = 0;
2260    %%%%%: 1323-block  0
2261unconditional  0 never executed
2262        -: 1324:
2263    #####: 1325:	int num_text = atoi(text);
2264        -: 1326:	static char *sorts[] = {
2265        -: 1327:	    "none",
2266        -: 1328:	    "name",
2267        -: 1329:	    "size",
2268        -: 1330:	    "atime",
2269        -: 1331:	    "btime",
2270        -: 1332:	    "ctime",
2271        -: 1333:	    "mtime",
2272        -: 1334:	    "version",
2273        -: 1335:	    "extension",
2274        -: 1336:	    "inode",
2275        -: 1337:	    "owner",
2276        -: 1338:	    "group",
2277        -: 1339:	    NULL
2278        -: 1340:	};
2279        -: 1341:
2280        -: 1342:	/* Check list of currently displayed files for a match */
2281    #####: 1343:	while (i <= SORT_TYPES && (name = sorts[i++]) != NULL) {
2282    %%%%%: 1343-block  0
2283unconditional  0 never executed
2284    %%%%%: 1343-block  1
2285branch  1 never executed
2286branch  2 never executed
2287    %%%%%: 1343-block  2
2288branch  3 never executed
2289branch  4 never executed
2290    #####: 1344:		if (*name == *sorts[num_text]
2291    %%%%%: 1344-block  0
2292branch  0 never executed
2293branch  1 never executed
2294    #####: 1345:		&& strcmp(name, sorts[num_text]) == 0)
2295    %%%%%: 1345-block  0
2296branch  0 never executed
2297branch  1 never executed
2298    #####: 1346:			return strdup(name);
2299    %%%%%: 1346-block  0
2300call    0 never executed
2301unconditional  1 never executed
2302        -: 1347:	}
2303        -: 1348:
2304    #####: 1349:	return (char *)NULL;
2305    %%%%%: 1349-block  0
2306unconditional  0 never executed
2307        -: 1350:}
2308        -: 1351:
2309        -: 1352:static char *
2310function nets_generator called 0 returned 0% blocks executed 0%
2311    #####: 1353:nets_generator(const char *text, int state)
2312        -: 1354:{
2313    #####: 1355:	if (!remotes)
2314    %%%%%: 1355-block  0
2315branch  0 never executed
2316branch  1 never executed
2317    #####: 1356:		return (char *)NULL;
2318    %%%%%: 1356-block  0
2319unconditional  0 never executed
2320        -: 1357:
2321        -: 1358:	static int i;
2322        -: 1359:	static size_t len;
2323        -: 1360:	char *name;
2324        -: 1361:
2325    #####: 1362:	if (!state) {
2326    %%%%%: 1362-block  0
2327branch  0 never executed
2328branch  1 never executed
2329    #####: 1363:		i = 0;
2330    #####: 1364:		len = strlen(text);
2331    %%%%%: 1364-block  0
2332unconditional  0 never executed
2333        -: 1365:	}
2334        -: 1366:
2335    #####: 1367:	while ((name = remotes[i++].name) != NULL) {
2336    %%%%%: 1367-block  0
2337unconditional  0 never executed
2338    %%%%%: 1367-block  1
2339branch  1 never executed
2340branch  2 never executed
2341    #####: 1368:		if (strncmp(name, text, len) == 0)
2342    %%%%%: 1368-block  0
2343branch  0 never executed
2344branch  1 never executed
2345    #####: 1369:			return strdup(name);
2346    %%%%%: 1369-block  0
2347call    0 never executed
2348unconditional  1 never executed
2349        -: 1370:	}
2350        -: 1371:
2351    #####: 1372:	return (char *)NULL;
2352    %%%%%: 1372-block  0
2353unconditional  0 never executed
2354        -: 1373:}
2355        -: 1374:
2356        -: 1375:static char *
2357function sort_name_generator called 0 returned 0% blocks executed 0%
2358    #####: 1376:sort_name_generator(const char *text, int state)
2359        -: 1377:{
2360        -: 1378:	static int i;
2361        -: 1379:	static size_t len;
2362        -: 1380:	char *name;
2363        -: 1381:
2364    #####: 1382:	if (!state) {
2365    %%%%%: 1382-block  0
2366branch  0 never executed
2367branch  1 never executed
2368    #####: 1383:		i = 0;
2369    #####: 1384:		len = strlen(text);
2370    %%%%%: 1384-block  0
2371unconditional  0 never executed
2372        -: 1385:	}
2373        -: 1386:
2374        -: 1387:	static char *sorts[] = {
2375        -: 1388:	    "none",
2376        -: 1389:	    "name",
2377        -: 1390:	    "size",
2378        -: 1391:	    "atime",
2379        -: 1392:	    "btime",
2380        -: 1393:	    "ctime",
2381        -: 1394:	    "mtime",
2382        -: 1395:	    "version",
2383        -: 1396:	    "extension",
2384        -: 1397:	    "inode",
2385        -: 1398:	    "owner",
2386        -: 1399:	    "group",
2387        -: 1400:	    NULL};
2388        -: 1401:
2389    #####: 1402:	while ((name = sorts[i++]) != NULL) {
2390    %%%%%: 1402-block  0
2391unconditional  0 never executed
2392    %%%%%: 1402-block  1
2393branch  1 never executed
2394branch  2 never executed
2395    #####: 1403:		if (*text == *name && strncmp(name, text, len) == 0)
2396    %%%%%: 1403-block  0
2397branch  0 never executed
2398branch  1 never executed
2399    %%%%%: 1403-block  1
2400branch  2 never executed
2401branch  3 never executed
2402    #####: 1404:			return strdup(name);
2403    %%%%%: 1404-block  0
2404call    0 never executed
2405unconditional  1 never executed
2406        -: 1405:	}
2407        -: 1406:
2408    #####: 1407:	return (char *)NULL;
2409    %%%%%: 1407-block  0
2410unconditional  0 never executed
2411        -: 1408:}
2412        -: 1409:
2413        -: 1410:/* Generate entries from the jump database (not using the j function)*/
2414        -: 1411:/*char *
2415        -: 1412:jump_gen(const char *text, int state)
2416        -: 1413:{
2417        -: 1414:	static int i;
2418        -: 1415:	static size_t len;
2419        -: 1416:	char *name;
2420        -: 1417:
2421        -: 1418:	if (!state) {
2422        -: 1419:		i = 0;
2423        -: 1420:		len = strlen(text);
2424        -: 1421:	}
2425        -: 1422:
2426        -: 1423:	while ((name = jump_db[i++].path) != NULL) {
2427        -: 1424:		if (case_sens_path_comp ? strncmp(name, text, len) == 0
2428        -: 1425:		: strncasecmp(name, text, len) == 0)
2429        -: 1426:			return strdup(name);
2430        -: 1427:	}
2431        -: 1428:
2432        -: 1429:	return (char *)NULL;
2433        -: 1430:} */
2434        -: 1431:
2435        -: 1432:char **
2436function my_rl_completion called 19 returned 100% blocks executed 49%
2437       19: 1433:my_rl_completion(const char *text, int start, int end)
2438        -: 1434:{
2439       19: 1435:	char **matches = (char **)NULL;
2440        -: 1436:
2441       19: 1437:	if (start == 0) { /* Only for the first word entered in the prompt */
2442       19: 1437-block  0
2443branch  0 taken 4 (fallthrough)
2444branch  1 taken 15
2445        -: 1438:		/* Commands completion */
2446        4: 1439:		if (end == 0) { /* If text is empty, do nothing */
2447        4: 1439-block  0
2448branch  0 taken 0 (fallthrough)
2449branch  1 taken 4
2450        -: 1440:			/* Prevent readline from attempting path completion if
2451        -: 1441:			* rl_completion matches returns NULL */
2452    #####: 1442:			rl_attempted_completion_over = 1;
2453    #####: 1443:			return (char **)NULL;
2454    %%%%%: 1443-block  0
2455unconditional  0 never executed
2456        -: 1444:		}
2457        -: 1445:
2458        -: 1446:		/* History cmd completion */
2459        4: 1447:		if (*text == '!')
2460        4: 1447-block  0
2461branch  0 taken 0 (fallthrough)
2462branch  1 taken 4
2463    #####: 1448:			matches = rl_completion_matches(text + 1, &hist_generator);
2464    %%%%%: 1448-block  0
2465call    0 never executed
2466unconditional  1 never executed
2467        -: 1449:
2468        -: 1450:		/* If autocd or auto-open, try to expand ELN's first */
2469       4*: 1451:		if (!matches && (autocd || auto_open)) {
2470        4: 1451-block  0
2471branch  0 taken 4 (fallthrough)
2472branch  1 taken 0
2473        4: 1451-block  1
2474branch  2 taken 0 (fallthrough)
2475branch  3 taken 4
2476    %%%%%: 1451-block  2
2477branch  4 never executed
2478branch  5 never executed
2479        4: 1452:			if (*text >= '1' && *text <= '9') {
2480        4: 1452-block  0
2481branch  0 taken 4 (fallthrough)
2482branch  1 taken 0
2483        4: 1452-block  1
2484branch  2 taken 0 (fallthrough)
2485branch  3 taken 4
2486    #####: 1453:				int num_text = atoi(text);
2487        -: 1454:
2488    #####: 1455:				if (is_number(text) && num_text > 0 && num_text <= (int)files)
2489    %%%%%: 1455-block  0
2490call    0 never executed
2491branch  1 never executed
2492branch  2 never executed
2493    %%%%%: 1455-block  1
2494branch  3 never executed
2495branch  4 never executed
2496    %%%%%: 1455-block  2
2497branch  5 never executed
2498branch  6 never executed
2499    #####: 1456:					matches = rl_completion_matches(text, &filenames_gen_eln);
2500    %%%%%: 1456-block  0
2501call    0 never executed
2502unconditional  1 never executed
2503        -: 1457:			}
2504        -: 1458:
2505        -: 1459:			/* Compĺete with files in CWD */
2506        4: 1460:			if (!matches && *text != '/')
2507        4: 1460-block  0
2508branch  0 taken 4 (fallthrough)
2509branch  1 taken 0
2510        4: 1460-block  1
2511branch  2 taken 4 (fallthrough)
2512branch  3 taken 0
2513        4: 1461:				matches = rl_completion_matches(text, &filenames_gen_text);
2514        4: 1461-block  0
2515call    0 returned 4
2516unconditional  1 taken 4
2517        -: 1462:
2518        -: 1463:			/* Complete with entries in the jump database */
2519        -: 1464:/*			if (autocd && !matches)
2520        -: 1465:				matches = rl_completion_matches(text, &jump_gen); */
2521        -: 1466:		}
2522        -: 1467:
2523        -: 1468:		/* Bookmarks completion */
2524       4*: 1469:		if (!matches && (autocd || auto_open) && expand_bookmarks)
2525        4: 1469-block  0
2526branch  0 taken 1 (fallthrough)
2527branch  1 taken 3
2528        1: 1469-block  1
2529branch  2 taken 0 (fallthrough)
2530branch  3 taken 1
2531    %%%%%: 1469-block  2
2532branch  4 never executed
2533branch  5 never executed
2534        1: 1469-block  3
2535branch  6 taken 0 (fallthrough)
2536branch  7 taken 1
2537    #####: 1470:			matches = rl_completion_matches(text, &bookmarks_generator);
2538    %%%%%: 1470-block  0
2539call    0 never executed
2540unconditional  1 never executed
2541        -: 1471:
2542        -: 1472:		/* If neither autocd nor auto-open, try to complete with
2543        -: 1473:		 * command names */
2544        4: 1474:		if (!matches)
2545        4: 1474-block  0
2546branch  0 taken 1 (fallthrough)
2547branch  1 taken 3
2548        1: 1475:			matches = rl_completion_matches(text, &bin_cmd_generator);
2549        1: 1475-block  0
2550call    0 returned 1
2551unconditional  1 taken 1
2552        -: 1476:	}
2553        -: 1477:
2554        -: 1478:	/* Second word or more */
2555        -: 1479:	else {
2556        -: 1480:		/* #### ELN AND JUMP ORDER EXPANSION ### */
2557        -: 1481:
2558        -: 1482:		/* Perform this check only if the first char of the string to be
2559        -: 1483:		 * completed is a number in order to prevent an unnecessary call
2560        -: 1484:		 * to atoi */
2561      15*: 1485:		if (*text >= '0' && *text <= '9') {
2562       15: 1485-block  0
2563branch  0 taken 3 (fallthrough)
2564branch  1 taken 12
2565        3: 1485-block  1
2566branch  2 taken 0 (fallthrough)
2567branch  3 taken 3
2568    %%%%%: 1485-block  2
2569unconditional  4 never executed
2570    #####: 1486:			int num_text = atoi(text);
2571        -: 1487:
2572        -: 1488:			/* Dirjump: jo command */
2573    #####: 1489:			if (*rl_line_buffer == 'j' && rl_line_buffer[1] == 'o'
2574    %%%%%: 1489-block  0
2575branch  0 never executed
2576branch  1 never executed
2577    %%%%%: 1489-block  1
2578branch  2 never executed
2579branch  3 never executed
2580    #####: 1490:			&& rl_line_buffer[2] == ' ') {
2581    %%%%%: 1490-block  0
2582branch  0 never executed
2583branch  1 never executed
2584    #####: 1491:				if (is_number(text) && num_text > 0 && num_text <= (int)jump_n) {
2585    %%%%%: 1491-block  0
2586call    0 never executed
2587branch  1 never executed
2588branch  2 never executed
2589    %%%%%: 1491-block  1
2590branch  3 never executed
2591branch  4 never executed
2592    %%%%%: 1491-block  2
2593branch  5 never executed
2594branch  6 never executed
2595    #####: 1492:					matches = rl_completion_matches(text,
2596    %%%%%: 1492-block  0
2597call    0 never executed
2598unconditional  1 never executed
2599        -: 1493:					    &jump_entries_generator);
2600        -: 1494:				}
2601        -: 1495:			}
2602        -: 1496:
2603        -: 1497:			/* Sort number expansion */
2604    #####: 1498:			else if (*rl_line_buffer == 's'
2605    %%%%%: 1498-block  0
2606branch  0 never executed
2607branch  1 never executed
2608    #####: 1499:			&& (strncmp(rl_line_buffer, "st ", 3) == 0
2609    %%%%%: 1499-block  0
2610branch  0 never executed
2611branch  1 never executed
2612    #####: 1500:			|| strncmp(rl_line_buffer, "sort ", 5) == 0)
2613    %%%%%: 1500-block  0
2614branch  0 never executed
2615branch  1 never executed
2616    #####: 1501:			&& is_number(text) && num_text >= 0 && num_text <= SORT_TYPES)
2617    %%%%%: 1501-block  0
2618call    0 never executed
2619branch  1 never executed
2620branch  2 never executed
2621    %%%%%: 1501-block  1
2622branch  3 never executed
2623branch  4 never executed
2624    %%%%%: 1501-block  2
2625branch  5 never executed
2626branch  6 never executed
2627    #####: 1502:				matches = rl_completion_matches(text, &sort_num_generator);
2628    %%%%%: 1502-block  0
2629call    0 never executed
2630unconditional  1 never executed
2631        -: 1503:
2632        -: 1504:			/* ELN expansion */
2633    #####: 1505:			else if (is_number(text) && num_text > 0 && num_text <= (int)files)
2634    %%%%%: 1505-block  0
2635call    0 never executed
2636branch  1 never executed
2637branch  2 never executed
2638    %%%%%: 1505-block  1
2639branch  3 never executed
2640branch  4 never executed
2641    %%%%%: 1505-block  2
2642branch  5 never executed
2643branch  6 never executed
2644    #####: 1506:				matches = rl_completion_matches(text, &filenames_gen_eln);
2645    %%%%%: 1506-block  0
2646call    0 never executed
2647unconditional  1 never executed
2648        -: 1507:		}
2649        -: 1508:
2650        -: 1509:		/* ### DIRJUMP COMPLETION ### */
2651        -: 1510:		/* j, jc, jp commands */
2652       15: 1511:		else if (*rl_line_buffer == 'j' && (rl_line_buffer[1] == ' '
2653       15: 1511-block  0
2654branch  0 taken 1 (fallthrough)
2655branch  1 taken 14
2656        1: 1511-block  1
2657branch  2 taken 0 (fallthrough)
2658branch  3 taken 1
2659    #####: 1512:		|| ((rl_line_buffer[1] == 'c' || rl_line_buffer[1] == 'p')
2660    %%%%%: 1512-block  0
2661branch  0 never executed
2662branch  1 never executed
2663    %%%%%: 1512-block  1
2664branch  2 never executed
2665branch  3 never executed
2666    #####: 1513:		&& rl_line_buffer[2] == ' ')
2667    %%%%%: 1513-block  0
2668branch  0 never executed
2669branch  1 never executed
2670    #####: 1514:		|| strncmp(rl_line_buffer, "jump ", 5) == 0))
2671    %%%%%: 1514-block  0
2672branch  0 never executed
2673branch  1 never executed
2674        1: 1515:			matches = rl_completion_matches(text, &jump_generator);
2675        1: 1515-block  0
2676call    0 returned 1
2677unconditional  1 taken 1
2678        -: 1516:
2679        -: 1517:		/* ### BOOKMARKS COMPLETION ### */
2680        -: 1518:
2681       14: 1519:		else if (*rl_line_buffer == 'b' && (rl_line_buffer[1] == 'm'
2682       14: 1519-block  0
2683branch  0 taken 3 (fallthrough)
2684branch  1 taken 11
2685        3: 1519-block  1
2686branch  2 taken 0 (fallthrough)
2687branch  3 taken 3
2688    #####: 1520:		|| rl_line_buffer[1] == 'o')
2689    %%%%%: 1520-block  0
2690branch  0 never executed
2691branch  1 never executed
2692        3: 1521:		&& (strncmp(rl_line_buffer, "bm ", 3) == 0
2693        3: 1521-block  0
2694branch  0 taken 0 (fallthrough)
2695branch  1 taken 3
2696    #####: 1522:		|| strncmp(rl_line_buffer, "bookmarks ", 10) == 0)) {
2697    %%%%%: 1522-block  0
2698branch  0 never executed
2699branch  1 never executed
2700        -: 1523:#ifndef _NO_SUGGESTIONS
2701        3: 1524:			if (suggestion.type != FILE_SUG)
2702        3: 1524-block  0
2703branch  0 taken 3 (fallthrough)
2704branch  1 taken 0
2705        3: 1525:				rl_attempted_completion_over = 1;
2706        3: 1525-block  0
2707unconditional  0 taken 3
2708        -: 1526:#endif
2709        3: 1527:			matches = rl_completion_matches(text, &bookmarks_generator);
2710        3: 1527-block  0
2711call    0 returned 3
2712unconditional  1 taken 3
2713        -: 1528:		}
2714        -: 1529:
2715        -: 1530:		/* ### COLOR SCHEMES COMPLETION ### */
2716       11: 1531:		else if (*rl_line_buffer == 'c' && ((rl_line_buffer[1] == 's'
2717       11: 1531-block  0
2718branch  0 taken 1 (fallthrough)
2719branch  1 taken 10
2720        1: 1531-block  1
2721branch  2 taken 1 (fallthrough)
2722branch  3 taken 0
2723        1: 1532:		&& rl_line_buffer[2] == ' ')
2724        1: 1532-block  0
2725branch  0 taken 0 (fallthrough)
2726branch  1 taken 1
2727    #####: 1533:		|| strncmp(rl_line_buffer, "colorschemes ", 13) == 0)) {
2728    %%%%%: 1533-block  0
2729branch  0 never executed
2730branch  1 never executed
2731        1: 1534:			matches = rl_completion_matches(text,
2732        1: 1534-block  0
2733call    0 returned 1
2734unconditional  1 taken 1
2735        -: 1535:			    &cschemes_generator);
2736        -: 1536:		}
2737        -: 1537:
2738        -: 1538:		/* ### PROFILES COMPLETION ### */
2739        -: 1539:
2740       10: 1540:		else if (*rl_line_buffer == 'p' && (rl_line_buffer[1] == 'r'
2741       10: 1540-block  0
2742branch  0 taken 4 (fallthrough)
2743branch  1 taken 6
2744        4: 1540-block  1
2745branch  2 taken 4 (fallthrough)
2746branch  3 taken 0
2747        4: 1541:		|| rl_line_buffer[1] == 'f')
2748        4: 1541-block  0
2749branch  0 taken 4 (fallthrough)
2750branch  1 taken 0
2751        4: 1542:		&& (strncmp(rl_line_buffer, "pf set ", 7) == 0
2752        4: 1542-block  0
2753branch  0 taken 2 (fallthrough)
2754branch  1 taken 2
2755        2: 1543:		|| strncmp(rl_line_buffer, "profile set ", 12) == 0
2756        2: 1543-block  0
2757branch  0 taken 2 (fallthrough)
2758branch  1 taken 0
2759        2: 1544:		|| strncmp(rl_line_buffer, "pf del ", 7) == 0
2760        2: 1544-block  0
2761branch  0 taken 2 (fallthrough)
2762branch  1 taken 0
2763        2: 1545:		|| strncmp(rl_line_buffer, "profile del ", 12) == 0)) {
2764        2: 1545-block  0
2765branch  0 taken 0 (fallthrough)
2766branch  1 taken 2
2767        -: 1546:#ifndef _NO_SUGGESTIONS
2768        2: 1547:			if (suggestion.type != FILE_SUG)
2769        2: 1547-block  0
2770branch  0 taken 2 (fallthrough)
2771branch  1 taken 0
2772        2: 1548:				rl_attempted_completion_over = 1;
2773        2: 1548-block  0
2774unconditional  0 taken 2
2775        -: 1549:#endif /* _NO_SUGGESTIONS */
2776        2: 1550:			matches = rl_completion_matches(text, &profiles_generator);
2777        2: 1550-block  0
2778call    0 returned 2
2779unconditional  1 taken 2
2780        -: 1551:		}
2781        -: 1552:
2782        8: 1553:		else if (expand_bookmarks) {
2783        8: 1553-block  0
2784branch  0 taken 0 (fallthrough)
2785branch  1 taken 8
2786    #####: 1554:			matches = rl_completion_matches(text, &bookmarks_generator);
2787    %%%%%: 1554-block  0
2788call    0 never executed
2789unconditional  1 never executed
2790        -: 1555:		}
2791        -: 1556:
2792        8: 1557:		else if (*rl_line_buffer == 's'
2793        8: 1557-block  0
2794branch  0 taken 0 (fallthrough)
2795branch  1 taken 8
2796    #####: 1558:		&& (strncmp(rl_line_buffer, "st ", 3) == 0
2797    %%%%%: 1558-block  0
2798branch  0 never executed
2799branch  1 never executed
2800    #####: 1559:		|| strncmp(rl_line_buffer, "sort ", 5) == 0))
2801    %%%%%: 1559-block  0
2802branch  0 never executed
2803branch  1 never executed
2804    #####: 1560:			matches = rl_completion_matches(text, &sort_name_generator);
2805    %%%%%: 1560-block  0
2806call    0 never executed
2807unconditional  1 never executed
2808        -: 1561:
2809        8: 1562:		else if (*rl_line_buffer == 'n'
2810        8: 1562-block  0
2811branch  0 taken 0 (fallthrough)
2812branch  1 taken 8
2813    #####: 1563:		&& strncmp(rl_line_buffer, "net ", 4) == 0)
2814    %%%%%: 1563-block  0
2815branch  0 never executed
2816branch  1 never executed
2817    #####: 1564:			matches = rl_completion_matches(text, &nets_generator);
2818    %%%%%: 1564-block  0
2819call    0 never executed
2820unconditional  1 never executed
2821        -: 1565:	}
2822        -: 1566:
2823        -: 1567:	/* ### PATH COMPLETION ### */
2824        -: 1568:
2825        -: 1569:	/* If none of the above, readline will attempt
2826        -: 1570:	 * path completion instead via my custom my_rl_path_completion() */
2827       19: 1571:	return matches;
2828       19: 1571-block  0
2829unconditional  0 taken 19
2830        -: 1572:}
2831        -: 1573:
2832        -: 1574:int
2833function initialize_readline called 4 returned 100% blocks executed 91%
2834        4: 1575:initialize_readline(void)
2835        -: 1576:{
2836        -: 1577:	/* #### INITIALIZE READLINE (what a hard beast to tackle!!) #### */
2837        -: 1578:
2838        -: 1579:	/* Set the name of the program using readline. Mostly used for
2839        -: 1580:	 * conditional constructs in the inputrc file */
2840        4: 1581:	rl_readline_name = argv_bk[0];
2841        -: 1582:
2842        -: 1583:/*	add_func_to_rl(); */
2843        -: 1584:
2844        -: 1585:	/* Load readline initialization file. Check order:
2845        -: 1586:	 * INPUTRC env var
2846        -: 1587:	 * ~/.config/clifm/readline.cfm
2847        -: 1588:	 * ~/.inputrc
2848        -: 1589:	 * /etc/inputrc */
2849        4: 1590:	char *p = getenv("INPUTRC");
2850        4: 1590-block  0
2851call    0 returned 4
2852        4: 1591:	if (p) {
2853branch  0 taken 0 (fallthrough)
2854branch  1 taken 4
2855    #####: 1592:		rl_read_init_file(p);
2856    %%%%%: 1592-block  0
2857call    0 never executed
2858unconditional  1 never executed
2859        4: 1593:	} else if (config_dir_gral) {
2860        4: 1593-block  0
2861branch  0 taken 4 (fallthrough)
2862branch  1 taken 0
2863        4: 1594:		char *rl_file = (char *)xnmalloc(strlen(config_dir_gral) + 14,
2864        4: 1594-block  0
2865call    0 returned 4
2866        -: 1595:							sizeof(char));
2867        4: 1596:		sprintf(rl_file, "%s/readline.cfm", config_dir_gral);
2868        4: 1597:		rl_read_init_file(rl_file);
2869call    0 returned 4
2870        4: 1598:		free(rl_file);
2871unconditional  0 taken 4
2872        -: 1599:	}
2873        -: 1600:
2874        -: 1601:	/* Enable tab auto-completion for commands (in PATH) in case of
2875        -: 1602:	  * first entered string (if autocd and/or auto-open are enabled, check
2876        -: 1603:	  * for paths as well). The second and later entered strings will
2877        -: 1604:	  * be autocompleted with paths instead, just like in Bash, or with
2878        -: 1605:	  * listed file names, in case of ELN's. I use a custom completion
2879        -: 1606:	  * function to add command and ELN completion, since readline's
2880        -: 1607:	  * internal completer only performs path completion */
2881        -: 1608:
2882        -: 1609:	/* Define a function for path completion.
2883        -: 1610:	 * NULL means to use filename_entry_function (), the default
2884        -: 1611:	 * filename completer. */
2885        4: 1612:	rl_completion_entry_function = my_rl_path_completion;
2886        -: 1613:
2887        -: 1614:	/* Pointer to alternative function to create matches.
2888        -: 1615:	 * Function is called with TEXT, START, and END.
2889        -: 1616:	 * START and END are indices in RL_LINE_BUFFER saying what the
2890        -: 1617:	 * boundaries of TEXT are.
2891        -: 1618:	 * If this function exists and returns NULL then call the value of
2892        -: 1619:	 * rl_completion_entry_function to try to match, otherwise use the
2893        -: 1620:	 * array of strings returned. */
2894        4: 1621:	rl_attempted_completion_function = my_rl_completion;
2895        4: 1622:	rl_ignore_completion_duplicates = 1;
2896        -: 1623:
2897        -: 1624:	/* I'm using here a custom quoting function. If not specified,
2898        -: 1625:	 * readline uses the default internal function. */
2899        4: 1626:	rl_filename_quoting_function = my_rl_quote;
2900        -: 1627:
2901        -: 1628:	/* Tell readline what char to use for quoting. This is only the
2902        -: 1629:	 * readline internal quoting function, and for custom ones, like the
2903        -: 1630:	 * one I use above. However, custom quoting functions, though they
2904        -: 1631:	 * need to define their own quoting chars, won't be called at all
2905        -: 1632:	 * if this variable isn't set. */
2906        4: 1633:	rl_completer_quote_characters = "\"'";
2907        4: 1634:	rl_completer_word_break_characters = " ";
2908        -: 1635:
2909        -: 1636:	/* Whenever readline finds any of the following chars, it will call
2910        -: 1637:	 * the quoting function */
2911        4: 1638:	rl_filename_quote_characters = " \t\n\"\\'`@$><=,;|&{[()]}?!*^";
2912        -: 1639:	/* According to readline documentation, the following string is
2913        -: 1640:	 * the default and the one used by Bash: " \t\n\"\\'`@$><=;|&{(" */
2914        -: 1641:
2915        -: 1642:	/* Executed immediately before calling the completer function, it
2916        -: 1643:	 * tells readline if a space char, which is a word break character
2917        -: 1644:	 * (see the above rl_completer_word_break_characters variable) is
2918        -: 1645:	 * quoted or not. If it is, readline then passes the whole string
2919        -: 1646:	 * to the completer function (ex: "user\ file"), and if not, only
2920        -: 1647:	 * wathever it found after the space char (ex: "file")
2921        -: 1648:	 * Thanks to George Brocklehurst for pointing out this function:
2922        -: 1649:	 * https://thoughtbot.com/blog/tab-completion-in-gnu-readline*/
2923        4: 1650:	rl_char_is_quoted_p = quote_detector;
2924        -: 1651:
2925        -: 1652:	/* Define a function to handle suggestions and syntax highlighting */
2926        4: 1653:	rl_getc_function = my_rl_getc;
2927        -: 1654:
2928        -: 1655:	/* This function is executed inmediately before path completion. So,
2929        -: 1656:	 * if the string to be completed is, for instance, "user\ file" (see
2930        -: 1657:	 * the above comment), this function should return the dequoted
2931        -: 1658:	 * string so it won't conflict with system file names: you want
2932        -: 1659:	 * "user file", because "user\ file" does not exist, and, in this
2933        -: 1660:	 * latter case, readline won't find any matches */
2934        4: 1661:	rl_filename_dequoting_function = dequote_str;
2935        -: 1662:
2936        -: 1663:	/* Initialize the keyboard bindings function */
2937        4: 1664:	readline_kbinds();
2938        4: 1664-block  0
2939call    0 returned 4
2940        -: 1665:
2941        -: 1666:	/* Copy the list of quote chars to a global variable to be used
2942        -: 1667:	 * later by some of the program functions like split_str(),
2943        -: 1668:	 * my_rl_quote(), is_quote_char(), and my_rl_dequote() */
2944        4: 1669:	qc = savestring(rl_filename_quote_characters,
2945call    0 returned 4
2946        -: 1670:	    strlen(rl_filename_quote_characters));
2947        -: 1671:
2948        -: 1672:#if !defined(_NO_SUGGESTIONS) && defined(__FreeBSD__)
2949        -: 1673:	if (!(flags & GUI) && getenv("CLIFM_FREEBSD_CONSOLE_SC"))
2950        -: 1674:		freebsd_sc_console = 1;
2951        -: 1675:#endif
2952        -: 1676:
2953        4: 1677:	return EXIT_SUCCESS;
2954unconditional  0 taken 4
2955        -: 1678:}
2956