Хрестоматия по программированию на Си в Unix
ch = EOF;
do
{
if( alarmed )
break;
ch = nextc();
if (ch != EOF) /* getc() returns EOF on error, too */
*(bufp++) = ch;
if (alarmed)
break;
while (ptr != (struct try *)NULL &&
(ch == EOF || unify(CRNL(ptr->ch)) != unify(CRNL(ch)) ))
ptr = ptr->sibling;
if (ptr != (struct try *)NULL)
{
if (ptr->value != 0)
{
alarm(0);
signal(SIGALRM, oldsig);
return(ptr->value);
}
else
{
ptr = ptr->child;
alarm(1);
}
}
} while (ptr != (struct try *)NULL);
alarm(0);
signal(SIGALRM, oldsig);
if (ch == EOF && bufp == buffer)
return ch;
А. Богатырев, 1992-95 - 379 - Си в UNIX
while (--bufp > buffer)
putback(*bufp);
return(*bufp & 0377);
}
void _sigalrm(int n)
{
alarmed = TRUE;
longjmp(jbuf, 1);
}
А. Богатырев, 1992-95 - 380 - Си в UNIX
/* ==================================================================== */
#else /* XENIX or USG */
/* Для семейства SYSTEM V */
static BOOLEAN alarmed;
int kgetch()
{
register struct try *ptr;
int ch;
char buffer[10]; /* Assume no sequences longer than 10 */
register char *bufp = buffer;
void (*oldsig)();
void _sigalrm();
ptr = _keytry;
oldsig = signal(SIGALRM, _sigalrm);
alarmed = FALSE;
do
{
ch = nextc();
if (ch != EOF) /* getc() returns EOF on error, too */
*(bufp++) = ch;
if (alarmed)
break;
while (ptr != (struct try *)NULL &&
(ch == EOF || unify(CRNL(ptr->ch)) != unify(CRNL(ch)) ))
ptr = ptr->sibling;
if (ptr != (struct try *)NULL)
{
if (ptr->value != 0)
{
alarm(0);
signal(SIGALRM, oldsig);
return(ptr->value);
}
else
{
ptr = ptr->child;
alarm(1);
}
}
} while (ptr != (struct try *)NULL);
alarm(0);
signal(SIGALRM, oldsig);
if (ch == EOF && bufp == buffer)
return ch;
while (--bufp > buffer)
putback(*bufp);
return(*bufp & 0377);
}
А. Богатырев, 1992-95 - 381 - Си в UNIX
void _sigalrm(int n)
{
alarmed = TRUE;
signal(SIGALRM, _sigalrm);
}
#endif /*XENIX*/
/* ==================================================================== */
/*
** init_keytry()
** Построение дерева разбора последовательностей символов.
**
*/
void init_keytry()
{
_keytry = (struct try *) NULL;
add_to_try(key_backspace, KEY_BACKSPACE);
add_to_try("\b", KEY_BACKSPACE);
add_to_try("\177", KEY_BACKSPACE);
add_to_try(key_backtab, KEY_BACKTAB);
add_to_try(key_dc, KEY_DC);
add_to_try(key_dl, KEY_DL);
add_to_try(key_down, KEY_DOWN);
add_to_try(key_f1, KEY_F(1));
add_to_try(key_f2, KEY_F(2));
add_to_try(key_f3, KEY_F(3));
add_to_try(key_f4, KEY_F(4));
add_to_try(key_f5, KEY_F(5));
add_to_try(key_f6, KEY_F(6));
add_to_try(key_f7, KEY_F(7));
add_to_try(key_f8, KEY_F(8));
add_to_try(key_f9, KEY_F(9));
add_to_try(key_f10, KEY_F(10));
add_to_try(key_f11, KEY_F(11));
add_to_try(key_f12, KEY_F(12));
add_to_try(key_home, KEY_HOME);
add_to_try(key_ic, KEY_IC);
add_to_try(key_il, KEY_IL);
add_to_try(key_left, KEY_LEFT);
add_to_try(key_npage, KEY_PGDN);
add_to_try(key_ppage, KEY_PGUP);
add_to_try(key_right, KEY_RIGHT);
add_to_try(key_up, KEY_UP);
add_to_try(key_end, KEY_END);
}
А. Богатырев, 1992-95 - 382 - Си в UNIX
void add_to_try(char *str, short code)
{
static BOOLEAN out_of_memory = FALSE;
struct try *ptr, *savedptr;
if (str == NULL || out_of_memory)
return;
if (_keytry != (struct try *) NULL)
{
ptr = _keytry;
for (;;)
{
while (ptr->ch != *str && ptr->sibling != (struct try *)NULL)
ptr = ptr->sibling;
if (ptr->ch == *str)
{
if (*(++str))
{
if (ptr->child != (struct try *)NULL)
ptr = ptr->child;
else
break;
}
else
{
ptr->value = code;
return;
}
}
else
{
if ((ptr->sibling =
(struct try *) malloc(sizeof *ptr)) == (struct try *)NULL)
{
out_of_memory = TRUE;
return;
}
savedptr = ptr = ptr->sibling;
ptr->child = ptr->sibling = (struct try *)NULL;
ptr->ch = *str++;
ptr->value = 0;
break;
}
} /* end for (;;) */
}
else /* _keytry == NULL :: First sequence to be added */
{
savedptr = ptr = _keytry = (struct try *) malloc(sizeof *ptr);
if (ptr == (struct try *) NULL)
{
out_of_memory = TRUE;
return;
}
ptr->child = ptr->sibling = (struct try *) NULL;
А. Богатырев, 1992-95 - 383 - Си в UNIX
ptr->ch = *(str++);
ptr->value = 0;
}
/* at this point, we are adding to the try. ptr->child == NULL */
while (*str)
{
ptr->child = (struct try *) malloc(sizeof *ptr);
ptr = ptr->child;
if (ptr == (struct try *)NULL)
{
out_of_memory = TRUE;
ptr = savedptr;
while (ptr != (struct try *)NULL)
{
savedptr = ptr->child;
free(ptr);
ptr = savedptr;
}
return;
}
ptr->child = ptr->sibling = (struct try *)NULL;
ptr->ch = *(str++);
ptr->value = 0;
}
ptr->value = code;
return;
}
/* Включение альтернативного режима клавиатуры */
void keypad_on(){
if( keypadok ) return;
keypadok = TRUE;
if( keypad_xmit ) _puts( keypad_xmit );
}
/* Включение стандартного режима клавиатуры */
void keypad_off(){
if( !keypadok ) return;
keypadok = FALSE;
if( keypad_local ) _puts( keypad_local );
}
А. Богатырев, 1992-95 - 384 - Си в UNIX
/* Тестовая функция */
int dotest()
{
struct termios saved_modes;
int c;
char *s;
char keyname[20];
if( tcgetattr(INPUT_CHANNEL, &saved_modes) < 0 ){
err: keyboard_access_denied();
}
if( tcsetattr(INPUT_CHANNEL, TCSADRAIN, &new_modes) < 0 )
goto err;
keyreset();
for(;;){
c = getch();
switch(c){
case KEY_DOWN: s = "K_DOWN" ; break;
case KEY_UP: s = "K_UP" ; break;
case KEY_LEFT: s = "K_LEFT" ; break;
case KEY_RIGHT: s = "K_RIGHT" ; break;
case KEY_PGDN: s = "K_PGDN" ; break;
case KEY_PGUP: s = "K_PGUP" ; break;
case KEY_HOME: s = "K_HOME" ; break;
case KEY_END: s = "K_END" ; break;
case KEY_BACKSPACE: s = "K_BS" ; break;
case '\t': s = "K_TAB" ; break;
case KEY_BACKTAB: s = "K_BTAB" ; break;
case KEY_DC: s = "K_DEL" ; break;
case KEY_IC: s = "K_INS" ; break;
case KEY_DL: s = "K_DL" ; break;
case KEY_IL: s = "K_IL" ; break;
case KEY_F(1): s = "K_F1" ; break;
case KEY_F(2): s = "K_F2" ; break;
case KEY_F(3): s = "K_F3" ; break;
case KEY_F(4): s = "K_F4" ; break;
case KEY_F(5): s = "K_F5" ; break;
case KEY_F(6): s = "K_F6" ; break;
case KEY_F(7): s = "K_F7" ; break;
case KEY_F(8): s = "K_F8" ; break;
case KEY_F(9): s = "K_F9" ; break;
case KEY_F(10): s = "K_F10" ; break;
case KEY_F(11): s = "K_F11" ; break;
case KEY_F(12): s = "K_F12" ; break;
case ESC: s = "ESC" ; break;
case EOF: s = "K_EOF" ; break;
case '\r': s = "K_RETURN"; break;
case '\n': s = "K_ENTER" ; break;
default:
s = keyname;
if( c >= 0400 ){
sprintf(keyname, "K_F%d", c - KEY_F(0));
} else if( iscntrl(c)){
sprintf(keyname, "CTRL(%c)", c + 'A' - 1);
} else {
sprintf(keyname, "%c", c );
А. Богатырев, 1992-95 - 385 - Си в UNIX