parser: Clear reparse flag earlier
Now the reparse' flag is true only while stack unwinding is begin done.
The reparse' flag is cleared just after stack unwinding ends.
@@ -510,10 +510,10 @@ | ||
510 | 510 | struct plist_T pending_heredocs; |
511 | 511 | /* false when alias substitution is suppressed */ |
512 | 512 | bool enable_alias; |
513 | - /* true when alias substitution has occurred */ | |
513 | + /* true when non-global alias substitution has occurred */ | |
514 | 514 | bool reparse; |
515 | 515 | /* record of alias substitutions that are responsible for the current |
516 | - * `startindex' */ | |
516 | + * `index' */ | |
517 | 517 | struct aliaslist_T *aliases; |
518 | 518 | } parsestate_T; |
519 | 519 |
@@ -1800,6 +1800,7 @@ | ||
1800 | 1800 | lastp = &ao->next; |
1801 | 1801 | } |
1802 | 1802 | if (ps->reparse) { |
1803 | + ps->reparse = false; | |
1803 | 1804 | assert(ao == NULL); |
1804 | 1805 | continue; |
1805 | 1806 | } |
@@ -1813,7 +1814,6 @@ | ||
1813 | 1814 | } |
1814 | 1815 | if (!toeol) |
1815 | 1816 | ps->error |= saveerror; |
1816 | - ps->reparse = false; | |
1817 | 1817 | return first; |
1818 | 1818 | } |
1819 | 1819 |
@@ -1860,10 +1860,12 @@ | ||
1860 | 1860 | } |
1861 | 1861 | if (ps->reparse) { |
1862 | 1862 | assert(p == NULL); |
1863 | - if (first != NULL) | |
1863 | + if (first != NULL) { | |
1864 | + ps->reparse = false; | |
1864 | 1865 | goto next; |
1865 | - else | |
1866 | + } else { | |
1866 | 1867 | break; |
1868 | + } | |
1867 | 1869 | } |
1868 | 1870 | |
1869 | 1871 | if (ps->tokentype == TT_AMPAMP) |
@@ -1893,11 +1895,14 @@ | ||
1893 | 1895 | serror(ps, Ngt("ksh-like extended glob pattern `!(...)' " |
1894 | 1896 | "is not supported")); |
1895 | 1897 | next_token(ps); |
1896 | - do { | |
1897 | - c = parse_commands_in_pipeline(ps); | |
1898 | - if (ps->reparse) | |
1899 | - assert(c == NULL); | |
1900 | - } while (ps->reparse); | |
1898 | + | |
1899 | +parse_after_bang: | |
1900 | + c = parse_commands_in_pipeline(ps); | |
1901 | + if (ps->reparse) { | |
1902 | + ps->reparse = false; | |
1903 | + assert(c == NULL); | |
1904 | + goto parse_after_bang; | |
1905 | + } | |
1901 | 1906 | } else { |
1902 | 1907 | neg = false; |
1903 | 1908 | c = parse_commands_in_pipeline(ps); |
@@ -1930,10 +1935,12 @@ | ||
1930 | 1935 | } |
1931 | 1936 | if (ps->reparse) { |
1932 | 1937 | assert(c == NULL); |
1933 | - if (first != NULL) | |
1938 | + if (first != NULL) { | |
1939 | + ps->reparse = false; | |
1934 | 1940 | goto next; |
1935 | - else | |
1941 | + } else { | |
1936 | 1942 | break; |
1943 | + } | |
1937 | 1944 | } |
1938 | 1945 | |
1939 | 1946 | if (ps->tokentype != TT_PIPE) |
@@ -1951,8 +1958,6 @@ | ||
1951 | 1958 | * NULL is returned. */ |
1952 | 1959 | command_T *parse_command(parsestate_T *ps) |
1953 | 1960 | { |
1954 | - ps->reparse = false; | |
1955 | - | |
1956 | 1961 | if (ps->tokentype == TT_BANG || ps->tokentype == TT_IN || |
1957 | 1962 | is_closing_tokentype(ps->tokentype)) { |
1958 | 1963 | print_errmsg_token_unexpected(ps); |
@@ -1964,6 +1969,10 @@ | ||
1964 | 1969 | return result; |
1965 | 1970 | |
1966 | 1971 | if (psubstitute_alias(ps, AF_NONGLOBAL)) { |
1972 | + /* After alias substitution, we need to re-parse the new current token, | |
1973 | + * which may be consumed by the caller of this function. We set the | |
1974 | + * `reparse' flag to tell the caller to re-parse the token. The caller | |
1975 | + * will reset the flag when staring re-parsing. */ | |
1967 | 1976 | ps->reparse = true; |
1968 | 1977 | return NULL; |
1969 | 1978 | } |