📄 char_io.c
字号:
} while (1) { /* A bit tricky. This below makes use of the equivalence: (A >= B && A <= C) <=> ((A - B) <= (C - B)) when C > B and A is unsigned. */ unsigned int digit; digit = tolower (*ptr) - '0'; if (digit > 9) { digit -= 'a' - '0'; if (mult == 10 || digit > 5) break; digit += 10; } found = 1; /* we do not check for hex or negative */ if (mult == 10 && ! negative) if ((unsigned)myint > (((unsigned)(MAXINT - digit)) / (unsigned)mult)) { errnum = ERR_NUMBER_OVERFLOW; return 0; } myint = ((unsigned)myint * (unsigned)mult) + digit; ptr++; } if (!found) { errnum = ERR_NUMBER_PARSING; return 0; } *str_ptr = ptr; *myint_ptr = negative ? -myint : myint; return 1;}#endif /* STAGE1_5 *///#if !defined(STAGE1_5) || defined(FSYS_FAT) || defined(FSYS_NTFS)intgrub_tolower (int c){ if (c >= 'A' && c <= 'Z') return (c + ('a' - 'A')); return c;}//#endif /* ! STAGE1_5 || FSYS_FAT || FSYS_NTFS */intgrub_isspace (int c){ switch (c) { case ' ': case '\t': case '\r': case '\n': return 1; default: break; } return 0;}#if !defined(STAGE1_5) || defined(FSYS_ISO9660)intgrub_memcmp (const char *s1, const char *s2, int n){ while (n) { if (*s1 < *s2) return -1; else if (*s1 > *s2) return 1; s1++; s2++; n--; } return 0;}#endif /* ! STAGE1_5 || FSYS_ISO9660 */#ifndef STAGE1_5intgrub_strncat (char *s1, const char *s2, int n){ int i = -1; while (++i < n && s1[i] != 0); while (i < n && (s1[i++] = *(s2++)) != 0); s1[n - 1] = 0; if (i >= n) return 0; s1[i] = 0; return 1;}#endif /* ! STAGE1_5 *//* XXX: This below is an evil hack. Certainly, we should change the strategy to determine what should be defined and what shouldn't be defined for each image. For example, it would be better to create a static library supporting minimal standard C functions and link each image with the library. Complicated things should be left to computer, definitely. -okuji */#if !defined(STAGE1_5) || defined(FSYS_VSTAFS)intgrub_strcmp (const char *s1, const char *s2){ while (*s1 || *s2) { if (*s1 < *s2) return -1; else if (*s1 > *s2) return 1; s1 ++; s2 ++; } return 0;}#endif /* ! STAGE1_5 || FSYS_VSTAFS */#ifndef STAGE1_5/* Wait for a keypress and return its code. */intgetkey (void){ return current_term->getkey ();}/* Check if a key code is available. */intcheckkey (void){ return current_term->checkkey ();}#endif /* ! STAGE1_5 *//* Display an ASCII character. */voidgrub_putchar (int c){ /* if it is a Line Feed, we insert a Carriage Return. */#ifdef STAGE1_5 /* In Stage 1.5, only the normal console is supported. */ if (c == '\n') //grub_putchar ('\r'); /* recursive, bad!! */ console_putchar ('\r'); console_putchar (c); #else /* ! STAGE1_5 */ if (c == '\t' && current_term->getxy) { c = 8 - ((current_term->getxy () >> 8) & 3); while (c--) //grub_putchar (' '); /* recursive, bad!! */ current_term->putchar (' '); return; } if (c == '\n') { current_term->putchar ('\r'); /* Internal `more'-like feature. */ if (count_lines >= 0) { count_lines++; if (count_lines >= max_lines - 2) { /* It's important to disable the feature temporarily, because the following grub_printf call will print newlines. */ count_lines = -1; //grub_printf("\n"); /* recursive, bad!! */ current_term->putchar ('\n'); if (! (current_term->flags & TERM_DUMB)) { if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); //grub_printf ("[Hit return to continue]"); /* recursive, bad!! */ c = (int)"[Hit Q to quit, any other key to continue]"; while (*(char *)c) current_term->putchar (*(char *)c++); if ((getkey () & 0xDF) == 0x51) /* 0x51 == 'Q' */ quit_print = 1;// do// {// tmp = ASCII_CHAR (getkey ());// if ((tmp & 0xdf) == 0x51) /* Q */// {// quit_print = 1;// break;// }// }// while (tmp != '\n' && tmp != '\r'); //grub_printf ("\r \r"); /* recursive, bad!! */ c = (int)"\r \r"; while (*(char *)c) current_term->putchar (*(char *)c++); if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_NORMAL); } /* Restart to count lines. */ count_lines = 0; return; } } }// if (! (current_term->flags & TERM_DUMB))// while (checkkey () != -1)// {// if ((getkey () & 0xdf) == 'Q')// {// quit_print = 1;// break;// }// } current_term->putchar (c); #endif /* ! STAGE1_5 */}#ifndef STAGE1_5voidgotoxy (int x, int y){ current_term->gotoxy (x, y);}intgetxy (void){ return current_term->getxy ();}voidcls (void){ /* If the terminal is dumb, there is no way to clean the terminal. */ if (current_term->flags & TERM_DUMB) grub_putchar ('\n'); else current_term->cls ();}intsetcursor (int on){ if (current_term->setcursor) return current_term->setcursor (on); return 1;}#endif /* ! STAGE1_5 */intsubstring (const char *s1, const char *s2, int case_insensitive){ char ch1, ch2; for (;;) { ch1 = *(s1++); ch2 = *(s2++); if (case_insensitive) { ch1 = tolower(ch1); ch2 = tolower(ch2); } if (! ch1) /* S1 is a substring of S2, or they match exactly */ return ch2 ? -1 : 0; if (ch1 != ch2) return 1; /* S1 isn't a substring of S2 */ }}#ifndef STAGE1_5/* Terminate the string STR with NUL. */intnul_terminate (char *str){ int ch; // while (*str && ! grub_isspace (*str))// str++; while ((ch = *str) && ! grub_isspace (ch)) { if (ch == '\\') { str++; if (! (ch = *str)) break; } str++; }// ch = *str; *str = 0; return ch;}char *grub_strstr (const char *s1, const char *s2){ while (*s1) { const char *ptr, *tmp; ptr = s1; tmp = s2; while (*tmp && *ptr == *tmp) ptr++, tmp++; if (tmp > s2 && ! *tmp) return (char *) s1; s1++; } return 0;}#endif /* ! STAGE1_5 *///#if !defined(STAGE1_5) || defined(FSYS_NTFS)intgrub_strlen (const char *str){ int len = 0; while (*str++) len++; return len;}//#endif /* ! STAGE1_5 || FSYS_NTFS */intmemcheck (unsigned long addr, unsigned long len){#ifdef GRUB_UTIL#if 0 auto unsigned long start_addr (void); auto unsigned long end_addr (void); auto unsigned long start_addr (void) { unsigned long ret;# if defined(HAVE_START_SYMBOL) asm volatile ("movl $start, %0" : "=a" (ret));# elif defined(HAVE_USCORE_START_SYMBOL) asm volatile ("movl $_start, %0" : "=a" (ret));# endif return ret; } auto unsigned long end_addr (void) { unsigned long ret;# if defined(HAVE_END_SYMBOL) asm volatile ("movl $end, %0" : "=a" (ret));# elif defined(HAVE_USCORE_END_SYMBOL) asm volatile ("movl $_end, %0" : "=a" (ret));# endif return ret; } errnum = 0;// if (/*! addr ||*/ (start_addr () <= addr && end_addr () > addr + len))// if (! addr || (start_addr () <= addr && addr < end_addr ()) || (start_addr () < addr + len && addr + len <= end_addr ()))// errnum = ERR_WONT_FIT;// return ! errnum; if (! addr) { errnum = ERR_WONT_FIT; return ! errnum; } if ((start_addr () <= addr && addr < end_addr ()) || (start_addr () < addr + len && addr + len <= end_addr ())) return ! errnum;#endif#endif /* GRUB_UTIL */ errnum = 0; if (! addr /* (addr < (unsigned long)(RAW_ADDR (0x1000))) */ /* || (addr < (unsigned long)(RAW_ADDR (0x100000)) && (unsigned long)(RAW_ADDR (saved_mem_lower * 1024)) < (addr + len)) */ || (addr >= (unsigned long)(RAW_ADDR (0x100000)) && (unsigned long)(RAW_ADDR (saved_mem_upper * 1024)) < ((addr - 0x100000) + len))) errnum = ERR_WONT_FIT; return ! errnum;}#if 0voidgrub_memcpy(void *dest, const void *src, int len){ int i; register char *d = (char*)dest, *s = (char*)src; for (i = 0; i < len; i++) d[i] = s[i];}#endif/* struct copy needs the memcpy function *//* #undef memcpy */#if 1void * grub_memcpy(void * to, const void * from, unsigned int n){ /* This assembly code is stolen from * linux-2.4.22/include/asm-i386/string.h * It assumes ds=es=data space, this should be normal. */ int d0, d1, d2; __asm__ __volatile__( "rep ; movsl\n\t" "testb $2,%b4\n\t" "je 1f\n\t" "movsw\n" "1:\ttestb $1,%b4\n\t" "je 2f\n\t" "movsb\n" "2:" : "=&c" (d0), "=&D" (d1), "=&S" (d2) :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) : "memory"); return to;}#else/* just in case the assembly version of grub_memcpy does not work. */void * grub_memcpy(void * to, const void * from, unsigned int n){ char *d = (char *)to, *s = (char *)from; while (n--) *d++ = *s++; return to;}#endifvoid *grub_memmove (void *to, const void *from, int len){ if (memcheck ((int) to, len)) { /* This assembly code is stolen from linux-2.2.2/include/asm-i386/string.h. This is not very fast but compact. */ int d0, d1, d2; if (to < from) { asm volatile ("cld\n\t" "rep\n\t" "movsb" : "=&c" (d0), "=&S" (d1), "=&D" (d2) : "0" (len),"1" (from),"2" (to) : "memory"); } else { asm volatile ("std\n\t" "rep\n\t" "movsb\n\t" "cld" : "=&c" (d0), "=&S" (d1), "=&D" (d2) : "0" (len), "1" (len - 1 + (const char *) from), "2" (len - 1 + (char *) to) : "memory"); } } return errnum ? NULL : to;}void *grub_memset (void *start, int c, int len){ char *p = start; if (memcheck ((int) start, len)) { while (len -- > 0) *p ++ = c; } return errnum ? NULL : start;}#ifndef STAGE1_5char *grub_strcpy (char *dest, const char *src){ grub_memmove (dest, src, grub_strlen (src) + 1); return dest;}#endif /* ! STAGE1_5 */#ifndef GRUB_UTIL# undef memcpy/* GCC emits references to memcpy() for struct copies etc. */void *memcpy (void *dest, const void *src, int n) __attribute__ ((alias ("grub_memmove")));#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -