示例#1
0
/// Detect whether the escape sequence sets one of the terminal attributes that affects how text is
/// displayed other than the color.
static bool is_visual_escape_seq(const wchar_t *code, size_t *resulting_length) {
    if (!cur_term) return false;
    const char *const esc2[] = {
        enter_bold_mode,      exit_attribute_mode,    enter_underline_mode,  exit_underline_mode,
        enter_standout_mode,  exit_standout_mode,     flash_screen,          enter_subscript_mode,
        exit_subscript_mode,  enter_superscript_mode, exit_superscript_mode, enter_blink_mode,
        enter_italics_mode,   exit_italics_mode,      enter_reverse_mode,    enter_shadow_mode,
        exit_shadow_mode,     enter_standout_mode,    exit_standout_mode,    enter_secure_mode,
        enter_dim_mode,       enter_blink_mode,       enter_protected_mode,  enter_alt_charset_mode,
        exit_alt_charset_mode};

    for (size_t p = 0; p < sizeof esc2 / sizeof *esc2; p++) {
        if (!esc2[p]) continue;
        // Test both padded and unpadded version, just to be safe. Most versions of tparm don't
        // actually seem to do anything these days.
        size_t esc_seq_len =
            std::max(try_sequence(tparm((char *)esc2[p]), code), try_sequence(esc2[p], code));
        if (esc_seq_len) {
            *resulting_length = esc_seq_len;
            return true;
        }
    }

    return false;
}
示例#2
0
文件: testalloc.c 项目: ayraei/CS24
int main(int argc, char *argv[]) {

  int max_used_memory;
  int allocation_factor;
  int memory_required;

  SEQLIST *test_sequence;

  max_used_memory = 2000;
  allocation_factor = 11;

  printf("running with MAX_USED_MEMORY=%d and ALLOCATION_FACTOR=%d\n",
         max_used_memory, allocation_factor);

  test_sequence = generate_sequence(max_used_memory, allocation_factor);
  if (VERBOSE)
    seq_print(test_sequence);

  // check that allocation can actually do something.
  // This becomes upper bound on binary search.
  if (try_sequence(test_sequence, max_used_memory * allocation_factor * 2)) {

    // binary search for smallest MEMORY_SIZE which can accommodate
    memory_required = binary_search_required_memory(test_sequence,
      max_used_memory - 1, max_used_memory * allocation_factor * 2);

    // run it one more time at the identified size.
    // this makes sure that the data is set from a successful run.
    if (try_sequence(test_sequence, memory_required)) {
      // check if data contents are intact
      if (check_data(test_sequence)) {
        printf("Data integrity FAIL.\n");
      }
      else {
        printf("Data integrity PASS.\n");
      }

      // print statistics
      printf("Memory utilization: (%d/%d)=%f\n", max_used_memory, memory_required,
             ((double) max_used_memory / (double) memory_required));
    }
    else {
      printf("Consistency problem: binary_search_reqruired_memory "
             "returned %d, but final test failed\n", memory_required);
    }
  }
  else {
    printf("Requires more memory than the no-free case.\n");
  }
}
示例#3
0
// PCA for term256 support, let's just detect the escape codes directly
static int is_term256_escape(const wchar_t *str) {
    // An escape code looks like this: \x1b[38;5;<num>m 
    // or like this: \x1b[48;5;<num>m 
    
    // parse out the required prefix
    int len = try_sequence("\x1b[38;5;", str);
    if (! len) len = try_sequence("\x1b[48;5;", str);
    if (! len) return 0;
    
    // now try parsing out a string of digits
    // we need at least one
    if (! iswdigit(str[len])) return 0;
    while (iswdigit(str[len])) len++;
    
    // look for the terminating m
    if (str[len++] != L'm') return 0;
    
    // success
    return len;
}
示例#4
0
/// Detect whether the escape sequence sets foreground/background color. Note that 24-bit color
/// sequences are detected by `is_csi_style_escape_seq()` if they use the ANSI X3.64 pattern for
/// such sequences. This function only handles those escape sequences for setting color that rely on
/// the terminfo definition and which might use a different pattern.
static bool is_color_escape_seq(const wchar_t *code, size_t *resulting_length) {
    if (!cur_term) return false;

    // Detect these terminfo color escapes with parameter value up to max_colors, all of which
    // don't move the cursor.
    const char *const esc[] = {
        set_a_foreground, set_a_background, set_foreground, set_background,
    };

    for (size_t p = 0; p < sizeof esc / sizeof *esc; p++) {
        if (!esc[p]) continue;

        for (int k = 0; k < max_colors; k++) {
            size_t esc_seq_len = try_sequence(tparm((char *)esc[p], k), code);
            if (esc_seq_len) {
                *resulting_length = esc_seq_len;
                return true;
            }
        }
    }

    return false;
}
示例#5
0
文件: testalloc.c 项目: ayraei/CS24
// search over memory sizes between low and high
//  report smallest size that can accommodate the sequence
int binary_search_required_memory(SEQLIST *test_sequence, int low, int high) {
  // invariant: low not achievable, high is achievable

  int mid;

  if (low + 1 == high) {     // nothing in between, we've found the smallest
    return high;
  }
  else {
    mid = (low + high + 1) / 2;
    if (try_sequence(test_sequence, mid)) {
      if (VERBOSE)
        printf("\tSucceeded for %d\n", mid);

      return(binary_search_required_memory(test_sequence, low, mid));
    }
    else {
      if (VERBOSE)
        printf("\tFailed for %d\n", mid);

      return(binary_search_required_memory(test_sequence, mid, high));
    }
  }
}
示例#6
0
/**
   Read a character from keyboard
*/
static wint_t readch()
{
	struct mapping
	{
		const char *seq;
		wint_t bnd;
	}
	;
	
	struct mapping m[]=
		{
			{				
				"\x1b[A", LINE_UP
			}
			,
			{
				key_up, LINE_UP
			}
			,
			{				
				"\x1b[B", LINE_DOWN
			}
			,
			{
				key_down, LINE_DOWN
			}
			,
			{
				key_ppage, PAGE_UP
			}
			,
			{
				key_npage, PAGE_DOWN
			}
			,
			{
				" ", PAGE_DOWN
			}
			,
			{
				"\t", PAGE_DOWN
			}
			,
			{
				0, 0
			}
			
		}
	;
	int i;
	
	for( i=0; m[i].bnd; i++ )
	{
		if( !m[i].seq )
		{
			continue;
		}
		
		if( try_sequence(m[i].seq ) )
			return m[i].bnd;
	}
	return input_common_readch(0);
}
示例#7
0
/**
   Calculate the width of the specified prompt. Does some clever magic
   to detect common escape sequences that may be embeded in a prompt,
   such as color codes.
*/
static int calc_prompt_width( wchar_t *prompt )
{
	int res = 0;
	int j, k;

	for( j=0; prompt[j]; j++ )
	{
		if( prompt[j] == L'\x1b' )
		{
			/*
			  This is the start of an escape code. Try to guess it's width.
			*/
			int l;
			int len=0;
			int found = 0;

			/*
			  Detect these terminfo color escapes with parameter
			  value 0..7, all of which don't move the cursor
			*/
			char * esc[] =
				{
					set_a_foreground,
					set_a_background,
					set_foreground,
					set_background,
				}
			;

			/*
			  Detect these semi-common terminfo escapes without any
			  parameter values, all of which don't move the cursor
			*/
			char *esc2[] =
				{
					enter_bold_mode,
					exit_attribute_mode,
					enter_underline_mode,
					exit_underline_mode,
					enter_standout_mode,
					exit_standout_mode,
					flash_screen,
					enter_subscript_mode,
					exit_subscript_mode,
					enter_superscript_mode,
					exit_superscript_mode,
					enter_blink_mode,
					enter_italics_mode,
					exit_italics_mode,
					enter_reverse_mode,
					enter_shadow_mode,
					exit_shadow_mode,
					enter_standout_mode,
					exit_standout_mode,
					enter_secure_mode
				}
			;

			for( l=0; l < (sizeof(esc)/sizeof(char *)) && !found; l++ )
			{
				if( !esc[l] )
					continue;

				for( k=0; k<8; k++ )
				{
					len = try_sequence( tparm(esc[l],k), &prompt[j] );
					if( len )
					{
						j += (len-1);
						found = 1;
						break;
					}
				}
			}

			for( l=0; l < (sizeof(esc2)/sizeof(char *)) && !found; l++ )
			{
				if( !esc2[l] )
					continue;
				/*
				  Test both padded and unpadded version, just to
				  be safe. Most versions of tparm don't actually
				  seem to do anything these days.
				*/
				len = maxi( try_sequence( tparm(esc2[l]), &prompt[j] ),
					    try_sequence( esc2[l], &prompt[j] ));

				if( len )
				{
					j += (len-1);
					found = 1;
				}
			}

			if( !found )
			{
				if( prompt[j+1] == L'k' )
				{
					wchar_t *term_name = env_get( L"TERM" );
					if( term_name && wcsstr( term_name, L"screen" ) == term_name )
					{
						wchar_t *end;
						j+=2;
						found = 1;
						end = wcsstr( &prompt[j], L"\x1b\\" );
						if( end )
						{
							/*
							  You'd thing this should be
							  '(end-prompt)+2', in order to move j
							  past the end of the string, but there is
							  a 'j++' at the end of each lap, so j
							  should always point to the last menged
							  character, e.g. +1.
							*/
							j = (end-prompt)+1;
						}
						else
						{
							break;
						}
					}
				}
			}

		}
		else if( prompt[j] == L'\t' )
		{
			res = next_tab_stop( res );
		}
		else if( prompt[j] == L'\n' )
		{
			res = 0;
		}
		else
		{
			/*
			  Ordinary decent character. Just add width.
			*/
			res += wcwidth( prompt[j] );
		}
	}
	return res;
}
示例#8
0
/// Returns the number of characters in the escape code starting at 'code' (which should initially
/// contain \x1b).
size_t escape_code_length(const wchar_t *code) {
    assert(code != NULL);

    // The only escape codes we recognize start with \x1b.
    if (code[0] != L'\x1b') return 0;

    size_t resulting_length = 0;
    bool found = false;

    if (cur_term != NULL) {
        // Detect these terminfo color escapes with parameter value 0..7, all of which don't move
        // the cursor.
        char *const esc[] = {
            set_a_foreground, set_a_background, set_foreground, set_background,
        };

        for (size_t p = 0; p < sizeof esc / sizeof *esc && !found; p++) {
            if (!esc[p]) continue;

            for (size_t k = 0; k < 8; k++) {
                size_t len = try_sequence(tparm(esc[p], k), code);
                if (len) {
                    resulting_length = len;
                    found = true;
                    break;
                }
            }
        }
    }

    if (cur_term != NULL) {
        // Detect these semi-common terminfo escapes without any parameter values, all of which
        // don't move the cursor.
        char *const esc2[] = {enter_bold_mode,        exit_attribute_mode,   enter_underline_mode,
                              exit_underline_mode,    enter_standout_mode,   exit_standout_mode,
                              flash_screen,           enter_subscript_mode,  exit_subscript_mode,
                              enter_superscript_mode, exit_superscript_mode, enter_blink_mode,
                              enter_italics_mode,     exit_italics_mode,     enter_reverse_mode,
                              enter_shadow_mode,      exit_shadow_mode,      enter_standout_mode,
                              exit_standout_mode,     enter_secure_mode};

        for (size_t p = 0; p < sizeof esc2 / sizeof *esc2 && !found; p++) {
            if (!esc2[p]) continue;
            // Test both padded and unpadded version, just to be safe. Most versions of tparm don't
            // actually seem to do anything these days.
            size_t len = maxi(try_sequence(tparm(esc2[p]), code), try_sequence(esc2[p], code));
            if (len) {
                resulting_length = len;
                found = true;
            }
        }
    }

    if (!found) found = is_screen_name_escape_seq(code, &resulting_length);
    if (!found) found = is_iterm2_escape_seq(code, &resulting_length);
    if (!found) found = is_single_byte_escape_seq(code, &resulting_length);
    if (!found) found = is_csi_style_escape_seq(code, &resulting_length);
    if (!found) found = is_two_byte_escape_seq(code, &resulting_length);

    return resulting_length;
}
示例#9
0
/* Returns the number of characters in the escape code starting at 'code' (which should initially contain \x1b) */
size_t escape_code_length(const wchar_t *code)
{
    assert(code != NULL);

    /* The only escape codes we recognize start with \x1b */
    if (code[0] != L'\x1b')
        return 0;

    size_t resulting_length = 0;
    bool found = false;

    if (cur_term != NULL)
    {
        /*
         Detect these terminfo color escapes with parameter
         value 0..7, all of which don't move the cursor
         */
        char * const esc[] =
        {
            set_a_foreground,
            set_a_background,
            set_foreground,
            set_background,
        };

        for (size_t p=0; p < sizeof esc / sizeof *esc && !found; p++)
        {
            if (!esc[p])
                continue;

            for (size_t k=0; k<8; k++)
            {
                size_t len = try_sequence(tparm(esc[p],k), code);
                if (len)
                {
                    resulting_length = len;
                    found = true;
                    break;
                }
            }
        }
    }

    if (cur_term != NULL)
    {
        /*
         Detect these semi-common terminfo escapes without any
         parameter values, all of which don't move the cursor
         */
        char * const esc2[] =
        {
            enter_bold_mode,
            exit_attribute_mode,
            enter_underline_mode,
            exit_underline_mode,
            enter_standout_mode,
            exit_standout_mode,
            flash_screen,
            enter_subscript_mode,
            exit_subscript_mode,
            enter_superscript_mode,
            exit_superscript_mode,
            enter_blink_mode,
            enter_italics_mode,
            exit_italics_mode,
            enter_reverse_mode,
            enter_shadow_mode,
            exit_shadow_mode,
            enter_standout_mode,
            exit_standout_mode,
            enter_secure_mode
        };



        for (size_t p=0; p < sizeof esc2 / sizeof *esc2 && !found; p++)
        {
            if (!esc2[p])
                continue;
            /*
             Test both padded and unpadded version, just to
             be safe. Most versions of tparm don't actually
             seem to do anything these days.
             */
            size_t len = maxi(try_sequence(tparm(esc2[p]), code), try_sequence(esc2[p], code));
            if (len)
            {
                resulting_length = len;
                found = true;
            }
        }
    }

    if (!found)
    {
        if (code[1] == L'k')
        {
            /* This looks like the escape sequence for setting a screen name */
            const env_var_t term_name = env_get_string(L"TERM");
            if (!term_name.missing() && string_prefixes_string(L"screen", term_name))
            {
                const wchar_t * const screen_name_end_sentinel = L"\x1b\\";
                const wchar_t *screen_name_end = wcsstr(&code[2], screen_name_end_sentinel);
                if (screen_name_end != NULL)
                {
                    const wchar_t *escape_sequence_end = screen_name_end + wcslen(screen_name_end_sentinel);
                    resulting_length = escape_sequence_end - code;
                }
                else
                {
                    /* Consider just <esc>k to be the code */
                    resulting_length = 2;
                }
                found = true;
            }
        }
    }

    if (! found)
    {
        /* Generic VT100 one byte sequence: CSI followed by something in the range @ through _ */
        if (code[1] == L'[' && (code[2] >= L'@' && code[2] <= L'_'))
        {
            resulting_length = 3;
            found = true;
        }
    }

    if (! found)
    {
        /* Generic VT100 CSI-style sequence. <esc>, followed by zero or more ASCII characters NOT in the range [@,_], followed by one character in that range */
        if (code[1] == L'[')
        {
            // Start at 2 to skip over <esc>[
            size_t cursor = 2;
            for (; code[cursor] != L'\0'; cursor++)
            {
                /* Consume a sequence of ASCII characters not in the range [@, ~] */
                wchar_t c = code[cursor];

                /* If we're not in ASCII, just stop */
                if (c > 127)
                    break;

                /* If we're the end character, then consume it and then stop */
                if (c >= L'@' && c <= L'~')
                {
                    cursor++;
                    break;
                }
            }
            /* curs now indexes just beyond the end of the sequence (or at the terminating zero) */
            found = true;
            resulting_length = cursor;
        }
    }

    if (! found)
    {
        /* Generic VT100 two byte sequence: <esc> followed by something in the range @ through _ */
        if (code[1] >= L'@' && code[1] <= L'_')
        {
            resulting_length = 2;
            found = true;
        }
    }

    return resulting_length;
}
示例#10
0
/**
   Calculate layout information for the given prompt. Does some clever magic
   to detect common escape sequences that may be embeded in a prompt,
   such as color codes.
*/
static prompt_layout_t calc_prompt_layout(const wchar_t *prompt)
{
    size_t current_line_width = 0;
    size_t j, k;

    prompt_layout_t prompt_layout = {};
    prompt_layout.line_count = 1;

    for (j=0; prompt[j]; j++)
    {
        if (prompt[j] == L'\x1b')
        {
            /*
             This is the start of an escape code. Try to guess its width.
             */
            size_t p;
            int len=0;
            bool found = false;

            /*
             Detect these terminfo color escapes with parameter
             value 0..7, all of which don't move the cursor
             */
            char * const esc[] =
            {
                set_a_foreground,
                set_a_background,
                set_foreground,
                set_background,
            }
            ;

            /*
             Detect these semi-common terminfo escapes without any
             parameter values, all of which don't move the cursor
             */
            char * const esc2[] =
            {
                enter_bold_mode,
                exit_attribute_mode,
                enter_underline_mode,
                exit_underline_mode,
                enter_standout_mode,
                exit_standout_mode,
                flash_screen,
                enter_subscript_mode,
                exit_subscript_mode,
                enter_superscript_mode,
                exit_superscript_mode,
                enter_blink_mode,
                enter_italics_mode,
                exit_italics_mode,
                enter_reverse_mode,
                enter_shadow_mode,
                exit_shadow_mode,
                enter_standout_mode,
                exit_standout_mode,
                enter_secure_mode
            }
            ;

            for (p=0; p < sizeof esc / sizeof *esc && !found; p++)
            {
                if (!esc[p])
                    continue;

                for (k=0; k<8; k++)
                {
                    len = try_sequence(tparm(esc[p],k), &prompt[j]);
                    if (len)
                    {
                        j += (len-1);
                        found = true;
                        break;
                    }
                }
            }

            /* PCA for term256 support, let's just detect the escape codes directly */
            if (! found)
            {
                len = is_term256_escape(&prompt[j]);
                if (len)
                {
                    j += (len - 1);
                    found = true;
                }
            }


            for (p=0; p < (sizeof(esc2)/sizeof(char *)) && !found; p++)
            {
                if (!esc2[p])
                    continue;
                /*
                 Test both padded and unpadded version, just to
                 be safe. Most versions of tparm don't actually
                 seem to do anything these days.
                 */
                len = maxi(try_sequence(tparm(esc2[p]), &prompt[j]),
                           try_sequence(esc2[p], &prompt[j]));

                if (len)
                {
                    j += (len-1);
                    found = true;
                }
            }

            if (!found)
            {
                if (prompt[j+1] == L'k')
                {
                    const env_var_t term_name = env_get_string(L"TERM");
                    if (!term_name.missing() && wcsstr(term_name.c_str(), L"screen") == term_name)
                    {
                        const wchar_t *end;
                        j+=2;
                        found = true;
                        end = wcsstr(&prompt[j], L"\x1b\\");
                        if (end)
                        {
                            /*
                             You'd thing this should be
                             '(end-prompt)+2', in order to move j
                             past the end of the string, but there is
                             a 'j++' at the end of each lap, so j
                             should always point to the last menged
                             character, e.g. +1.
                             */
                            j = (end-prompt)+1;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }

        }
        else if (prompt[j] == L'\t')
        {
            current_line_width = next_tab_stop(current_line_width);
        }
        else if (prompt[j] == L'\n' || prompt[j] == L'\f')
        {
            /* PCA: At least one prompt uses \f\r as a newline. It's unclear to me what this is meant to do, but terminals seem to treat it as a newline so we do the same. */
            current_line_width = 0;
            prompt_layout.line_count += 1;
        }
        else if (prompt[j] == L'\r')
        {
            current_line_width = 0;
        }
        else
        {
            /* Ordinary decent character. Just add width. This returns -1 for a control character - don't add that. */
            current_line_width += fish_wcwidth_min_0(prompt[j]);
            prompt_layout.max_line_width = maxi(prompt_layout.max_line_width, current_line_width);
        }
    }
    prompt_layout.last_line_width = current_line_width;
    return prompt_layout;
}