home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume22 / beav / part04 / symbol.c < prev    next >
C/C++ Source or Header  |  1991-08-14  |  19KB  |  504 lines

  1. /*
  2. *              Symbol table stuff.
  3. * Symbol tables, and keymap setup.
  4. * The terminal specific parts of building the
  5. * keymap has been moved to a better place.
  6. */
  7. #define LINT_ARGS   1           /* enable lint type checking */
  8. #include        "def.h"
  9.  
  10. void keyadd ();
  11. void keydup ();
  12.  
  13.  
  14. extern    char    MSG_byte_shift[];
  15. extern    char    MSG_back_char[];
  16. extern    char    MSG_quit[];
  17. extern    char    MSG_forw_del_char[];
  18. extern    char    MSG_toggle_swap[];
  19. extern    char    MSG_forw_char[];
  20. extern    char    MSG_abort[];
  21. extern    char    MSG_ins_self[];
  22. extern    char    MSG_back_del_char[];
  23. extern    char    MSG_refresh[];
  24. extern    char    MSG_forw_line[];
  25. extern    char    MSG_back_line[];
  26. extern    char    MSG_quote[];
  27. extern    char    MSG_recall[];
  28. extern    char    MSG_twiddle[];
  29. extern    char    MSG_forw_page[];
  30. extern    char    MSG_kill_region[];
  31. extern    char    MSG_yank[];
  32. extern    char    MSG_down_window[];
  33. extern    char    MSG_ins_toggle[];
  34. extern    char    MSG_display_buffers[];
  35. extern    char    MSG_quit[];
  36. extern    char    MSG_exit_flush_all[];
  37. extern    char    MSG_set_file_name[];
  38. extern    char    MSG_file_insert[];
  39. extern    char    MSG_buf_size_lock[];
  40. extern    char    MSG_flush_all[];
  41. extern    char    MSG_down_window[];
  42. extern    char    MSG_up_window[];
  43. extern    char    MSG_file_read[];
  44. extern    char    MSG_file_save[];
  45. extern    char    MSG_file_visit[];
  46. extern    char    MSG_file_write[];
  47. extern    char    MSG_swap_dot_and_mark[];
  48. extern    char    MSG_shrink_window[];
  49. extern    char    MSG_display_position[];
  50. extern    char    MSG_start_macro[];
  51. extern    char    MSG_end_macro[];
  52. extern    char    MSG_help[];
  53. extern    char    MSG_only_window[];
  54. extern    char    MSG_del_window[];
  55. extern    char    MSG_split_window[];
  56. extern    char    MSG_use_buffer[];
  57. extern    char    MSG_spawn_cli[];
  58. extern    char    MSG_execute_macro[];
  59. extern    char    MSG_goto_line[];
  60. extern    char    MSG_ins_unit[];
  61. extern    char    MSG_kill_buffer[];
  62. extern    char    MSG_load_bindings[];
  63. extern    char    MSG_forw_window[];
  64. extern    char    MSG_back_window[];
  65. extern    char    MSG_view_file[];
  66. extern    char    MSG_enlarge_window[];
  67. extern    char    MSG_ascii_mode[];
  68. extern    char    MSG_binary_mode[];
  69. extern    char    MSG_buffer_name[];
  70. extern    char    MSG_decimal_mode[];
  71. extern    char    MSG_ebcdic_mode[];
  72. extern    char    MSG_hex_mode[];
  73. extern    char    MSG_back_del_unit[];
  74. extern    char    MSG_octal_mode[];
  75. extern    char    MSG_display_version[];
  76. extern    char    MSG_unit_size1[];
  77. extern    char    MSG_unit_size2[];
  78. extern    char    MSG_unit_size4[];
  79. extern    char    MSG_reposition_window[];
  80. extern    char    MSG_set_mark[];
  81. extern    char    MSG_goto_eob[];
  82. extern    char    MSG_goto_bob[];
  83. extern    char    MSG_next_buff[];
  84. extern    char    MSG_prev_buff[];
  85. extern    char    MSG_query_replace[];
  86. extern    char    MSG_display_bindings[];
  87. extern    char    MSG_auto_save[];
  88. extern    char    MSG_back_unit[];
  89. extern    char    MSG_compare[];
  90. extern    char    MSG_forw_del_unit[];
  91. extern    char    MSG_forw_unit[];
  92. extern    char    MSG_link_windows[];
  93. extern    char    MSG_print[];
  94. extern    char    MSG_back_search[];
  95. extern    char    MSG_forw_search[];
  96. extern    char    MSG_back_page[];
  97. extern    char    MSG_copy_region[];
  98. extern    char    MSG_extended_command[];
  99. extern    char    MSG_up_window[];
  100. extern    char    MSG_search_again[];
  101. extern    char    MSG_bind_to_key[];
  102. extern    char    MSG_file_visit_split[];
  103. extern    char    MSG_yank_buffer[];
  104. extern    char    MSG_save_region[];
  105. extern    char    MSG_use_buffer_split[];
  106. extern    char    MSG_no_f_tb[];
  107. extern    char    MSG_n_split[];
  108. extern    char    MSG_n_combine[];
  109. extern    char    MSG_show_save_buf[];
  110.  
  111. /*
  112. * Defined by "main.c".
  113. */
  114. extern char ctrlg ();           /* Abort out of things      */
  115. extern char quit ();            /* Quit             */
  116. extern char ctlxlp ();          /* Begin macro          */
  117. extern char ctlxrp ();          /* End macro            */
  118. extern char ctlxe ();           /* Execute macro        */
  119. extern char showversion ();     /* Show version numbers, etc.   */
  120. extern char flushnquit ();      /* Flush buffers & exit (fitz)  */
  121. extern char flush_all ();       /* Flush buffers (jam)      */
  122. extern char autosave ();        /* autosave function (jam)  */
  123.  
  124. /*
  125. * Defined by "search.c".
  126. */
  127. extern char forwsearch ();      /* Search forward       */
  128. extern char backsearch ();      /* Search backwards     */
  129. extern char searchagain ();     /* Repeat last search command   */
  130. extern char queryrepl ();       /* Query replace        */
  131. extern char compare ();         /* Compare two windows  */
  132. extern char recall ();          /* Recall last search string  */
  133.  
  134. /*
  135. * Defined by "basic.c".
  136. */
  137. extern char backchar ();        /* Move backward by characters  */
  138. extern char forwchar ();        /* Move forward by characters   */
  139. extern char gotobob ();         /* Move to start of buffer  */
  140. extern char gotoeob ();         /* Move to end of buffer    */
  141. extern char forwline ();        /* Move forward by lines    */
  142. extern char backline ();        /* Move backward by lines   */
  143. extern char forwpage ();        /* Move forward by pages    */
  144. extern char backpage ();        /* Move backward by pages   */
  145. extern char setmark ();         /* Set mark         */
  146. extern char swapmark ();        /* Swap "." and mark        */
  147. extern char gotoline ();        /* Go to a specified line.  */
  148.  
  149. /*
  150. * Defined by "buffer.c".
  151. */
  152. extern char listbuffers ();     /* Display list of buffers  */
  153. extern char showsavebuf ();     /* Show the save buffer contents */
  154. extern char usebuffer ();       /* Switch a window to a buffer  */
  155. extern char use_buffer ();      /* ditto, plus window split */
  156. extern char killbuffer ();      /* Make a buffer go away.   */
  157. extern char next_buf ();        /* goto next buffer     */
  158. extern char prev_buf ();        /* goto prev buffer     */
  159. extern char yank_buffer ();     /* yank buffer by name      */
  160. extern char buffername ();      /* change buffer name       */
  161. extern char bufsizlock ();      /* lock buffer size         */
  162.  
  163. /*
  164. * Defined by "file."
  165. */
  166. extern char fileread ();        /* Get a file, read only    */
  167. extern char filevisit ();       /* Get a file, read write   */
  168. extern char file_visit ();      /* ditto , plus window split    */
  169. extern char filewrite ();       /* Write a file         */
  170. extern char filesave ();        /* Save current file        */
  171. extern char filename ();        /* Adjust file name     */
  172. extern char fileinsert ();      /* insert file to cursor (jam ) */
  173. extern char viewfile ();        /* readonly file visit (jam)    */
  174.  
  175. /*
  176. * Defined by "random.c".
  177. */
  178.  
  179. extern char dispshift ();       /* Increment display shift   */
  180. extern char selfinsert ();      /* Insert character  */
  181. extern char insert_toggle ();   /* toggle insert mode  (jam)    */
  182. extern char insertunit ();      /* insert unit  (pvr)    */
  183. extern char showcpos ();        /* Show the cursor position */
  184. extern char twiddle ();         /* Twiddle units        */
  185. extern char forwdel ();         /* Forward delete       */
  186. extern char backdel ();         /* Backward delete      */
  187. extern char quote ();           /* Insert literal       */
  188. extern char asciimode ();       /* display ASCII data   */
  189. extern char ebcdicmode ();      /* display EBCDIC data   */
  190. extern char decimalmode ();     /* display DECIMAL data   */
  191. extern char hexmode ();         /* display HEX data   */
  192. extern char octalmode ();       /* display OCTAL data   */
  193. extern char binarymode ();      /* display BINARY data   */
  194. extern char dispsize1 ();       /* display in BYTE format */
  195. extern char dispsize2 ();       /* display in WORD format */
  196. extern char dispsize4 ();       /* display in DWORD format*/
  197. extern char dispswapbyte ();    /* Display swaped bytes    pvr   */
  198. extern char yank ();            /* Yank back from killbuffer.   */
  199. extern char linkwind ();        /* Link all windows on one buffer. */
  200. extern char n_way_split ();     /* Split buffer into n buffers. */
  201. extern char n_way_combine ();   /* Combine n buffers into one. */
  202.  
  203. /*
  204. * Defined by "region.c".
  205. */
  206. extern char killregion ();      /* Kill region.         */
  207. extern char copyregion ();      /* Copy region to kill buffer.  */
  208. extern char save_region ();     /* Save region in named buffer. */
  209.  
  210. /*
  211. * Defined by "spawn.c".
  212. */
  213. extern char spawncli ();        /* Run CLI in a subjob.     */
  214. extern char clock ();           /* display time in modeline */
  215.  
  216. /*
  217. * Defined by "window.c".
  218. */
  219. extern char reposition ();      /* Reposition window        */
  220. extern char refresh ();         /* Refresh the screen       */
  221. extern char nextwind ();        /* Move to the next window  */
  222. extern char prevwind ();        /* Move to the previous window  */
  223. extern char mvdnwind ();        /* Move window down     */
  224. extern char mvupwind ();        /* Move window up       */
  225. extern char onlywind ();        /* Make current window only one */
  226. extern char delwind ();         /* Delete current window */
  227. extern char splitwind ();       /* Split current window     */
  228. extern char enlargewind ();     /* Enlarge display window.  */
  229. extern char shrinkwind ();      /* Shrink window.       */
  230.  
  231. /*
  232. * Defined by "word.c".
  233. */
  234. extern char backunit ();        /* Backup by units      */
  235. extern char forwunit ();        /* Advance by units     */
  236. extern char delfunit ();        /* Delete forward unit. */
  237. extern char delbunit ();        /* Delete backward unit.    */
  238.  
  239. /*
  240. * Defined by "extend.c".
  241. */
  242. extern char extend ();          /* Extended commands.       */
  243. extern char help ();            /* Help key.            */
  244. extern char bindtokey ();       /* Modify key bindings.     */
  245. extern char wallchart ();       /* Make wall chart.     */
  246. extern void check_extend ();    /* load extended key file   */
  247. extern char load_extend ();     /* load extended file by name   */
  248.  
  249. /*
  250. * Defined by "display.c
  251. */
  252. extern char print ();           /* print window from mark to dot */
  253.  
  254. typedef struct
  255. {
  256.  
  257.     short   k_key;              /* Key to bind.                 */
  258.     char    (*k_funcp) ();      /* Function.            */
  259.     char   *k_name;             /* Function name string.        */
  260.     char    k_modify;           /* modify bit */
  261. }                KEY;
  262.  
  263. /*
  264. * Default key binding table. This contains
  265. * the function names, the symbol table name, and (possibly)
  266. * a key binding for the builtin functions. There are no
  267. * bindings for C-U or C-X. These are done with special
  268. * code, but should be done normally.
  269. */
  270. KEY key[] =
  271. {
  272.     KCTRL | 'A', dispshift, MSG_byte_shift, 0,
  273.         KCTRL | 'B', backchar, MSG_back_char, SSRCH | SRPLC,
  274.         KCTRL | 'C', quit, MSG_quit, 0,/* pvr */
  275.     KCTRL | 'D', forwdel, MSG_forw_del_char, SMOD | SSIZE | SSRCH | SRPLC,
  276.         KCTRL | 'E', dispswapbyte, MSG_toggle_swap, SSRCH | SRPLC,/* pvr */
  277.     KCTRL | 'F', forwchar, MSG_forw_char, SSRCH | SRPLC,
  278.         KCTRL | 'G', ctrlg, MSG_abort, SSRCH | SRPLC,
  279.         KCTRL | 'I', selfinsert, MSG_ins_self, SMOD | SSRCH | SRPLC,
  280.         KCTRL | 'H', backdel, MSG_back_del_char, SMOD | SSIZE | SSRCH | SRPLC,
  281.         KCTRL | 'L', refresh, MSG_refresh, SSRCH | SRPLC,
  282.         KCTRL | 'N', forwline, MSG_forw_line, SSRCH | SRPLC,
  283.         KCTRL | 'P', backline, MSG_back_line, SSRCH | SRPLC,
  284.         KCTRL | 'Q', quote, MSG_quote, 0,
  285.         KCTRL | 'R', recall, MSG_recall, SSRCH | SRPLC,
  286.         KCTRL | 'T', twiddle, MSG_twiddle, SMOD | SSRCH | SRPLC,
  287.         KCTRL | 'V', forwpage, MSG_forw_page, SRPLC,
  288.         KCTRL | 'W', killregion, MSG_kill_region, SMOD | SSIZE,
  289.         KCTRL | 'Y', yank, MSG_yank, SMOD | SSIZE,
  290.         KCTRL | 'Z', mvdnwind, MSG_down_window, 0,/* fitz */
  291.     KCTLX | KCTRL | 'A', insert_toggle, MSG_ins_toggle, SSRCH | SRPLC,
  292.         KCTLX | KCTRL | 'B', listbuffers, MSG_display_buffers, 0,
  293.         KCTLX | KCTRL | 'C', quit, MSG_quit, 0,
  294.         KCTLX | KCTRL | 'E', flushnquit, MSG_exit_flush_all, 0,/* fitz */
  295.     KCTLX | KCTRL | 'F', filename, MSG_set_file_name, SMOD,/* jam */
  296.     KCTLX | KCTRL | 'I', fileinsert, MSG_file_insert, SMOD | SSIZE,
  297.         KCTLX | KCTRL | 'L', bufsizlock, MSG_buf_size_lock, 0,
  298.         KCTLX | KCTRL | 'M', flush_all, MSG_flush_all, 0,
  299.         KCTLX | KCTRL | 'N', mvdnwind, MSG_down_window, 0,
  300.         KCTLX | KCTRL | 'P', mvupwind, MSG_up_window, 0,
  301.         KCTLX | KCTRL | 'R', fileread, MSG_file_read, 0,
  302.         KCTLX | KCTRL | 'S', filesave, MSG_file_save, 0,
  303.         KCTLX | KCTRL | 'V', filevisit, MSG_file_visit, 0,
  304.         KCTLX | KCTRL | 'W', filewrite, MSG_file_write, 0,
  305.         KCTLX | KCTRL | 'X', swapmark, MSG_swap_dot_and_mark, 0,
  306.         KCTLX | KCTRL | 'Z', shrinkwind, MSG_shrink_window, 0,
  307.         KCTLX | '=', showcpos, MSG_display_position, 0,
  308.         KCTLX | '(', ctlxlp, MSG_start_macro, 0,
  309.         KCTLX | ')', ctlxrp, MSG_end_macro, 0,
  310.         KCTLX | '?', help, MSG_help, 0,
  311.         KCTLX | '0', delwind, MSG_del_window, 0,
  312.         KCTLX | '1', onlywind, MSG_only_window, 0,
  313.         KCTLX | '2', splitwind, MSG_split_window, 0,
  314.         KCTLX | 'B', usebuffer, MSG_use_buffer, 0,
  315.         KCTLX | 'C', spawncli, MSG_spawn_cli, 0,/* fitz */
  316.     KCTLX | 'E', ctlxe, MSG_execute_macro, 0,
  317.         KCTLX | 'G', gotoline, MSG_goto_line, 0,
  318.         KCTLX | 'I', insertunit, MSG_ins_unit, SMOD | SSIZE | SSRCH | SRPLC,
  319.         KCTLX | 'K', killbuffer, MSG_kill_buffer, 0,
  320.         KCTLX | 'L', load_extend, MSG_load_bindings, 0,
  321.         KCTLX | 'N', nextwind, MSG_forw_window, 0,
  322.         KCTLX | 'P', prevwind, MSG_back_window, 0,
  323.         KCTLX | 'V', viewfile, MSG_view_file, 0,/* jam */
  324.     KCTLX | 'Z', enlargewind, MSG_enlarge_window, 0,
  325.         KMETA | KCTRL | 'A', asciimode, MSG_ascii_mode, SSRCH | SRPLC, /* pvr */
  326.     KMETA | KCTRL | 'B', binarymode, MSG_binary_mode, SSRCH | SRPLC, /* pvr */
  327.     KMETA | KCTRL | 'F', n_way_combine, MSG_n_combine, SSIZE | SMOD, /* pvr */
  328.     KMETA | KCTRL | 'N', buffername, MSG_buffer_name, 0,
  329.         KMETA | KCTRL | 'D', decimalmode, MSG_decimal_mode, SSRCH | SRPLC, /* pvr */
  330.     KMETA | KCTRL | 'E', ebcdicmode, MSG_ebcdic_mode, SSRCH | SRPLC, /* pvr */
  331.     KMETA | KCTRL | 'H', hexmode, MSG_hex_mode, SSRCH | SRPLC, /* pvr */
  332.     KMETA | KCTRL | 'K', delbunit, MSG_back_del_unit, SMOD | SSIZE | SSRCH | SRPLC,
  333.         KMETA | KCTRL | 'O', octalmode, MSG_octal_mode, SSRCH | SRPLC, /* pvr */
  334.     KMETA | KCTRL | 'S', n_way_split, MSG_n_split, 0, /* pvr */
  335.     KMETA | KCTRL | 'V', showversion, MSG_display_version, 0,
  336.         KMETA | KCTRL | 'W', showsavebuf, MSG_show_save_buf, 0,
  337.         KMETA | '1', dispsize1, MSG_unit_size1, SSRCH | SRPLC,/* pvr */
  338.     KMETA | '2', dispsize2, MSG_unit_size2, SSRCH | SRPLC,/* pvr */
  339.     KMETA | '4', dispsize4, MSG_unit_size4, SSRCH | SRPLC,/* pvr */
  340.     KMETA | '!', reposition, MSG_reposition_window, 0,
  341.         KMETA | '.', setmark, MSG_set_mark, 0,
  342.         KMETA | '>', gotoeob, MSG_goto_eob, SSRCH | SRPLC,
  343.         KMETA | '<', gotobob, MSG_goto_bob, SSRCH | SRPLC,
  344.         KMETA | '+', next_buf, MSG_next_buff, 0,
  345.         KMETA | '-', prev_buf, MSG_prev_buff, 0,
  346.         KMETA | '%', queryrepl, MSG_query_replace, SMOD,
  347.         KMETA | '?', wallchart, MSG_display_bindings, 0,
  348.         KMETA | 'A', autosave, MSG_auto_save, 0,
  349.         KMETA | 'B', backunit, MSG_back_unit, SSRCH | SRPLC,
  350.         KMETA | 'C', compare, MSG_compare, 0,
  351.         KMETA | 'D', delfunit, MSG_forw_del_unit, SMOD | SSIZE | SSRCH | SRPLC,
  352.         KMETA | 'F', forwunit, MSG_forw_unit, SSRCH | SRPLC,
  353.         KMETA | 'G', use_buffer, MSG_use_buffer_split, 0,
  354.         KMETA | 'K', bindtokey, MSG_bind_to_key, 0,
  355.         KMETA | 'L', linkwind, MSG_link_windows, 0,
  356.         KMETA | 'O', save_region, MSG_save_region, 0,
  357.         KMETA | 'P', print, MSG_print, 0,
  358.         KMETA | 'R', backsearch, MSG_back_search, 0,
  359.         KMETA | 'S', forwsearch, MSG_forw_search, 0,
  360.         KMETA | 'T', searchagain, MSG_search_again, 0,
  361.         KMETA | 'U', file_visit, MSG_file_visit_split, 0,
  362.         KMETA | 'V', backpage, MSG_back_page, SRPLC,
  363.         KMETA | 'W', copyregion, MSG_copy_region, 0,
  364.         KMETA | 'X', extend, MSG_extended_command, 0,
  365.         KMETA | 'Y', yank_buffer, MSG_yank_buffer, SMOD | SSIZE,
  366.         KMETA | 'Z', mvupwind, MSG_up_window, 0
  367. };
  368.  
  369. #define NKEY    (sizeof(key) / sizeof(key[0]))
  370.  
  371. /*
  372. * Symbol table lookup.
  373. * Return a pointer to the SYMBOL node, or NULL if
  374. * the symbol is not found.
  375. */
  376. SYMBOL * symlookup (cp)
  377. register char  *cp;
  378. {
  379.     register    SYMBOL * sp;
  380.  
  381.     sp = symbol[symhash (cp)];
  382.     while (sp != NULL)
  383.     {
  384.         if (strcmp (cp, sp -> s_name) == 0)
  385.             return (sp);
  386.         sp = sp -> s_symp;
  387.     }
  388.     return (NULL);
  389. }
  390.  
  391.  
  392. /*
  393. * Take a string, and compute the symbol table
  394. * bucket number. This is done by adding all of the characters
  395. * together, and taking the sum mod NSHASH. The string probably
  396. * should not contain any GR characters; if it does the "*cp"
  397. * may get a nagative number on some machines, and the "%"
  398. * will return a negative number!
  399. */
  400. int     symhash (cp)
  401. register char  *cp;
  402. {
  403.     register int    c;
  404.     register int    n;
  405.  
  406.     n = 0;
  407.     while ((c = *cp++) != 0)
  408.         n += c;
  409.     return (n % NSHASH);
  410. }
  411.  
  412.  
  413. /*
  414. * Build initial keymap. The funny keys
  415. * (commands, odd control characters) are mapped using
  416. * a big table and calls to "keyadd". The printing characters
  417. * are done with some do-it-yourself handwaving. The terminal
  418. * specific keymap initialization code is called at the
  419. * very end to finish up. All errors are fatal.
  420. */
  421. void keymapinit ()
  422. {
  423.     register    SYMBOL * sp;
  424.     register    KEY * kp;
  425.     register int    i;
  426.     register int    hash;
  427.  
  428.     for (i = 0; i < NKEYS; ++i)
  429.         binding[i] = NULL;
  430.     for (kp = &key[0]; kp < &key[NKEY]; ++kp)
  431.         keyadd (kp -> k_key, kp -> k_funcp, kp -> k_name, kp -> k_modify);
  432.     keydup (KCTLX | KCTRL | 'G', MSG_abort);
  433.     keydup (KMETA | KCTRL | 'G', MSG_abort);
  434.     keydup (0x7F, MSG_back_del_char);
  435.     keydup (KMETA | 'Q', MSG_quote);
  436.     keydup (KMETA | 0x7F, MSG_back_del_unit);
  437.     /* 
  438.   * Should be bound by "tab" already.
  439.   */
  440.     if ((sp = symlookup (MSG_ins_self)) == NULL)
  441.         abort ();
  442.     for (i = 0x20; i < 0x7F; ++i)
  443.     {
  444.         if (binding[i] != NULL)
  445.             abort ();
  446.         binding[i] = sp;
  447.         ++sp -> s_nkey;
  448.     }
  449.     ttykeymapinit ();
  450. }
  451.  
  452.  
  453. /*
  454. * Create a new builtin function "name"
  455. * with function "funcp". If the "new" is a real
  456. * key, bind it as a side effect. All errors
  457. * are fatal.
  458. */
  459. void keyadd (new, funcp, name, modify)
  460. bool   (*funcp) ();
  461. char   *name;
  462. {
  463.     register    SYMBOL * sp;
  464.     register int    hash;
  465.  
  466.     if ((sp = (SYMBOL *) malloc (sizeof (SYMBOL))) == NULL)
  467.         abort ();
  468.     hash = symhash (name);
  469.     sp -> s_symp = symbol[hash];
  470.     symbol[hash] = sp;
  471.     sp -> s_nkey = 0;
  472.     sp -> s_name = name;
  473.     sp -> s_funcp = funcp;
  474.     sp -> s_modify = modify;
  475.     if (new >= 0)
  476.     {
  477.         /* Bind this key.       */
  478.         if (binding[new] != NULL)
  479.             abort ();
  480.         binding[new] = sp;
  481.         ++sp -> s_nkey;
  482.     }
  483. }
  484.  
  485. /*
  486. * Bind key "new" to the existing
  487. * routine "name". If the name cannot be found,
  488. * or the key is already bound, abort.
  489. */
  490. void keydup (new, name)
  491. register int    new;
  492. char   *name;
  493. {
  494.     register    SYMBOL * sp;
  495.  
  496.     if (binding[new] != NULL || (sp = symlookup (name)) == NULL)
  497.     {
  498.         printf (MSG_no_f_tb, name);
  499.         abort ();
  500.     }
  501.     binding[new] = sp;
  502.     ++sp -> s_nkey;
  503. }
  504.