1/* $NetBSD: tc1.c,v 1.5 2010/04/18 21:17:47 christos Exp $ */ 2 3/*- 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Christos Zoulas of Cornell University. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#include "config.h" 36#ifndef lint 37__COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\ 38 The Regents of the University of California. All rights reserved.\n"); 39#endif /* not lint */ 40 41#if !defined(lint) && !defined(SCCSID) 42#if 0 43static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93"; 44#else 45__RCSID("$NetBSD: tc1.c,v 1.5 2010/04/18 21:17:47 christos Exp $"); 46#endif 47#endif /* not lint && not SCCSID */ 48 49/* from src/sys/sys/cdefs.h */ 50#ifndef __UNCONST 51# define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) 52#endif 53 54/* 55 * test.c: A little test program 56 */ 57#include <stdio.h> 58#include <string.h> 59#include <signal.h> 60#include <sys/wait.h> 61#include <ctype.h> 62#include <stdlib.h> 63#include <unistd.h> 64#include <dirent.h> 65#include <locale.h> 66 67#include "histedit.h" 68 69static int continuation = 0; 70volatile sig_atomic_t gotsig = 0; 71 72static unsigned char complete(EditLine *, int); 73 int main(int, char **); 74static char *prompt(EditLine *); 75static void sig(int); 76 77static char * 78prompt(EditLine *el __attribute__((__unused__))) 79{ 80 static char a[] = "\1\033[7m\1Edit$\1\033[0m\1 "; 81 static char b[] = "Edit> "; 82 83 return (continuation ? b : a); 84} 85 86static void 87sig(int i) 88{ 89 gotsig = i; 90} 91 92static unsigned char 93complete(EditLine *el, int ch __attribute__((__unused__))) 94{ 95 DIR *dd = opendir("."); 96 struct dirent *dp; 97 const char* ptr; 98 const LineInfo *lf = el_line(el); 99 size_t len; 100 int res = CC_ERROR; 101 102 /* 103 * Find the last word 104 */ 105 for (ptr = lf->cursor - 1; 106 !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--) 107 continue; 108 len = lf->cursor - ++ptr; 109 110 for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { 111 if (len > strlen(dp->d_name)) 112 continue; 113 if (strncmp(dp->d_name, ptr, len) == 0) { 114 if (el_insertstr(el, &dp->d_name[len]) == -1) 115 res = CC_ERROR; 116 else 117 res = CC_REFRESH; 118 break; 119 } 120 } 121 122 closedir(dd); 123 return res; 124} 125 126int 127main(int argc __attribute__((__unused__)), char *argv[]) 128{ 129 EditLine *el = NULL; 130 int num; 131 const char *buf; 132 Tokenizer *tok; 133#if 0 134 int lastevent = 0; 135#endif 136 int ncontinuation; 137 History *hist; 138 HistEvent ev; 139 140 (void) setlocale(LC_CTYPE, ""); 141 (void) signal(SIGINT, sig); 142 (void) signal(SIGQUIT, sig); 143 (void) signal(SIGHUP, sig); 144 (void) signal(SIGTERM, sig); 145 146 hist = history_init(); /* Init the builtin history */ 147 /* Remember 100 events */ 148 history(hist, &ev, H_SETSIZE, 100); 149 150 tok = tok_init(NULL); /* Initialize the tokenizer */ 151 152 /* Initialize editline */ 153 el = el_init(*argv, stdin, stdout, stderr); 154 155 el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */ 156 el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */ 157 el_set(el, EL_PROMPT_ESC, prompt, '\1');/* Set the prompt function */ 158 159 /* Tell editline to use this history interface */ 160 el_set(el, EL_HIST, history, hist); 161 162 /* Add a user-defined function */ 163 el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete); 164 165 /* Bind tab to it */ 166 el_set(el, EL_BIND, "^I", "ed-complete", NULL); 167 168 /* 169 * Bind j, k in vi command mode to previous and next line, instead 170 * of previous and next history. 171 */ 172 el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL); 173 el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL); 174 175 /* 176 * Source the user's defaults file. 177 */ 178 el_source(el, NULL); 179 180 while ((buf = el_gets(el, &num)) != NULL && num != 0) { 181 int ac, cc, co; 182#ifdef DEBUG 183 int i; 184#endif 185 const char **av; 186 const LineInfo *li; 187 li = el_line(el); 188#ifdef DEBUG 189 (void) fprintf(stderr, "==> got %d %s", num, buf); 190 (void) fprintf(stderr, " > li `%.*s_%.*s'\n", 191 (li->cursor - li->buffer), li->buffer, 192 (li->lastchar - 1 - li->cursor), 193 (li->cursor >= li->lastchar) ? "" : li->cursor); 194 195#endif 196 if (gotsig) { 197 (void) fprintf(stderr, "Got signal %d.\n", gotsig); 198 gotsig = 0; 199 el_reset(el); 200 } 201 202 if (!continuation && num == 1) 203 continue; 204 205 ac = cc = co = 0; 206 ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co); 207 if (ncontinuation < 0) { 208 (void) fprintf(stderr, "Internal error\n"); 209 continuation = 0; 210 continue; 211 } 212#ifdef DEBUG 213 (void) fprintf(stderr, " > nc %d ac %d cc %d co %d\n", 214 ncontinuation, ac, cc, co); 215#endif 216#if 0 217 if (continuation) { 218 /* 219 * Append to the right event in case the user 220 * moved around in history. 221 */ 222 if (history(hist, &ev, H_SET, lastevent) == -1) 223 err(1, "%d: %s", lastevent, ev.str); 224 history(hist, &ev, H_ADD , buf); 225 } else { 226 history(hist, &ev, H_ENTER, buf); 227 lastevent = ev.num; 228 } 229#else 230 /* Simpler */ 231 history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf); 232#endif 233 234 continuation = ncontinuation; 235 ncontinuation = 0; 236 if (continuation) 237 continue; 238#ifdef DEBUG 239 for (i = 0; i < ac; i++) { 240 (void) fprintf(stderr, " > arg# %2d ", i); 241 if (i != cc) 242 (void) fprintf(stderr, "`%s'\n", av[i]); 243 else 244 (void) fprintf(stderr, "`%.*s_%s'\n", 245 co, av[i], av[i] + co); 246 } 247#endif 248 249 if (strcmp(av[0], "history") == 0) { 250 int rv; 251 252 switch (ac) { 253 case 1: 254 for (rv = history(hist, &ev, H_LAST); rv != -1; 255 rv = history(hist, &ev, H_PREV)) 256 (void) fprintf(stdout, "%4d %s", 257 ev.num, ev.str); 258 break; 259 260 case 2: 261 if (strcmp(av[1], "clear") == 0) 262 history(hist, &ev, H_CLEAR); 263 else 264 goto badhist; 265 break; 266 267 case 3: 268 if (strcmp(av[1], "load") == 0) 269 history(hist, &ev, H_LOAD, av[2]); 270 else if (strcmp(av[1], "save") == 0) 271 history(hist, &ev, H_SAVE, av[2]); 272 break; 273 274 badhist: 275 default: 276 (void) fprintf(stderr, 277 "Bad history arguments\n"); 278 break; 279 } 280 } else if (el_parse(el, ac, av) == -1) { 281 switch (fork()) { 282 case 0: 283 execvp(av[0], (char *const *)__UNCONST(av)); 284 perror(av[0]); 285 _exit(1); 286 /*NOTREACHED*/ 287 break; 288 289 case -1: 290 perror("fork"); 291 break; 292 293 default: 294 if (wait(&num) == -1) 295 perror("wait"); 296 (void) fprintf(stderr, "Exit %x\n", num); 297 break; 298 } 299 } 300 301 tok_reset(tok); 302 } 303 304 el_end(el); 305 tok_end(tok); 306 history_end(hist); 307 308 return (0); 309} 310