(linenum→info "unix/slp.c:2238")

anthy/9100e/src-util/agent.c

    1: /* 
    2:  * 標準入出力でコマンドを受けたり,変換結果を送るなどの通信を
    3:  * アプリケーション(おもにEmacs)と行うことにより,アプリケーションに
    4:  * Anthyによる入力機能を容易かつ安全に追加できる.
    5:  *
    6:  * Funded by IPA未踏ソフトウェア創造事業 2002 2/26
    7:  * Copyright (C) 2001-2002 UGAWA Tomoharu
    8:  * Copyright (C) 2002-2004 TABATA Yusuke,
    9:  */
   10: /*
   11:  * *マルチコンテキストの扱いを決めかねている
   12:  * *入出力にstdioを使うかfdを使うか決めかねている
   13:  */
   14: 
   15: #include <sys/time.h>
   16: #include <sys/types.h>
   17: #include <unistd.h>
   18: #include <string.h>
   19: #include <stdio.h>
   20: #include <stdlib.h>
   21: #include <ctype.h>
   22: #include <assert.h>
   23: 
   24: #include <anthy/anthy.h>
   25: #include <anthy/input.h>
   26: 
   27: #include "rkconv.h"
   28: 
   29: #include <config.h>
   30: 
   31: extern void egg_main(void);
   32: 
   33: /* 何回次候補を押すと候補の列挙を一覧モードに切替えるか? */
   34: #define DEFAULT_ENUM_CAND_LIMIT 3
   35: 
   36: 
   37: /* キーに対応する定数 */
   38: #define KEY_SHIFT   0x00010000
   39: #define KEY_CTRL    0x00020000
   40: #define KEY_ALT     0x00040000
   41: 
   42: #define KEY_SPACE   ' '
   43: #define KEY_OPAR    '('
   44: #define KEY_CPAR    ')'
   45: 
   46: #define KEY_ENTER     0x00000100
   47: #define KEY_DELETE    0x00000200
   48: #define KEY_LEFT      0x00000300
   49: #define KEY_RIGHT     0x00000400
   50: #define KEY_ESC       0x00000500
   51: #define KEY_BACKSPACE 0x00000600
   52: #define KEY_UP        0x00000700
   53: #define KEY_DOWN      0x00000800
   54: 
   55: #define KEY_CTRL_A      (KEY_CTRL  | 'A')
   56: #define KEY_CTRL_E      (KEY_CTRL  | 'E')
   57: #define KEY_CTRL_J      (KEY_CTRL  | 'J')
   58: #define KEY_CTRL_K      (KEY_CTRL  | 'K')
   59: #define KEY_CTRL_H      (KEY_CTRL  | 'H')
   60: #define KEY_CTRL_D      (KEY_CTRL  | 'D')
   61: #define KEY_SHIFT_LEFT  (KEY_SHIFT | KEY_LEFT)
   62: #define KEY_SHIFT_RIGHT (KEY_SHIFT | KEY_RIGHT)
   63: 
   64: #define BUF_GROW_SIZE 4096
   65: 
   66: #define MAX(a,b) ((a) > (b) ? (a) : (b))
   67: 
   68: 
   69: /*
   70:  * コマンドにはキーが押されたことを示す普通のコマンドと
   71:  * 高水準な命令のハイレベルコマンドがある.
   72:  */
   73: enum {
   74:   /* ハイレベルコマンド */
   75:   CMDH_IGNORE_ICTXT, CMDH_GETPREEDIT, CMDH_SELECT_CONTEXT,
   76:   CMDH_RELEASE_CONTEXT, CMDH_MAP_EDIT, CMDH_MAP_SELECT,
   77:   CMDH_GET_CANDIDATE, CMDH_SELECT_CANDIDATE, CMDH_CHANGE_TOGGLE,
   78:   CMDH_MAP_CLEAR, CMDH_SET_BREAK_INTO_ROMAN,
   79:   CMDH_SET_PREEDIT_MODE, CMDH_PRINT_CONTEXT,
   80: 
   81:   /* キーコマンド */
   82:   CMD_SPACE = 1000,
   83:   CMD_ENTER,
   84:   CMD_BACKSPACE, 
   85:   CMD_DELETE,
   86:   CMD_UP,
   87:   CMD_ESC,
   88:   CMD_SHIFTARROW,
   89:   CMD_ARROW,
   90:   CMD_KEY,
   91:   CMD_GOBOL,
   92:   CMD_GOEOL,
   93:   CMD_CUT
   94: };
   95: 
   96: struct high_level_command_type {
   97:   const char* name;
   98:   int cmd;
   99:   int n_arg;
  100:   int opt_arg;
  101: } high_level_command_type[] = {
  102:   /* コンテキストの情報を表示する */
  103:   {"PRINT_CONTEXT",  CMDH_PRINT_CONTEXT,  0, 0},
  104:   /* トグルに使うキーを変更する */
  105:   {"CHANGE_TOGGLE",  CMDH_CHANGE_TOGGLE,  1, 0},
  106:   /* コンテキストを選択する */
  107:   {"SELECT_CONTEXT", CMDH_SELECT_CONTEXT, 1, 0},
  108:   {"RELEASE_CONTEXT", CMDH_RELEASE_CONTEXT, 0, 0},
  109:   {"MAP_CLEAR", CMDH_MAP_CLEAR, 1, 0},
  110:   {"MAP_EDIT",       CMDH_MAP_EDIT,       3, 0},
  111:   {"MAP_SELECT",     CMDH_MAP_SELECT,     1, 0},
  112:   {"GET_CANDIDATE",  CMDH_GET_CANDIDATE,  1, 0},
  113:   {"SELECT_CANDIDATE", CMDH_SELECT_CANDIDATE, 1, 0},
  114:   /* バックスペースでローマ字に戻る */
  115:   {"BREAK_INTO_ROMAN", CMDH_SET_BREAK_INTO_ROMAN, 1, 0},
  116:   /**/
  117:   {"SET_PREEDIT_MODE", CMDH_SET_PREEDIT_MODE, 1, 0},
  118:   /**/
  119:   {NULL, -1, 0, 0}
  120: };
Permalink to this note guest: anthy/9100e/src-util/agent.c:96-120 on Fri Feb 29 19:14:21 +0900 2008

ハイレベルコマンドの文字列定義

121: 122: struct command { 123: int cmd; 124: char** arg; 125: int n_arg; 126: struct command* next; 127: }; 128: 129: struct connection { 130: char* rbuf; 131: int n_rbuf; 132: int s_rbuf; 133: int rfd; 134: 135: char* wbuf; 136: int n_wbuf; 137: int s_wbuf; 138: int wfd; 139: }; 140: 141: static void send_error(void); 142: 143: static struct connection* conn; 144: static struct anthy_input_config* config; 145: static struct command* command_queue; 146: static int daemon_sock = -1; 147: static int anonymous; 148: static int egg; 149: static char *personality; 150: int use_utf8; 151: 152: static char * 153: encode_command_arg(char *a) 154: { 155: int i, j, len; 156: char *s; 157: 158: len = strlen(a); 159: s = malloc(len + 1); 160: for(i = 0,j = 0; i < len; i++) { 161: if (a[i] != '\\') { 162: s[j] = a[i]; 163: j++; 164: continue; 165: } 166: /* バックスラッシュ */ 167: i++; 168: switch (a[i]) { 169: case 0: 170: case '\\': 171: s[j] = '\\'; 172: j++; 173: break; 174: case '\"': 175: s[j] = '\"'; 176: j++; 177: break; 178: case 'X': 179: { 180: char buf[5]; 181: unsigned char *p; 182: int num; 183: /* ToBeDone エラーチェック */ 184: strncpy(buf, &a[i+1], 4); 185: i+= 5; 186: sscanf(buf, "%x", (unsigned int *)&num); 187: p = (unsigned char *)buf; 188: p[0] = num & 255; 189: p[1] = num >> 8; 190: j += sprintf(&s[j], "%c%c", buf[1] , buf[0]); 191: } 192: break; 193: } 194: } 195: s[j] = 0; 196: 197: return s; 198: } 199: 200: static int 201: ensure_buffer(char** buf, int* size, int to_size) 202: { 203: if (*size < to_size) { 204: *buf = (char*) realloc(*buf, to_size); 205: if (*buf == NULL) { 206: return -1; 207: } 208: *size = to_size; 209: } 210: return 0; 211: } 212: 213: static void 214: kill_connection(struct connection* conn) 215: { 216: (void) conn; 217: exit(0); 218: } 219: 220: static struct command * 221: make_command0(int no) 222: { 223: struct command* cmd; 224: 225: cmd = (struct command*) malloc(sizeof(struct command)); 226: cmd->cmd = no; 227: cmd->n_arg = 0; 228: cmd->arg = NULL; 229: cmd->next = NULL; 230: 231: return cmd; 232: } 233: 234: static struct command * 235: make_command1(int no, const char* arg1) 236: { 237: struct command* cmd; 238: 239: cmd = (struct command*) malloc(sizeof(struct command)); 240: cmd->cmd = no; 241: cmd->n_arg = 1; 242: cmd->arg = (char**) malloc(sizeof(char*) * 1); 243: cmd->arg[0] = strdup(arg1); 244: cmd->next = NULL; 245: 246: return cmd; 247: } 248: 249: static struct key_name_table { 250: const char* name; 251: int code; 252: int is_modifier; 253: } key_name_table[] = { 254: {"shift", KEY_SHIFT, 1}, 255: {"ctrl", KEY_CTRL, 1}, 256: {"alt", KEY_ALT, 1}, 257: 258: {"space", KEY_SPACE, 0}, 259: {"opar", KEY_OPAR, 0}, 260: {"cpar", KEY_CPAR, 0}, 261: {"enter", KEY_ENTER, 0}, 262: {"esc", KEY_ESC, 0}, 263: {"backspace", KEY_BACKSPACE, 0}, 264: {"delete", KEY_DELETE, 0}, 265: {"left", KEY_LEFT, 0}, 266: {"right", KEY_RIGHT, 0}, 267: {"up", KEY_UP, 0}, 268: 269: {NULL, 0, 0} 270: }; 271: 272: /* 273: * エンコードされたキーの情報を取得する 274: */ 275: static int 276: read_encoded_key(char** buf) 277: { 278: char* p; 279: char* str; 280: 281: int key = 0; 282: 283: /* 閉じ括弧を探す */ 284: for (p = *buf + 1; *p; p++) { 285: if (*p == ')') { 286: break; 287: } 288: } 289: 290: if (*p == '\0') { 291: *buf = p; 292: return '\0'; 293: } 294: 295: str = *buf + 1; 296: *p = '\0'; 297: *buf = p + 1; 298: 299: p = strtok(str, " \t\r"); 300: if (!p) { 301: return '\0'; 302: } 303: 304: do { 305: if (p[1] == '\0') { 306: return key | *p; 307: } else { 308: struct key_name_table* e; 309: 310: for (e = key_name_table; e->name; e++) { 311: if (strcmp(e->name, p) == 0) { 312: key |= e->code; 313: if (e->is_modifier == 0) { 314: return key; 315: } 316: } 317: } 318: } 319: } while((p = strtok(NULL, " \t\r"))); 320: 321: return '\0'; 322: } 323: 324: static struct high_level_command_type * 325: find_command_type(char *str) 326: { 327: struct high_level_command_type* cmdn; 328: for (cmdn = high_level_command_type; cmdn->name; cmdn++) { 329: if (!strcmp(str, cmdn->name)) { 330: return cmdn; 331: } 332: } 333: return NULL; 334: } 335: 336: /* ハイレベルコマンドをパースする */ 337: static struct command * 338: make_hl_command(char *buf) 339: { 340: /* high-level command */ 341: struct high_level_command_type* cmdn; 342: struct command* cmd = NULL; 343: char* p; 344: int i; 345: 346: /* コマンドの種類を調べる */ 347: p = strtok(buf, " \t\r"); 348: if (!p) { 349: return NULL; 350: } 351: cmdn = find_command_type(p); 352: if (!cmdn) { 353: return NULL; 354: } 355: 356: /* コマンドを作る */ 357: cmd = (struct command*) malloc(sizeof(struct command)); 358: cmd->cmd = cmdn->cmd; 359: cmd->n_arg = cmdn->n_arg; 360: if (cmd->n_arg > 0) { 361: cmd->arg = (char**) malloc(sizeof(char*) * cmd->n_arg); 362: } else { 363: cmd->arg = NULL; 364: } 365: for (i = 0; i < cmd->n_arg; i++) { 366: p = strtok(NULL, " \t\r"); 367: if (!p) { 368: while (i-- > 0) 369: free(cmd->arg[i]); 370: free(cmd->arg); 371: free(cmd); 372: return NULL; 373: } 374: cmd->arg[i] = encode_command_arg(p); 375: } 376: while ((p = strtok(NULL, " \t\r"))) { 377: if (!p) { 378: break; 379: } 380: cmd->n_arg++; 381: cmd->arg = (char**) realloc(cmd->arg, sizeof(char*) * cmd->n_arg); 382: cmd->arg[cmd->n_arg - 1] = encode_command_arg(p); 383: } 384: cmd->next = NULL; 385: return cmd; 386: } 387: 388: /* 普通のコマンドをパースする */ 389: static struct command * 390: make_ll_command(char *buf) 391: { 392: struct command* cmd_head = NULL; 393: struct command* cmd = NULL; 394: char* p; 395: 396: for (p = buf; *p; ) { 397: struct command* cmd0 = NULL; 398: int c; 399: 400: if (isspace((int)(unsigned char) *p)) { 401: p++; 402: continue; 403: } else if (*p == '(') { 404: c = read_encoded_key(&p); 405: } else { 406: c = *p++; 407: } 408: 409: switch (c) { 410: case '\0': 411: break; 412: case KEY_SPACE: 413: cmd0 = make_command0(CMD_SPACE); 414: break; 415: case KEY_CTRL_J: 416: case KEY_ENTER: 417: case KEY_DOWN: 418: cmd0 = make_command0(CMD_ENTER); 419: break; 420: case KEY_BACKSPACE: 421: case KEY_CTRL_H: 422: cmd0 = make_command0(CMD_BACKSPACE); 423: break; 424: case KEY_DELETE: 425: case KEY_CTRL_D: 426: cmd0 = make_command0(CMD_DELETE); 427: break; 428: case KEY_SHIFT_LEFT: 429: cmd0 = make_command1(CMD_SHIFTARROW, "-1"); 430: break; 431: case KEY_SHIFT_RIGHT: 432: cmd0 = make_command1(CMD_SHIFTARROW, "1"); 433: break; 434: case KEY_LEFT: 435: cmd0 = make_command1(CMD_ARROW, "-1"); 436: break; 437: case KEY_RIGHT: 438: cmd0 = make_command1(CMD_ARROW, "1"); 439: break; 440: case KEY_UP: 441: cmd0 = make_command0(CMD_UP); 442: break; 443: case KEY_ESC: 444: cmd0 = make_command0(CMD_ESC); 445: break; 446: case KEY_CTRL_A: 447: cmd0 = make_command0(CMD_GOBOL); 448: break; 449: case KEY_CTRL_E: 450: cmd0 = make_command0(CMD_GOEOL); 451: break; 452: case KEY_CTRL_K: 453: cmd0 = make_command0(CMD_CUT); 454: break; 455: default: 456: if ((c & 0xffffff80) == 0) { 457: /* ASCII文字 */ 458: char str[2]; 459: 460: str[0] = (char)c; 461: str[1] = '\0'; 462: /* cmd_key */ 463: cmd0 = make_command1(CMD_KEY, str); 464: } 465: break; 466: } 467: 468: if (cmd0) { 469: if (cmd) { 470: cmd->next = cmd0; 471: } else { 472: cmd_head = cmd0; 473: } 474: cmd = cmd0; 475: } 476: } /* for (p) */ 477: 478: if (cmd) { 479: cmd->next = make_command0(CMDH_GETPREEDIT); 480: } else { 481: cmd_head = make_command0(CMDH_GETPREEDIT); 482: } 483: 484: return cmd_head; 485: } 486: 487: static struct command* 488: make_command(char* buf) 489: { 490: 491: if (*buf == ' ') { 492: /* ハイレベルコマンド */ 493: struct command *cmd; 494: cmd = make_hl_command(buf); 495: if (!cmd) { 496: send_error(); 497: } 498: return cmd; 499: } 500: return make_ll_command(buf); 501: } 502: 503: static int 504: proc_connection(void)
Permalink to this note guest: anthy/9100e/src-util/agent.c:503-504 on Fri Feb 29 18:44:11 +0900 2008

