/* If path looks like: A/B/C/D/whatever, it returns A/B/C/D as a malloced * string. */ char *SLpath_dirname (SLFUTURE_CONST char *file) { SLCONST char *b; if (file == NULL) return NULL; b = file + strlen (file); while (b != file) { b--; if (IS_PATH_SEP(*b)) { #ifdef VMS b++; /* make sure final ] is included */ #else if (b == file) b++; #endif break; } #ifdef DRIVE_SPECIFIER if (*b == DRIVE_SPECIFIER) { b++; break; } #endif } if (b == file) return SLmake_string (THIS_DIR_STRING); return SLmake_nstring (file, (unsigned int) (b - file)); }
static int parse_range (SLFUTURE_CONST char **sp, SLFUTURE_CONST char *smax, SLFUTURE_CONST char **fp, char **str) { SLFUTURE_CONST char *s, *s0; char *range; SLFUTURE_CONST char *f; unsigned char map[256]; unsigned char reverse; /* How can one represent a range with just '^'? The naive answer is * is [^]. However, this may be interpreted as meaning any character * but ']' and others. Let's assume that the user will not use a range * to match '^'. */ f = *fp; /* f is a pointer to (one char after) [...]. */ if (*f == '^') { f++; reverse = 1; } else reverse = 0; s0 = f; if (*f == ']') f++; while (1) { char ch = *f; if (ch == 0) { _pSLang_verror (SL_INVALID_PARM, "Unexpected end of range in format"); return -1; } if (ch == ']') break; f++; } if (NULL == (range = SLmake_nstring (s0, (unsigned int) (f - s0)))) return -1; *fp = f + 1; /* skip ] */ SLmake_lut (map, (unsigned char *) range, reverse); SLfree (range); s0 = s = *sp; while ((s < smax) && map [(unsigned char) *s]) s++; if (NULL == (*str = SLang_create_nslstring (s0, (unsigned int) (s - s0)))) return -1; *sp = s; return 1; }
/* This is used if the key is not UTF-8, or it is but the search is case-sensitive */ static SLsearch_Type *bm_open_search (SLuchar_Type *key, int flags) { SLsearch_Type *st; size_t keylen; keylen = strlen ((char *)key); if (NULL == (st = (SLsearch_Type *)SLcalloc (1, sizeof (SLsearch_Type)))) return NULL; st->free_fun = bm_free; /* If the search is case-insensitive, then it must either be all ascii, or * it is not unicode. In either case, the UPPER_CASE and LOWER_CASE macros * should be ok to use. */ if (flags & SLSEARCH_CASELESS) { char *keyup = SLmake_nstring ((char *)key, keylen); if (keyup != NULL) { unsigned char *k = (unsigned char *)keyup; while (*k != 0) { *k = UPPER_CASE(*k); k++; } st->s.bm.key = (SLuchar_Type *)SLang_create_slstring (keyup); SLfree (keyup); } else st->s.bm.key = NULL; } else st->s.bm.key = (SLuchar_Type*) SLang_create_slstring ((char *)key); if (st->s.bm.key == NULL) { SLsearch_delete (st); return NULL; } st->s.bm.key_len = keylen; st->flags = flags; st->search_fun = bm_search; init_skip_table (st->s.bm.key, st->s.bm.key_len, st->s.bm.fskip_table, 1, flags); init_skip_table (st->s.bm.key, st->s.bm.key_len, st->s.bm.bskip_table, -1, flags); return st; }
static void path_extname (char *path) { #ifdef VMS char *p; #endif path = SLpath_extname (path); #ifndef VMS SLang_push_string (path); #else p = strchr (path, ';'); if (p == NULL) (void)SLang_push_string (p); else (void)SLang_push_malloced_string (SLmake_nstring (path, (unsigned int)(p - path))); #endif }
SLsearch_Type *SLsearch_new (SLuchar_Type *key, int flags) { SLsearch_Type *st, *bf_st; SLuchar_Type *key_upper, *key_lower, *non_ascii; size_t len, upper_len, lower_len; if (Case_Tables_Ok == 0) SLang_init_case_tables (); if (key == NULL) return NULL; if ((0 == (flags & SLSEARCH_CASELESS)) || (0 == (flags & SLSEARCH_UTF8))) return bm_open_search (key, flags); /* Otherwise the key is UTF-8 and the search is case-insensitive */ len = strlen ((char *)key); key_upper = SLutf8_strup (key, key + len); if (key_upper == NULL) return NULL; upper_len = strlen ((char *)key_upper); if (is_bm_ok (key_upper, upper_len, &non_ascii)) { st = bm_open_search (key_upper, flags); SLang_free_slstring ((char *)key_upper); return st; } /* Tricky part */ if (NULL == (key_lower = SLutf8_strlo (key, key + len))) { SLang_free_slstring ((char *)key_upper); return NULL; } lower_len = strlen ((char *)key_lower); /* Try a case-less search */ if ((lower_len == upper_len) && (0 == strcmp ((char *)key_upper, (char *)key_lower))) { flags &= ~SLSEARCH_CASELESS; st = bm_open_search (key_upper, flags); SLang_free_slstring ((char *)key_upper); SLang_free_slstring ((char *)key_lower); return st; } /* Now Perform a brute-force search. */ /* If the first few characters of the search string are ascii, then * use BM for that portion */ bf_st = NULL; if (non_ascii - key_upper >= 3) { SLuchar_Type *key1 = (SLuchar_Type *) SLmake_nstring ((char *)key_upper, non_ascii - key_upper); /* ok to propagate NULL below */ bf_st = SLsearch_new (key1, flags); SLfree ((char *)key1); if (bf_st == NULL) { SLang_free_slstring ((char *)key_upper); SLang_free_slstring ((char *)key_lower); return NULL; } key1 = (SLuchar_Type *) SLang_create_slstring ((char *)non_ascii); non_ascii = key_lower + (non_ascii - key_upper); SLang_free_slstring ((char *)key_upper); key_upper = key1; key1 = (SLuchar_Type *)SLang_create_slstring ((char *)non_ascii); SLang_free_slstring ((char *)key_lower); key_lower = key1; if ((key_lower == NULL) || (key_upper == NULL)) { SLang_free_slstring ((char *)key_upper); SLang_free_slstring ((char *)key_lower); SLsearch_delete (bf_st); return NULL; } upper_len = strlen ((char *)key_upper); lower_len = strlen ((char *)key_lower); } st = (SLsearch_Type *)SLcalloc (sizeof (SLsearch_Type), 1); if (st == NULL) goto return_error; st->free_fun = bf_free; st->flags = flags; st->search_fun = bf_search; st->s.bf.st = bf_st; bf_st = NULL; if (NULL == (st->s.bf.lower_chars = make_string_array (key_lower, lower_len, &st->s.bf.nlower_chars))) goto return_error; if (NULL == (st->s.bf.upper_chars = make_string_array (key_upper, upper_len, &st->s.bf.nupper_chars))) goto return_error; SLang_free_slstring ((char *)key_upper); SLang_free_slstring ((char *)key_lower); return st; return_error: SLsearch_delete (st); SLsearch_delete (bf_st); SLang_free_slstring ((char *)key_upper); SLang_free_slstring ((char *)key_lower); return NULL; }
int SLcmd_execute_string (char *str, SLcmd_Cmd_Table_Type *table) { char *s, *arg_type, *last_str, *cmd_name; SLcmd_Cmd_Type *cmd; char *buf; int token_present; int i; int status; unsigned int len; int argc; unsigned int space; table->argc = 0; table->string_args = NULL; table->int_args = NULL; table->double_args = NULL; table->arg_type = NULL; buf = SLmake_string (str); if (buf == NULL) return -1; status = extract_token (&str, buf); if (status <= 0) { SLfree (buf); return status; } if (((len = strlen (buf)) >= 32) || (NULL == (cmd = SLcmd_find_command (buf, table->table)))) { SLang_verror (SL_UNDEFINED_NAME,"%s: invalid command", buf); SLfree (buf); return -1; } if (NULL == (cmd_name = SLmake_string (buf))) { SLfree (buf); return -1; } space = 0; argc = 0; if (-1 == allocate_arg_space (table, argc, &space)) { SLfree (buf); return -1; } table->arg_type[argc] = SLANG_STRING_TYPE; table->string_args[argc++] = cmd_name; arg_type = cmd->arg_type; status = -1; while (*arg_type) { int guess_type = 0; last_str = str; if (-1 == allocate_arg_space (table, argc, &space)) goto error; if (-1 == (token_present = extract_token (&str, buf))) goto error; table->string_args[argc] = NULL; if (token_present) { char *b = buf; len = strlen (b); if ((*b == '"') && (len > 1)) { b++; len -= 2; b[len] = 0; guess_type = SLANG_STRING_TYPE; SLexpand_escaped_string (buf, b, b + len); len = strlen (buf); } else if ((*b == '\'') && (len > 1)) { char ch; b++; len -= 2; b[len] = 0; guess_type = SLANG_INT_TYPE; ch = *b; if (ch == '\\') (void) _SLexpand_escaped_char (b, &ch); sprintf (buf, "%d", (unsigned char) ch); len = strlen (buf); } else guess_type = SLang_guess_type (buf); } switch (*arg_type++) { /* variable argument number */ case 'v': if (token_present == 0) break; case 'V': if (token_present == 0) { SLang_verror (SL_INVALID_PARM, "%s: Expecting argument", cmd_name); goto error; } while (*last_str == ' ') last_str++; len = strlen (last_str); str = last_str + len; s = SLmake_nstring (last_str, len); if (s == NULL) goto error; table->arg_type[argc] = SLANG_STRING_TYPE; table->string_args[argc++] = s; break; case 's': if (token_present == 0) break; case 'S': if (token_present == 0) { SLang_verror (SL_TYPE_MISMATCH, "%s: Expecting string argument", cmd_name); goto error; } s = SLmake_nstring (buf, len); if (s == NULL) goto error; table->arg_type[argc] = SLANG_STRING_TYPE; table->string_args[argc++] = s; break; /* integer argument */ case 'i': if (token_present == 0) break; case 'I': if ((token_present == 0) || (SLANG_INT_TYPE != guess_type)) { SLang_verror (SL_TYPE_MISMATCH, "%s: Expecting integer argument", cmd_name); goto error; } table->arg_type[argc] = SLANG_INT_TYPE; table->int_args[argc++] = SLatoi((unsigned char *) buf); break; /* floating point arg */ #if SLANG_HAS_FLOAT case 'f': if (token_present == 0) break; case 'F': if ((token_present == 0) || (SLANG_STRING_TYPE == guess_type)) { SLang_verror (SL_TYPE_MISMATCH, "%s: Expecting double argument", cmd_name); goto error; } table->arg_type[argc] = SLANG_DOUBLE_TYPE; table->double_args[argc++] = atof(buf); break; #endif /* Generic type */ case 'g': if (token_present == 0) break; case 'G': if (token_present == 0) { SLang_verror (SL_TYPE_MISMATCH, "%s: Expecting argument", cmd_name); goto error; } switch (guess_type) { case SLANG_INT_TYPE: table->arg_type[argc] = SLANG_INT_TYPE; table->int_args[argc++] = SLatoi((unsigned char *) buf); break; case SLANG_STRING_TYPE: s = SLmake_nstring (buf, len); if (s == NULL) goto error; table->arg_type[argc] = SLANG_STRING_TYPE; table->string_args[argc++] = s; break; #if SLANG_HAS_FLOAT case SLANG_DOUBLE_TYPE: table->arg_type[argc] = SLANG_DOUBLE_TYPE; table->double_args[argc++] = atof(buf); #endif } break; } } /* call function */ status = (*cmd->cmdfun)(argc, table); error: if (table->string_args != NULL) for (i = 0; i < argc; i++) { if (NULL != table->string_args[i]) { SLfree (table->string_args[i]); table->string_args[i] = NULL; } } SLfree ((char *)table->string_args); table->string_args = NULL; SLfree ((char *)table->double_args); table->double_args = NULL; SLfree ((char *)table->int_args); table->int_args = NULL; SLfree ((char *)table->arg_type); table->arg_type = NULL; SLfree (buf); return status; }
/* If path looks like: A/B/C/D/whatever, it returns A/B/C/D as a malloced * string. */ char *SLpath_dirname (SLFUTURE_CONST char *drivefile) { SLCONST char *b; const char *file; char *dir, *drivedir; size_t len; if (drivefile == NULL) return NULL; file = skip_drive (drivefile); b = file + strlen (file); while (b != file) { b--; if (0 == IS_PATH_SEP(*b)) continue; #ifdef VMS b++; /* make sure final ] is included */ #else /* collapse multiple slashes */ while ((b != file) && IS_PATH_SEP(*(b-1))) b--; if (b == file) b++; #endif break; } /* now b should point to the character after the slash: * file="zzz/xxxx" * b------^ */ if (b == file) { /* pathological cases -- what is the parent? For simplicity * simply return the current directory. */ len = file - drivefile; if (NULL == (dir = SLmalloc (len + 1 + strlen(THIS_DIR_STRING)))) return NULL; strncpy (dir, drivefile, len); strcpy (dir + len, THIS_DIR_STRING); return dir; } if (NULL == (drivedir = SLmake_nstring (drivefile, b - drivefile))) return NULL; dir = drivedir + (file - drivefile); len = b - file; /* len is from start of file on drive */ #ifndef VMS /* handle special cases * /foo/. --> /foo * /. --> / * /foo/.. --> / * C:/. */ while ((len > 1) && (dir[len-1] == '.')) { if (IS_PATH_SEP(dir[len-2])) { len--; /* lose "." */ while ((len > 1) && IS_PATH_SEP(dir[len-1])) len--; /* lose "/" */ dir[len] = 0; continue; } if ((len > 2) && (dir[len-2] == '.') && IS_PATH_SEP(dir[len-3])) { len -= 2; /* lose ".." */ if (len > 1) { len--; /* lose "/" */ dir[len] = 0; b = SLpath_basename (dir); /* will not fail: zzz/xxx --> zzz/x */ len = b - dir; while ((len > 1) && IS_PATH_SEP(dir[len-1])) len--; } dir[len] = 0; continue; } break; } #endif /* not VMS */ return drivedir; }
char *SLrline_get_line (SLrline_Type *rli) { if (rli == NULL) return NULL; return SLmake_nstring ((char *)rli->buf, rli->len); }
char *SLrline_read_line (SLrline_Type *rli, SLFUTURE_CONST char *prompt, unsigned int *lenp) { unsigned char *p, *pmax; SLang_Key_Type *key; int last_input_char; unsigned int dummy_len_buf; if (lenp == NULL) lenp = &dummy_len_buf; *lenp = 0; if (rli == NULL) return NULL; if (rli->state == RLI_LINE_IN_PROGRESS) { *lenp = 0; return NULL; } if (prompt == NULL) prompt = ""; if ((rli->prompt == NULL) || strcmp (rli->prompt, prompt)) { if (NULL == (prompt = SLmake_string (prompt))) return NULL; SLfree ((char *)rli->prompt); rli->prompt = prompt; } SLang_Rline_Quit = 0; p = rli->old_upd; pmax = p + rli->edit_width; while (p < pmax) *p++ = ' '; if (rli->state != RLI_LINE_SET) { rli->len = 0; rli->point = 0; *rli->buf = 0; } rli->state = RLI_LINE_IN_PROGRESS; rli->curs_pos = rli->start_column = 0; rli->new_upd_len = rli->old_upd_len = 0; rli->last_fun = NULL; if (rli->update_hook == NULL) putc ('\r', stdout); rli->is_modified = 0; rli->last = NULL; RLupdate (rli); last_input_char = 0; while (1) { SLrline_Type *save_rli = Active_Rline_Info; key = SLang_do_key (RL_Keymap, (int (*)(void)) rli->getkey); if ((key == NULL) || (key->f.f == NULL)) { rl_beep (); continue; } if ((*key->str != 2) || (key->str[1] != rli->eof_char)) last_input_char = 0; else { if ((rli->len == 0) && (last_input_char != rli->eof_char)) { rli->buf[rli->len] = 0; rli->state = RLI_LINE_READ; *lenp = 0; return NULL; /* EOF */ } last_input_char = rli->eof_char; } Active_Rline_Info = rli; if (key->type == SLKEY_F_INTRINSIC) { int (*func)(SLrline_Type *); func = (int (*)(SLrline_Type *)) key->f.f; (void) (*func)(rli); RLupdate (rli); if ((rli->flags & SL_RLINE_BLINK_MATCH) && (rli->input_pending != NULL)) blink_match (rli); } else if (key->type == SLKEY_F_SLANG) { (void) SLexecute_function (key->f.slang_fun); RLupdate (rli); } Active_Rline_Info = save_rli; if ((SLang_Rline_Quit) || _pSLang_Error) { if (_pSLang_Error) { rli->len = 0; } rli->buf[rli->len] = 0; rli->state = RLI_LINE_READ; *lenp = rli->len; free_history_item (rli->saved_line); rli->saved_line = NULL; if (_pSLang_Error) return NULL; return SLmake_nstring ((char *)rli->buf, rli->len); } if (key != NULL) rli->last_fun = key->f.f; } }