sb_initwithmax and wb_initwithmax
@@ -1,6 +1,6 @@ | ||
1 | 1 | /* Yash: yet another shell */ |
2 | 2 | /* builtin.c: built-in commands */ |
3 | -/* (C) 2007-2018 magicant */ | |
3 | +/* (C) 2007-2020 magicant */ | |
4 | 4 | |
5 | 5 | /* This program is free software: you can redistribute it and/or modify |
6 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -422,7 +422,7 @@ | ||
422 | 422 | bool print_short_option = there_is_any_short_option(options); |
423 | 423 | |
424 | 424 | xstrbuf_T line; |
425 | - sb_init(&line); | |
425 | + sb_initwithmax(&line, 127); | |
426 | 426 | |
427 | 427 | for (const struct xgetopt_T *opt = options; opt->shortopt != L'\0'; opt++) { |
428 | 428 | if (posixly_correct && !opt->posix) |
@@ -845,7 +845,7 @@ | ||
845 | 845 | pl_add(&e->e.cclist, sb_tostr(&e->ccbuf)); |
846 | 846 | |
847 | 847 | wb_initwith(&e->valuebuf, values[i]); |
848 | - sb_init(&e->ccbuf); | |
848 | + sb_initwithmax(&e->ccbuf, e->valuebuf.length); | |
849 | 849 | fill_ccbuf(e, cc); |
850 | 850 | } |
851 | 851 | } |
@@ -1165,11 +1165,12 @@ | ||
1165 | 1165 | size_t lastelemindex = splitpoints.length - 1; |
1166 | 1166 | size_t headlen = idx(splitpoints.contents[0]) - 1; |
1167 | 1167 | size_t taillen = wcslen(splitpoints.contents[lastelemindex]); |
1168 | + size_t totallen = idx(splitpoints.contents[lastelemindex]) + taillen; | |
1168 | 1169 | for (size_t i = 0; i < lastelemindex; i++) { |
1169 | 1170 | xwcsbuf_T buf; |
1170 | 1171 | xstrbuf_T cbuf; |
1171 | - wb_init(&buf); | |
1172 | - sb_init(&cbuf); | |
1172 | + wb_initwithmax(&buf, totallen); | |
1173 | + sb_initwithmax(&cbuf, totallen); | |
1173 | 1174 | |
1174 | 1175 | wb_ncat_force(&buf, word, headlen); |
1175 | 1176 | sb_ncat_force(&cbuf, cc, headlen); |
@@ -1268,8 +1269,8 @@ | ||
1268 | 1269 | do { |
1269 | 1270 | xwcsbuf_T buf; |
1270 | 1271 | xstrbuf_T cbuf; |
1271 | - wb_init(&buf); | |
1272 | - sb_init(&cbuf); | |
1272 | + wb_initwithmax(&buf, wordlen); | |
1273 | + sb_initwithmax(&cbuf, wordlen); | |
1273 | 1274 | |
1274 | 1275 | size_t slen = idx(startc - 1); |
1275 | 1276 | wb_ncat_force(&buf, word, slen); |
@@ -1510,7 +1511,7 @@ | ||
1510 | 1511 | wchar_t *escape(const wchar_t *restrict s, const wchar_t *restrict t) |
1511 | 1512 | { |
1512 | 1513 | xwcsbuf_T buf; |
1513 | - wb_init(&buf); | |
1514 | + wb_initwithmax(&buf, mul(wcslen(s), 2)); | |
1514 | 1515 | for (size_t i = 0; s[i] != L'\0'; i++) { |
1515 | 1516 | if (t == NULL || wcschr(t, s[i]) != NULL) |
1516 | 1517 | wb_wccat(&buf, L'\\'); |
@@ -1536,7 +1537,7 @@ | ||
1536 | 1537 | wchar_t *unescape(const wchar_t *s) |
1537 | 1538 | { |
1538 | 1539 | xwcsbuf_T buf; |
1539 | - wb_init(&buf); | |
1540 | + wb_initwithmax(&buf, wcslen(s)); | |
1540 | 1541 | for (size_t i = 0; s[i] != L'\0'; i++) { |
1541 | 1542 | if (s[i] == L'\\') { |
1542 | 1543 | i++; |
@@ -1565,7 +1566,7 @@ | ||
1565 | 1566 | wchar_t *quote_as_word(const wchar_t *s) |
1566 | 1567 | { |
1567 | 1568 | xwcsbuf_T buf; |
1568 | - wb_init(&buf); | |
1569 | + wb_initwithmax(&buf, mul(wcslen(s), 2)); | |
1569 | 1570 | wb_quote_as_word(&buf, s); |
1570 | 1571 | return wb_towcs(&buf); |
1571 | 1572 | } |
@@ -1619,7 +1620,7 @@ | ||
1619 | 1620 | { |
1620 | 1621 | bool indq = false; |
1621 | 1622 | xwcsbuf_T buf; |
1622 | - wb_init(&buf); | |
1623 | + wb_initwithmax(&buf, wcslen(s)); | |
1623 | 1624 | for (;;) { |
1624 | 1625 | switch (*s) { |
1625 | 1626 | case L'\0': |
@@ -1670,7 +1671,7 @@ | ||
1670 | 1671 | const wchar_t *restrict s, const char *restrict cc, escaping_T escaping) |
1671 | 1672 | { |
1672 | 1673 | xwcsbuf_T result; |
1673 | - wb_init(&result); | |
1674 | + wb_initwithmax(&result, mul(wcslen(s), 2)); | |
1674 | 1675 | for (size_t i = 0; s[i] != L'\0'; i++) { |
1675 | 1676 | if (cc[i] & CC_QUOTATION) |
1676 | 1677 | continue; |
@@ -1,6 +1,6 @@ | ||
1 | 1 | /* Yash: yet another shell */ |
2 | 2 | /* history.c: command history management */ |
3 | -/* (C) 2007-2016 magicant */ | |
3 | +/* (C) 2007-2020 magicant */ | |
4 | 4 | |
5 | 5 | /* This program is free software: you can redistribute it and/or modify |
6 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -77,7 +77,11 @@ | ||
77 | 77 | #error DEFAULT_HISTSIZE cannot be larger than HISTORY_MIN_MAX_NUMBER |
78 | 78 | #endif |
79 | 79 | |
80 | +#ifndef HISTORY_DEFAULT_LINE_LENGTH | |
81 | +#define HISTORY_DEFAULT_LINE_LENGTH 127 | |
82 | +#endif | |
80 | 83 | |
84 | + | |
81 | 85 | /* The main history list. */ |
82 | 86 | histlist_T histlist = { |
83 | 87 | .link = { Histlist, Histlist, }, |
@@ -649,7 +653,7 @@ | ||
649 | 653 | |
650 | 654 | assert(histfile != NULL); |
651 | 655 | rewind(histfile); |
652 | - if (!read_line(histfile, wb_init(&buf))) | |
656 | + if (!read_line(histfile, wb_initwithmax(&buf, HISTORY_DEFAULT_LINE_LENGTH))) | |
653 | 657 | goto end; |
654 | 658 | |
655 | 659 | s = matchwcsprefix(buf.contents, L"#$# yash history v0 r"); |
@@ -675,7 +679,7 @@ | ||
675 | 679 | xwcsbuf_T buf; |
676 | 680 | |
677 | 681 | assert(histfile != NULL); |
678 | - wb_init(&buf); | |
682 | + wb_initwithmax(&buf, HISTORY_DEFAULT_LINE_LENGTH); | |
679 | 683 | while (read_line(histfile, &buf)) { |
680 | 684 | char *line = malloc_wcstombs(buf.contents); |
681 | 685 | if (line != NULL) { |
@@ -699,7 +703,7 @@ | ||
699 | 703 | xwcsbuf_T buf; |
700 | 704 | |
701 | 705 | assert(histfile != NULL); |
702 | - wb_init(&buf); | |
706 | + wb_initwithmax(&buf, HISTORY_DEFAULT_LINE_LENGTH); | |
703 | 707 | while (read_line(histfile, &buf)) { |
704 | 708 | histfilelines++; |
705 | 709 | switch (buf.contents[0]) { |
@@ -1606,7 +1610,7 @@ | ||
1606 | 1610 | update_time(); |
1607 | 1611 | update_history(false); |
1608 | 1612 | |
1609 | - wb_init(&buf); | |
1613 | + wb_initwithmax(&buf, HISTORY_DEFAULT_LINE_LENGTH); | |
1610 | 1614 | while (read_line(f, &buf)) { |
1611 | 1615 | if (!quiet) |
1612 | 1616 | printf("%ls\n", buf.contents); |
@@ -117,7 +117,7 @@ | ||
117 | 117 | le_context_T *ctxt = xmalloc(sizeof *ctxt); |
118 | 118 | |
119 | 119 | cparseinfo_T parseinfo; |
120 | - wb_init(&parseinfo.buf); | |
120 | + wb_initwithmax(&parseinfo.buf, le_main_index); | |
121 | 121 | wb_ncat_force(&parseinfo.buf, le_main_buffer.contents, le_main_index); |
122 | 122 | parseinfo.bufindex = 0; |
123 | 123 | parseinfo.aliaslist = NULL; |
@@ -1207,7 +1207,7 @@ | ||
1207 | 1207 | bool unclosed = false; |
1208 | 1208 | xwcsbuf_T buf; |
1209 | 1209 | |
1210 | - wb_init(&buf); | |
1210 | + wb_initwithmax(&buf, wcslen(s)); | |
1211 | 1211 | wb_cat(&buf, s); |
1212 | 1212 | |
1213 | 1213 | for (size_t i = 0; i < buf.length; ) { |
@@ -1,6 +1,6 @@ | ||
1 | 1 | /* Yash: yet another shell */ |
2 | 2 | /* editing.c: main editing module */ |
3 | -/* (C) 2007-2017 magicant */ | |
3 | +/* (C) 2007-2020 magicant */ | |
4 | 4 | |
5 | 5 | /* This program is free software: you can redistribute it and/or modify |
6 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -3143,7 +3143,7 @@ | ||
3143 | 3143 | } |
3144 | 3144 | if (w1end >= w2start) |
3145 | 3145 | goto error; |
3146 | - wb_init(&buf); | |
3146 | + wb_initwithmax(&buf, w2end - w1start); | |
3147 | 3147 | wb_ncat_force(&buf, &le_main_buffer.contents[w2start], w2end - w2start); |
3148 | 3148 | wb_ncat_force(&buf, &le_main_buffer.contents[w1end], w2start - w1end); |
3149 | 3149 | wb_ncat_force(&buf, &le_main_buffer.contents[w1start], w1end - w1start); |
@@ -1,6 +1,6 @@ | ||
1 | 1 | /* Yash: yet another shell */ |
2 | 2 | /* option.c: option settings */ |
3 | -/* (C) 2007-2018 magicant */ | |
3 | +/* (C) 2007-2020 magicant */ | |
4 | 4 | |
5 | 5 | /* This program is free software: you can redistribute it and/or modify |
6 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -398,7 +398,7 @@ | ||
398 | 398 | wchar_t *normalize_option_name(const wchar_t *optname) |
399 | 399 | { |
400 | 400 | xwcsbuf_T result; |
401 | - wb_init(&result); | |
401 | + wb_initwithmax(&result, wcslen(optname)); | |
402 | 402 | for (const wchar_t *s = optname; *s != L'\0'; s++) |
403 | 403 | if (iswalnum(*s)) |
404 | 404 | wb_wccat(&result, towlower(*s)); |
@@ -1,6 +1,6 @@ | ||
1 | 1 | /* Yash: yet another shell */ |
2 | 2 | /* path.c: filename-related utilities */ |
3 | -/* (C) 2007-2016 magicant */ | |
3 | +/* (C) 2007-2020 magicant */ | |
4 | 4 | |
5 | 5 | /* This program is free software: you can redistribute it and/or modify |
6 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -323,7 +323,7 @@ | ||
323 | 323 | n = (uintmax_t) shell_pid * 272229637312669; |
324 | 324 | if (num == 0) |
325 | 325 | num = (uintmax_t) time(NULL) * 5131212142718371 << 1 | 1; |
326 | - sb_init(&buf); | |
326 | + sb_initwithmax(&buf, 31); | |
327 | 327 | for (int i = 0; i < 100; i++) { |
328 | 328 | num = (num ^ n) * 16777619; |
329 | 329 | sb_printf(&buf, "/tmp/yash-%" PRIXMAX, num); |
@@ -641,18 +641,18 @@ | ||
641 | 641 | bool wglob(const wchar_t *restrict pattern, enum wglobflags_T flags, |
642 | 642 | plist_T *restrict list) |
643 | 643 | { |
644 | - size_t listbase = list->length; | |
644 | + size_t listbase = list->length, patternsize = add(wcslen(pattern), 1); | |
645 | 645 | xstrbuf_T path; |
646 | 646 | xwcsbuf_T wpath; |
647 | 647 | struct wglob_pattern *p; |
648 | - wchar_t savepattern[wcslen(pattern) + 1]; | |
648 | + wchar_t savepattern[patternsize]; | |
649 | 649 | |
650 | 650 | p = wglob_parse_pattern(wcscpy(savepattern, pattern), flags); |
651 | 651 | if (p == NULL) |
652 | 652 | return false; |
653 | 653 | |
654 | - sb_init(&path); | |
655 | - wb_init(&wpath); | |
654 | + sb_initwithmax(&path, patternsize); | |
655 | + wb_initwithmax(&wpath, patternsize); | |
656 | 656 | wglob_search(p, flags, &path, &wpath, list); |
657 | 657 | sb_destroy(&path); |
658 | 658 | wb_destroy(&wpath); |
@@ -1595,7 +1595,7 @@ | ||
1595 | 1595 | { |
1596 | 1596 | xstrbuf_T outputtext; |
1597 | 1597 | |
1598 | - sb_init(&outputtext); | |
1598 | + sb_initwithmax(&outputtext, 18); | |
1599 | 1599 | sb_ccat(&outputtext, 'u'); |
1600 | 1600 | sb_ccat(&outputtext, '='); |
1601 | 1601 | if (!(mode & S_IRUSR)) sb_ccat(&outputtext, 'r'); |
@@ -1,6 +1,6 @@ | ||
1 | 1 | /* Yash: yet another shell */ |
2 | 2 | /* strbuf.c: modifiable string buffer */ |
3 | -/* (C) 2007-2015 magicant */ | |
3 | +/* (C) 2007-2020 magicant */ | |
4 | 4 | |
5 | 5 | /* This program is free software: you can redistribute it and/or modify |
6 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -36,14 +36,7 @@ | ||
36 | 36 | size_t len, mbstate_t *restrict ps); |
37 | 37 | #endif |
38 | 38 | |
39 | -#ifndef XSTRBUF_INITSIZE | |
40 | -#define XSTRBUF_INITSIZE 15 | |
41 | -#endif | |
42 | -#ifndef XWCSBUF_INITSIZE | |
43 | -#define XWCSBUF_INITSIZE 15 | |
44 | -#endif | |
45 | 39 | |
46 | - | |
47 | 40 | /* If the type of the return value of the functions below is string buffer, |
48 | 41 | * the return value is the argument buffer. */ |
49 | 42 |
@@ -51,13 +44,13 @@ | ||
51 | 44 | /********** Multibyte String Buffer **********/ |
52 | 45 | |
53 | 46 | /* Initializes the specified string buffer as an empty string. */ |
54 | -xstrbuf_T *sb_init(xstrbuf_T *buf) | |
47 | +xstrbuf_T *sb_initwithmax(xstrbuf_T *buf, size_t max) | |
55 | 48 | { |
56 | - // buf->contents = xmallocn(XSTRBUF_INITSIZE + 1, sizeof (char)); | |
57 | - buf->contents = xmalloc(XSTRBUF_INITSIZE + 1); | |
49 | + // buf->contents = xmalloce(max, 1, sizeof (char)); | |
50 | + buf->contents = xmalloc(add(max, 1)); | |
58 | 51 | buf->contents[0] = '\0'; |
59 | 52 | buf->length = 0; |
60 | - buf->maxlength = XSTRBUF_INITSIZE; | |
53 | + buf->maxlength = max; | |
61 | 54 | return buf; |
62 | 55 | } |
63 | 56 |
@@ -322,12 +315,12 @@ | ||
322 | 315 | /********** Wide String Buffer **********/ |
323 | 316 | |
324 | 317 | /* Initializes the specified wide string buffer as an empty string. */ |
325 | -xwcsbuf_T *wb_init(xwcsbuf_T *buf) | |
318 | +xwcsbuf_T *wb_initwithmax(xwcsbuf_T *buf, size_t max) | |
326 | 319 | { |
327 | - buf->contents = xmallocn(XWCSBUF_INITSIZE + 1, sizeof (wchar_t)); | |
320 | + buf->contents = xmalloce(max, 1, sizeof (wchar_t)); | |
328 | 321 | buf->contents[0] = L'\0'; |
329 | 322 | buf->length = 0; |
330 | - buf->maxlength = XWCSBUF_INITSIZE; | |
323 | + buf->maxlength = max; | |
331 | 324 | return buf; |
332 | 325 | } |
333 | 326 |
@@ -25,7 +25,14 @@ | ||
25 | 25 | |
26 | 26 | #define Size_max ((size_t) -1) // = SIZE_MAX |
27 | 27 | |
28 | +#ifndef XSTRBUF_INITSIZE | |
29 | +#define XSTRBUF_INITSIZE 15 | |
30 | +#endif | |
31 | +#ifndef XWCSBUF_INITSIZE | |
32 | +#define XWCSBUF_INITSIZE 15 | |
33 | +#endif | |
28 | 34 | |
35 | + | |
29 | 36 | typedef struct xstrbuf_T { |
30 | 37 | char *contents; |
31 | 38 | size_t length, maxlength; |
@@ -35,10 +42,12 @@ | ||
35 | 42 | size_t length, maxlength; |
36 | 43 | } xwcsbuf_T; |
37 | 44 | |
38 | -extern xstrbuf_T *sb_init(xstrbuf_T *buf) | |
45 | +static inline xstrbuf_T *sb_init(xstrbuf_T *buf) | |
39 | 46 | __attribute__((nonnull)); |
40 | 47 | extern xstrbuf_T *sb_initwith(xstrbuf_T *restrict buf, char *restrict s) |
41 | 48 | __attribute__((nonnull)); |
49 | +extern xstrbuf_T *sb_initwithmax(xstrbuf_T *buf, size_t max) | |
50 | + __attribute__((nonnull)); | |
42 | 51 | static inline void sb_destroy(xstrbuf_T *buf) |
43 | 52 | __attribute__((nonnull)); |
44 | 53 | static inline char *sb_tostr(xstrbuf_T *buf) |
@@ -107,10 +116,12 @@ | ||
107 | 116 | xstrbuf_T *restrict buf, const char *restrict format, ...) |
108 | 117 | __attribute__((nonnull(1,2),format(printf,2,3))); |
109 | 118 | |
110 | -extern xwcsbuf_T *wb_init(xwcsbuf_T *buf) | |
119 | +static inline xwcsbuf_T *wb_init(xwcsbuf_T *buf) | |
111 | 120 | __attribute__((nonnull)); |
112 | 121 | extern xwcsbuf_T *wb_initwith(xwcsbuf_T *restrict buf, wchar_t *restrict s) |
113 | 122 | __attribute__((nonnull)); |
123 | +extern xwcsbuf_T *wb_initwithmax(xwcsbuf_T *buf, size_t max) | |
124 | + __attribute__((nonnull)); | |
114 | 125 | static inline void wb_destroy(xwcsbuf_T *buf) |
115 | 126 | __attribute__((nonnull)); |
116 | 127 | static inline wchar_t *wb_towcs(xwcsbuf_T *buf) |
@@ -194,6 +205,12 @@ | ||
194 | 205 | __attribute__((malloc,warn_unused_result,nonnull)); |
195 | 206 | |
196 | 207 | |
208 | +/* Initializes the specified string buffer as an empty string. */ | |
209 | +xstrbuf_T *sb_init(xstrbuf_T *buf) | |
210 | +{ | |
211 | + return sb_initwithmax(buf, XSTRBUF_INITSIZE); | |
212 | +} | |
213 | + | |
197 | 214 | /* Frees the specified multibyte string buffer. The contents are lost. */ |
198 | 215 | void sb_destroy(xstrbuf_T *buf) |
199 | 216 | { |
@@ -310,6 +327,12 @@ | ||
310 | 327 | } |
311 | 328 | #endif |
312 | 329 | |
330 | +/* Initializes the specified wide string buffer as an empty string. */ | |
331 | +xwcsbuf_T *wb_init(xwcsbuf_T *buf) | |
332 | +{ | |
333 | + return wb_initwithmax(buf, XWCSBUF_INITSIZE); | |
334 | +} | |
335 | + | |
313 | 336 | /* Frees the specified wide string buffer. The contents are lost. */ |
314 | 337 | void wb_destroy(xwcsbuf_T *buf) |
315 | 338 | { |
@@ -1852,7 +1852,7 @@ | ||
1852 | 1852 | case L't': |
1853 | 1853 | assert(wcscmp(argv0, L"typeset") == 0); |
1854 | 1854 | typeset: |
1855 | - sb_init(&opts); | |
1855 | + sb_initwithmax(&opts, 4); | |
1856 | 1856 | if (var->v_type & VF_EXPORT) |
1857 | 1857 | sb_ccat(&opts, 'x'); |
1858 | 1858 | if (var->v_type & VF_READONLY) |
@@ -1913,7 +1913,7 @@ | ||
1913 | 1913 | case L't': |
1914 | 1914 | assert(wcscmp(argv0, L"typeset") == 0); |
1915 | 1915 | typeset: |
1916 | - sb_init(&opts); | |
1916 | + sb_initwithmax(&opts, 4); | |
1917 | 1917 | if (var->v_type & VF_EXPORT) |
1918 | 1918 | sb_ccat(&opts, 'x'); |
1919 | 1919 | if (var->v_type & VF_READONLY) |
@@ -1,6 +1,6 @@ | ||
1 | 1 | /* Yash: yet another shell */ |
2 | 2 | /* yash.c: basic functions of the shell */ |
3 | -/* (C) 2007-2018 magicant */ | |
3 | +/* (C) 2007-2020 magicant */ | |
4 | 4 | |
5 | 5 | /* This program is free software: you can redistribute it and/or modify |
6 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -303,7 +303,7 @@ | ||
303 | 303 | return false; |
304 | 304 | |
305 | 305 | xwcsbuf_T fullpath; |
306 | - wb_init(&fullpath); | |
306 | + wb_initwithmax(&fullpath, add(add(wcslen(home), wcslen(path)), 1)); | |
307 | 307 | wb_cat(&fullpath, home); |
308 | 308 | if (fullpath.contents[fullpath.length - 1] != L'/') |
309 | 309 | wb_wccat(&fullpath, L'/'); |