標準入力を処理する

505: { 506: fd_set rfds; 507: fd_set wfds; 508: int max_fd; 509: int ret; 510: 511: max_fd = -1; 512: FD_ZERO(&rfds); 513: FD_ZERO(&wfds); 514: if (daemon_sock >= 0) { 515: max_fd = daemon_sock; 516: FD_SET(daemon_sock, &rfds); 517: } 518: max_fd = MAX(conn->rfd, max_fd); 519: FD_SET(conn->rfd, &rfds); 520: if (conn->n_wbuf > 0) { 521: max_fd = MAX(conn->wfd, max_fd); 522: FD_SET(conn->wfd, &wfds); 523: } 524: 525: if (max_fd == -1) 526: return -1; 527: 528: ret = select(max_fd + 1, &rfds, &wfds, NULL, NULL); 529: if (ret < 0) { 530: return -1; 531: } 532: 533: if (conn->n_wbuf > 0 && FD_ISSET(conn->wfd, &wfds)) { 534: ret = write(conn->wfd, conn->wbuf, conn->n_wbuf); 535: if (ret <= 0) { 536: kill_connection (conn); 537: } else { 538: conn->n_wbuf -= ret; 539: if (conn->n_wbuf > 0) { 540: memmove(conn->wbuf, conn->wbuf + ret, conn->n_wbuf); 541: } 542: } 543: } 544: 545: if (FD_ISSET(conn->rfd, &rfds)) { 546: ensure_buffer(&conn->rbuf, &conn->s_rbuf, 547: conn->n_rbuf + BUF_GROW_SIZE); 548: ret = read(conn->rfd, 549: conn->rbuf + conn->n_rbuf, conn->s_rbuf - conn->n_rbuf); 550: if (ret <= 0) { 551: kill_connection (conn); 552: } else { 553: conn->n_rbuf += ret; 554: } 555: } 556: return 0; 557: } 558: 559: static struct command * 560: read_command(void) 561: { 562: struct command* cmd; 563: 564: AGAIN: 565: if (command_queue != NULL) { 566: cmd = command_queue; 567: command_queue = cmd->next; 568: return cmd; 569: } 570: 571: while (1) { 572: 573: char* p; 574: for (p = conn->rbuf; p < conn->rbuf + conn->n_rbuf; p++) { 575: if (*p == '\n') { 576: *p = '\0'; 577: cmd = make_command(conn->rbuf); 578: