Annotation of src/usr.bin/vim/alloc.c, Revision 1.1
1.1 ! downsj 1: /* $OpenBSD$ */
! 2: /* vi:set ts=4 sw=4:
! 3: *
! 4: * VIM - Vi IMproved by Bram Moolenaar
! 5: *
! 6: * Do ":help uganda" in Vim to read copying and usage conditions.
! 7: * Do ":help credits" in Vim to see a list of people who contributed.
! 8: */
! 9:
! 10: /*
! 11: * alloc.c
! 12: *
! 13: * This file contains various routines dealing with allocation and
! 14: * deallocation of memory. And some funcions for copying text.
! 15: */
! 16:
! 17: #include "vim.h"
! 18: #include "globals.h"
! 19: #include "proto.h"
! 20:
! 21: /*
! 22: * Some memory is reserved for error messages and for being able to
! 23: * call mf_release_all(), which needs some memory for mf_trans_add().
! 24: */
! 25: #define KEEP_ROOM 8192L
! 26:
! 27: /*
! 28: * Note: if unsinged is 16 bits we can only allocate up to 64K with alloc().
! 29: * Use lalloc for larger blocks.
! 30: */
! 31: char_u *
! 32: alloc(size)
! 33: unsigned size;
! 34: {
! 35: return (lalloc((long_u)size, TRUE));
! 36: }
! 37:
! 38: /*
! 39: * alloc() with check for maximum line length
! 40: */
! 41: char_u *
! 42: alloc_check(size)
! 43: unsigned size;
! 44: {
! 45: #if !defined(UNIX) && !defined(__EMX__)
! 46: if (sizeof(int) == 2 && size > 0x7fff)
! 47: {
! 48: EMSG("Line is becoming too long");
! 49: return NULL;
! 50: }
! 51: #endif
! 52: return (lalloc((long_u)size, TRUE));
! 53: }
! 54:
! 55: char_u *
! 56: lalloc(size, message)
! 57: long_u size;
! 58: int message;
! 59: {
! 60: register char_u *p; /* pointer to new storage space */
! 61: static int releasing = FALSE; /* don't do mf_release_all() recursive */
! 62: int try_again;
! 63:
! 64: if (size <= 0)
! 65: {
! 66: EMSGN("Internal error: lalloc(%ld, )", size);
! 67: return NULL;
! 68: }
! 69: #if defined(MSDOS) && !defined(DJGPP)
! 70: if (size >= 0xfff0) /* in MSDOS we can't deal with >64K blocks */
! 71: p = NULL;
! 72: else
! 73: #endif
! 74:
! 75: /*
! 76: * If out of memory, try to release some memfile blocks.
! 77: * If some blocks are released call malloc again.
! 78: */
! 79: for (;;)
! 80: {
! 81: if ((p = (char_u *)malloc(size)) != NULL)
! 82: {
! 83: if (mch_avail_mem(TRUE) < KEEP_ROOM && !releasing)
! 84: { /* System is low... no go! */
! 85: vim_free((char *)p);
! 86: p = NULL;
! 87: }
! 88: }
! 89: /*
! 90: * Remember that mf_release_all() is being called to avoid an endless loop,
! 91: * because mf_release_all() may call alloc() recursively.
! 92: */
! 93: if (p != NULL || releasing)
! 94: break;
! 95: releasing = TRUE;
! 96: try_again = mf_release_all();
! 97: releasing = FALSE;
! 98: if (!try_again)
! 99: break;
! 100: }
! 101:
! 102: /*
! 103: * Avoid repeating the error message many times (they take 1 second each).
! 104: * Did_outofmem_msg is reset when a character is read.
! 105: */
! 106: if (message && p == NULL)
! 107: do_outofmem_msg();
! 108: return (p);
! 109: }
! 110:
! 111: void
! 112: do_outofmem_msg()
! 113: {
! 114: if (!did_outofmem_msg)
! 115: {
! 116: emsg(e_outofmem);
! 117: did_outofmem_msg = TRUE;
! 118: }
! 119: }
! 120:
! 121: /*
! 122: * copy a string into newly allocated memory
! 123: */
! 124: char_u *
! 125: strsave(string)
! 126: char_u *string;
! 127: {
! 128: char_u *p;
! 129:
! 130: p = alloc((unsigned) (STRLEN(string) + 1));
! 131: if (p != NULL)
! 132: STRCPY(p, string);
! 133: return p;
! 134: }
! 135:
! 136: char_u *
! 137: strnsave(string, len)
! 138: char_u *string;
! 139: int len;
! 140: {
! 141: char_u *p;
! 142:
! 143: p = alloc((unsigned) (len + 1));
! 144: if (p != NULL)
! 145: {
! 146: STRNCPY(p, string, len);
! 147: p[len] = NUL;
! 148: }
! 149: return p;
! 150: }
! 151:
! 152: /*
! 153: * Same as strsave(), but any characters found in esc_chars are preceded by a
! 154: * backslash.
! 155: */
! 156: char_u *
! 157: strsave_escaped(string, esc_chars)
! 158: char_u *string;
! 159: char_u *esc_chars;
! 160: {
! 161: char_u *p;
! 162: char_u *p2;
! 163: char_u *escaped_string;
! 164: unsigned length;
! 165:
! 166: /*
! 167: * First count the number of backslashes required.
! 168: * Then allocate the memory and insert them.
! 169: */
! 170: length = 1; /* count the trailing '/' and NUL */
! 171: for (p = string; *p; p++)
! 172: {
! 173: if (vim_strchr(esc_chars, *p) != NULL)
! 174: ++length; /* count a backslash */
! 175: ++length; /* count an ordinary char */
! 176: }
! 177: escaped_string = alloc(length);
! 178: if (escaped_string != NULL)
! 179: {
! 180: p2 = escaped_string;
! 181: for (p = string; *p; p++)
! 182: {
! 183: if (vim_strchr(esc_chars, *p) != NULL)
! 184: *p2++ = '\\';
! 185: *p2++ = *p;
! 186: }
! 187: *p2 = NUL;
! 188: }
! 189: return escaped_string;
! 190: }
! 191:
! 192: /*
! 193: * copy a number of spaces
! 194: */
! 195: void
! 196: copy_spaces(ptr, count)
! 197: char_u *ptr;
! 198: size_t count;
! 199: {
! 200: register size_t i = count;
! 201: register char_u *p = ptr;
! 202:
! 203: while (i--)
! 204: *p++ = ' ';
! 205: }
! 206:
! 207: /*
! 208: * delete spaces at the end of a string
! 209: */
! 210: void
! 211: del_trailing_spaces(ptr)
! 212: char_u *ptr;
! 213: {
! 214: char_u *q;
! 215:
! 216: q = ptr + STRLEN(ptr);
! 217: while (--q > ptr && vim_iswhite(q[0]) && q[-1] != '\\' &&
! 218: q[-1] != Ctrl('V'))
! 219: *q = NUL;
! 220: }
! 221:
! 222: /*
! 223: * Isolate one part of a string option where parts are separated with commas.
! 224: * The part is copied into buf[maxlen].
! 225: * "*option" is advanced to the next part.
! 226: * The length is returned.
! 227: */
! 228: int
! 229: copy_option_part(option, buf, maxlen, sep_chars)
! 230: char_u **option;
! 231: char_u *buf;
! 232: int maxlen;
! 233: char *sep_chars;
! 234: {
! 235: int len = 0;
! 236: char_u *p = *option;
! 237:
! 238: /* skip '.' at start of option part, for 'suffixes' */
! 239: if (*p == '.')
! 240: buf[len++] = *p++;
! 241: while (*p && vim_strchr((char_u *)sep_chars, *p) == NULL)
! 242: {
! 243: /*
! 244: * Skip backslash before a separator character and space.
! 245: */
! 246: if (p[0] == '\\' && vim_strchr((char_u *)sep_chars, p[1]) != NULL)
! 247: ++p;
! 248: if (len < maxlen - 1)
! 249: buf[len++] = *p;
! 250: ++p;
! 251: }
! 252: buf[len] = NUL;
! 253:
! 254: p = skip_to_option_part(p); /* p points to next file name */
! 255:
! 256: *option = p;
! 257: return len;
! 258: }
! 259:
! 260: /*
! 261: * replacement for free() that ignores NULL pointers
! 262: */
! 263: void
! 264: vim_free(x)
! 265: void *x;
! 266: {
! 267: if (x != NULL)
! 268: free(x);
! 269: }
! 270:
! 271: #ifndef HAVE_MEMSET
! 272: void *
! 273: vim_memset(ptr, c, size)
! 274: void *ptr;
! 275: int c;
! 276: size_t size;
! 277: {
! 278: register char *p = ptr;
! 279:
! 280: while (size-- > 0)
! 281: *p++ = c;
! 282: return ptr;
! 283: }
! 284: #endif
! 285:
! 286: #ifdef VIM_MEMMOVE
! 287: /*
! 288: * Version of memmove that handles overlapping source and destination.
! 289: * For systems that don't have a function that is guaranteed to do that (SYSV).
! 290: */
! 291: void
! 292: vim_memmove(dst_arg, src_arg, len)
! 293: void *src_arg, *dst_arg;
! 294: size_t len;
! 295: {
! 296: /*
! 297: * A void doesn't have a size, we use char pointers.
! 298: */
! 299: register char *dst = dst_arg, *src = src_arg;
! 300:
! 301: /* overlap, copy backwards */
! 302: if (dst > src && dst < src + len)
! 303: {
! 304: src +=len;
! 305: dst +=len;
! 306: while (len-- > 0)
! 307: *--dst = *--src;
! 308: }
! 309: else /* copy forwards */
! 310: while (len-- > 0)
! 311: *dst++ = *src++;
! 312: }
! 313: #endif
! 314:
! 315: /*
! 316: * compare two strings, ignoring case
! 317: * return 0 for match, 1 for difference
! 318: */
! 319: int
! 320: vim_strnicmp(s1, s2, len)
! 321: char_u *s1;
! 322: char_u *s2;
! 323: size_t len;
! 324: {
! 325: while (len)
! 326: {
! 327: if (TO_UPPER(*s1) != TO_UPPER(*s2))
! 328: return 1; /* this character different */
! 329: if (*s1 == NUL)
! 330: return 0; /* strings match until NUL */
! 331: ++s1;
! 332: ++s2;
! 333: --len;
! 334: }
! 335: return 0; /* strings match */
! 336: }
! 337:
! 338: /*
! 339: * Version of strchr() and strrchr() that handle unsigned char strings
! 340: * with characters above 128 correctly. Also it doesn't return a pointer to
! 341: * the NUL at the end of the string.
! 342: */
! 343: char_u *
! 344: vim_strchr(string, n)
! 345: char_u *string;
! 346: int n;
! 347: {
! 348: while (*string)
! 349: {
! 350: if (*string == n)
! 351: return string;
! 352: ++string;
! 353: }
! 354: return NULL;
! 355: }
! 356:
! 357: char_u *
! 358: vim_strrchr(string, n)
! 359: char_u *string;
! 360: int n;
! 361: {
! 362: char_u *retval = NULL;
! 363:
! 364: while (*string)
! 365: {
! 366: if (*string == n)
! 367: retval = string;
! 368: ++string;
! 369: }
! 370: return retval;
! 371: }
! 372:
! 373: /*
! 374: * Vim has its own isspace() function, because on some machines isspace()
! 375: * can't handle characters above 128.
! 376: */
! 377: int
! 378: vim_isspace(x)
! 379: int x;
! 380: {
! 381: return ((x >= 9 && x <= 13) || x == ' ');
! 382: }