home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / misc / inter41 / intlist.e < prev    next >
Text File  |  1994-05-07  |  32KB  |  1,146 lines

  1. /****************************************************************/
  2. /*    EEL code file for editing the Interrupt List        */
  3. /*                                */
  4. /*    Written by Ralf Brown                    */
  5. /*    LastEdit: 7 May 94                    */
  6. /*                                */
  7. /*  This EEL file adds the following keybindings:        */
  8. /*    Shf-Alt-B add another BUG: to the current entry           */
  9. /*    Shf-Alt-D add a Desc: section to the current entry    */
  10. /*    Shf-Alt-R add a Range: section to the current entry       */
  11. /*    Alt-I    add an Index: section to the current entry    */
  12. /*        add another Index: line if already on Index:    */
  13. /*      Alt-N   add a new note to current entry or data struct  */
  14. /*      Alt-P   add a Program: section to the current entry     */
  15. /*      Alt-R   insert Return: at start of line                 */
  16. /*    Alt-S    insert SeeAlso: at start of line        */
  17. /*    F11    insert a blank separator line            */
  18. /*    ^F11    create Format of: header            */
  19. /*    Shf-F11    create Values for: header            */
  20. /*    Alt-F11 create Call with: header            */
  21. /*    Alt-F12 create Bitfield for: header            */
  22. /*    F12    add the interrupt number to the separator line    */
  23. /*        preceding the current entry            */
  24. /*    ^F12    jump to a specified entry            */
  25. /*                                */
  26. /*  It adds the following unbound commands:                */
  27. /*      renumber-tables                            */
  28. /*                                */
  29. /*  Other:                            */
  30. /*    adds intlist-mode for .LST and .1ST files        */
  31. /*    switches current buffer into intlist-mode on loading    */
  32. /*      maintains a table counter which is inserted each time   */
  33. /*        a table is created in the text                */
  34. /****************************************************************/
  35.  
  36. #include "eel.h"
  37.  
  38. keytable intlist_tab ;            /* key table for IntList mode */
  39.  
  40. /*=============================================================*/
  41. /*    Global Variables                           */
  42. /*=============================================================*/
  43.  
  44. char return_section[] = "Return: " ;
  45. char program_section[] = "Program: " ;
  46. char desc_section[] = "Desc:\t" ;
  47. char range_section[] = "Range:\t" ;
  48. char notes_section[] = "Notes*:\t" ;
  49. char bugs_section[] = "BUGS*:\t" ;
  50. char seealso_section[] = "SeeAlso: " ;
  51. char index_section[] = "Index:\t" ;
  52.  
  53. char *(section_order[9]) ;
  54.  
  55. when_loading()
  56. {
  57.    /* list the sections of an entry in the order they should appear (if */
  58.    /* present at all) */
  59.    section_order[0] = return_section ;
  60.    section_order[1] = program_section ;
  61.    section_order[2] = desc_section ;
  62.    section_order[3] = range_section ;
  63.    section_order[4] = notes_section ;
  64.    section_order[5] = bugs_section ;
  65.    section_order[6] = seealso_section ;
  66.    section_order[7] = index_section ;
  67.    section_order[8] = NULL ;
  68. }
  69.  
  70. /*=============================================================*/
  71. /*    Buffer-specific variables                       */
  72. /*=============================================================*/
  73.  
  74. buffer spot table_counter ;
  75.  
  76. /*=============================================================*/
  77. /*=============================================================*/
  78.  
  79. int empty_line()
  80. {
  81.    return (character(point-1) == '\n' && character(point) == '\n') ;
  82. }
  83.  
  84. /*=============================================================*/
  85. /*=============================================================*/
  86.  
  87. int is_separator_line()
  88. {
  89.    return (empty_line() || parse_string(1,"--------",NULL)) ;
  90. }
  91.  
  92. /*=============================================================*/
  93. /* search in the specified direction (1 = forward, -1 = back)  */
  94. /* for the next entry separator line                   */
  95. /*=============================================================*/
  96.  
  97. int to_separator_line(dir)
  98. int dir ;
  99. {
  100.    nl_reverse() ;
  101.    return search(dir,"\n--------") ;
  102. }
  103.  
  104. /*=============================================================*/
  105. /* move to the location where the specified section of an      */
  106. /* entry begins (if present) or should begin (if not)           */
  107. /*=============================================================*/
  108.  
  109. int to_section_start(section)
  110. char *section ;
  111. {
  112.    int i, j, len ;
  113.  
  114.    for (i = 0 ; section_order[i] ; i++)
  115.       if (strcmp(section,section_order[i]) == 0)
  116.      break ;
  117.    if (section_order[i])
  118.       {
  119.       while (!is_separator_line())
  120.      {
  121.      for (j = i ; section_order[j] ; j++)
  122.         if (parse_string(1,section_order[j],NULL))
  123.            {
  124.            if ((len = parse_string(1,section,NULL)) != 0)
  125.           {
  126.           point += len ;
  127.           return 1 ;    /* section already exists */
  128.           }
  129.            return 0 ;    /* section nonexistent, but found position */
  130.            }
  131.      if (!nl_forward())
  132.         break ;
  133.      }
  134.       return 0 ;    /* section does not yet exist */
  135.       }
  136.    else
  137.       return 0 ;    /* section not found */
  138. }
  139.  
  140. /*=============================================================*/
  141. /*=============================================================*/
  142.  
  143. int make_section(section,start_entry,name)
  144. char *section, *name ;
  145. int start_entry ;
  146. {
  147.    int start = point ;
  148.  
  149.    if (start_entry)
  150.       {
  151.       if (!to_separator_line(-1))  /* find previous separator line */
  152.      {
  153.      point = start ;
  154.      say("Not in an interrupt entry") ;
  155.      return 0 ;
  156.      }
  157.       }
  158.    else
  159.       {
  160.       to_begin_line() ;
  161.       while (!empty_line() && !parse_string(1,"\n--------",NULL))
  162.      if (!nl_reverse())
  163.         break ;
  164.       }
  165.    point++ ;                 /* skip the newline */
  166.    nl_forward() ;             /* advance to first line of entry */
  167.    if (!to_section_start(section))
  168.       {
  169.       if (name)
  170.      stuff(name) ;
  171.       else
  172.      stuff(section) ;
  173.       stuff("\n") ;
  174.       point-- ;              /* back up over inserted newline */
  175.       return 1 ;
  176.       }
  177.    else
  178.       return 0 ;
  179.    return 2 ;  /* just in case */
  180. }
  181.  
  182. /*=============================================================*/
  183. /*=============================================================*/
  184.  
  185. int pluralize_section(plural)
  186. char plural ;
  187. {
  188.    point -= 3 ;
  189.    if (curchar() != plural)        /* already plural ? */
  190.       {
  191.       point++ ;
  192.       insert(plural) ;
  193.       }
  194.    nl_forward() ;
  195.    while (!is_separator_line() && parse_string(1,"[ \t]",NULL))
  196.       nl_forward() ;
  197.    stuff("\t\n") ;
  198.    point-- ;
  199. }
  200.  
  201. /*=============================================================*/
  202. /* Add "SeeAlso: " to the beginning of the current line unless */
  203. /* it is already present                       */
  204. /*=============================================================*/
  205.  
  206. command see_also() on intlist_tab[ALT('s')]
  207. {
  208.    to_begin_line() ;
  209.    if (parse_string(1,"SeeAlso: ",NULL) == 0)
  210.       stuff("SeeAlso: ") ;
  211.    else
  212.       {
  213.       nl_forward() ;
  214.       stuff("SeeAlso: \n") ;
  215.       point-- ;
  216.       }
  217. }
  218.  
  219. /*=============================================================*/
  220. /* Add a Desc: section if the current entry does not already   */
  221. /* have one; if there is already a Desc: section, move to the  */
  222. /* start of it                               */
  223. /*=============================================================*/
  224.  
  225. command desc() on intlist_tab[ALT('D')]
  226. {
  227.    make_section(desc_section,1,NULL) ;
  228. }
  229.  
  230. /*=============================================================*/
  231. /* Add a Range: section if the current entry does not already  */
  232. /* have one; if there is already a Range: section, move to the */
  233. /* start of it                               */
  234. /*=============================================================*/
  235.  
  236. command range() on intlist_tab[ALT('R')]
  237. {
  238.    make_section(range_section,1,NULL) ;
  239. }
  240.  
  241. /*=============================================================*/
  242. /* Add a "Program: " section to the current entry if it does   */
  243. /* not have one; otherwise, move to the beginning of the       */
  244. /* Program: section                           */
  245. /*=============================================================*/
  246.  
  247. command program() on intlist_tab[ALT('p')]
  248. {
  249.    make_section(program_section,1,NULL) ;
  250. }
  251.  
  252. /*=============================================================*/
  253. /* Add an "Index: " section to the current entry if it does    */
  254. /* not have one; otherwise, move to the beginning of the       */
  255. /* Index: section                           */
  256. /*=============================================================*/
  257.  
  258. command add_index() on intlist_tab[ALT('i')]
  259. {
  260.    to_begin_line() ;
  261.    if (parse_string(1,"Index:",NULL))
  262.       {
  263.       while (parse_string(1,"Index:",NULL))
  264.      nl_forward() ;
  265.       stuff("Index:\t\n") ;
  266.       point-- ;
  267.       }
  268.    else
  269.       make_section(index_section,1,NULL) ;
  270. }
  271.  
  272. /*=============================================================*/
  273. /*=============================================================*/
  274.  
  275. command bug() on intlist_tab[ALT('B')]
  276. {
  277.    if (!make_section(bugs_section,1,"BUG:\t"))
  278.       pluralize_section('S') ;
  279. }
  280.  
  281. /*=============================================================*/
  282. /* Add "Note: " section to the current entry; change an        */
  283. /* existing Note: to Notes: and position at end of Note:       */
  284. /* section.                               */
  285. /*=============================================================*/
  286.  
  287. command add_note() on intlist_tab[ALT('n')]
  288. {
  289.    if (!make_section(notes_section,0,"Note:\t"))
  290.       pluralize_section('s') ;
  291. }
  292.  
  293. /*=============================================================*/
  294. /* Insert "Return: " at the beginning of the current line, if  */
  295. /* not already present                           */
  296. /*=============================================================*/
  297.  
  298. command returns() on intlist_tab[ALT('r')]
  299. {
  300.    int start = point ;
  301.    
  302.    to_begin_line() ;
  303.    if (parse_string(1,return_section,NULL) == 0)
  304.       stuff(return_section) ;
  305.    else
  306.       point = start ;
  307. }
  308.  
  309. /*=============================================================*/
  310. /* insert a line of dashes prior to the current cursor line    */
  311. /*=============================================================*/
  312.  
  313. command separator_line() on intlist_tab[FKEY(11)]
  314. {
  315.    int i ;
  316.  
  317.    to_begin_line() ;
  318.    for (i = 0 ; i < 45 ; i++)
  319.       insert('-') ;
  320.    insert('\n') ;
  321. }
  322.  
  323. /*=============================================================*/
  324. /*=============================================================*/
  325.  
  326. void insert_table_counter()
  327. {
  328.    char counter[6] ;
  329.    save_var point = *table_counter + 3 ;
  330.  
  331.    /* increment that table counter */
  332.    while (curchar() >= '0')
  333.       {
  334.       if (curchar() < '9')
  335.      {
  336.      replace(point,curchar()+1) ;
  337.      break ;
  338.      }
  339.       else
  340.      {
  341.      replace(point,'0') ;
  342.      point-- ;
  343.      }
  344.       }
  345.    restore_vars() ;
  346.    /* and now insert the incremented value at point */
  347.    stuff("(Table ") ;
  348.    grab(*table_counter,*table_counter+4,counter) ;
  349.    stuff(counter) ;
  350.    stuff(")") ;
  351. }
  352.  
  353. /*=============================================================*/
  354. /* type the name of a structure, then invoke this function     */
  355. /* to create the "Format of X:" and "Offset Size Descr" lines  */
  356. /*=============================================================*/
  357.  
  358. command structure_header() on intlist_tab[FCTRL(11)]
  359. {
  360.    int start = point ;
  361.  
  362.    to_begin_line() ;
  363.    if (parse_string(1,"Format of ",NULL) == 0)
  364.       {
  365.       stuff("Format of ") ;
  366.       to_end_line() ;
  367.       stuff(":\nOffset\tSize\tDescription\t") ;
  368.       insert_table_counter() ;
  369.       stuff("\n 00h\t") ;
  370.       }
  371.    else
  372.       point = start ;
  373. }
  374.  
  375. /*=============================================================*/
  376. /* Turn the current line into the header for a "Values of"     */
  377. /* section                               */
  378. /*=============================================================*/
  379.  
  380. command value_header() on intlist_tab[FSHIFT(11)]
  381. {
  382.    int start = point ;
  383.    
  384.    to_begin_line() ;
  385.    if (parse_string(1,"Values for ",NULL) == 0)
  386.       {
  387.       insert_table_counter() ;
  388.       stuff("\nValues for ") ;
  389.       to_end_line() ;
  390.       stuff(":\n ") ;
  391.       }
  392.    else
  393.       point = start ;
  394. }
  395.  
  396. /*=============================================================*/
  397. /* Turn the current line into the header of a "Call with"      */
  398. /* section                               */
  399. /*=============================================================*/
  400.  
  401. command call_with_header() on intlist_tab[FALT(11)]
  402. {
  403.    int start = point ;
  404.    
  405.    to_begin_line() ;
  406.    if (parse_string(1,"Call ",NULL) == 0)
  407.       {
  408.       insert_table_counter() ;
  409.       stuff("\nCall ") ;
  410.       to_end_line() ;
  411.       if (character(point-1) != ' ')
  412.      stuff(" ") ;
  413.       stuff("with:\n") ;
  414.       }
  415.    else
  416.       point = start ;
  417. }
  418.  
  419. /*=============================================================*/
  420. /* Turn the current line into the header of a "Bitfield for"   */
  421. /* section                               */
  422. /*=============================================================*/
  423.  
  424. command bitfields_for_header() on intlist_tab[FALT(12)]
  425. {
  426.    int start = point ;
  427.    
  428.    to_begin_line() ;
  429.    if (parse_string(1,"Bitfields for ",NULL) == 0)
  430.       {
  431.       stuff("Bitfields for ") ;
  432.       to_end_line() ;
  433.       stuff(":\nBit(s)\tDescription\t") ;
  434.       insert_table_counter() ;
  435.       stuff("\n ") ;
  436.       }
  437.    else
  438.       point = start ;
  439. }
  440.  
  441. /*=============================================================*/
  442. /*=============================================================*/
  443.  
  444. char grab_entry_number(func_num)
  445. char *func_num ;
  446. {
  447.    char c ;
  448.    int i ;
  449.  
  450.    strcpy(func_num,"------------") ;    /* 12 dashes */
  451.    point++ ;                /* go to first char of separator line */
  452.    nl_forward() ;            /* go to first line of entry */
  453.    if (parse_string(1,"INT ",NULL) == 0)
  454.       return 0 ;            /* not an interrupt entry, so return */
  455.    point += 4 ;                /* skip the "INT " */
  456.    func_num[0] = curchar() ;        /* grab the interrupt number */
  457.    point++ ;
  458.    func_num[1] = curchar() ;
  459.    nl_forward() ;            /* skip to second line of entry */
  460.    if (parse_string(1,"[ \t]*A[LHX][ \t]=[ \t][0-9A-F][0-9A-F]+h",NULL))
  461.       {
  462.       re_search(1,"[ \t]*A") ;
  463.       c = curchar() ;
  464.       point += 4 ;            /* skip ch and " = " */
  465.       if (c != 'L')
  466.      {
  467.      grab(point,point+((c=='X')?4:2),func_num+2) ;
  468.      point += ((c=='X')?4:2) ;
  469.      func_num[(c=='H')?4:6] = '-' ;    /* grab() stuck a NUL into the string */
  470.      }
  471.       else /* c == 'L' */
  472.      {
  473.      func_num[4] = curchar() ;
  474.      point++ ;
  475.      func_num[5] = curchar() ;
  476.      point ++ ;
  477.      }
  478.       point++ ;
  479.       if (parse_string(1,"[ \t]*subfn [0-9A-F][0-9A-F]+h",NULL))
  480.      {
  481.      re_search(1,"[ \t]*subfn ") ;
  482.      func_num[6] = 'S' ;
  483.      func_num[7] = 'F' ;
  484.      for (i = 0 ; i < 4 ; i++)
  485.         {
  486.         c = curchar() ;
  487.         if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))
  488.            {
  489.            func_num[8+i] = c ;
  490.            point++ ;
  491.            }
  492.         else
  493.            break ;
  494.         }
  495.      }
  496.       nl_forward() ;            /* skip to third line of entry */
  497.       }
  498.    if (parse_string(1,"[ \t]*[BCDES][HILPSX] = [0-9A-F][0-9A-F]+h",NULL))
  499.       {
  500.       re_search(1,"[ \t]*") ;
  501.       func_num[6] = curchar() ;
  502.       point++ ;
  503.       func_num[7] = c = curchar() ;
  504.       point += 4 ;            /* skip curchar and " = " */
  505.       if (c == 'H' || c == 'L')
  506.      {
  507.      grab(point,point+2,func_num+8) ;
  508.      func_num[10] = '-' ;        /* grab() stuck a NUL into the string */
  509.      }
  510.       else /* c == 'X' || c == 'I' || c == 'P' || c == 'S' */
  511.      grab(point,point+4,func_num+8) ;
  512.       }
  513.    return 1 ;                /* successful and have func number */
  514. }
  515.  
  516. /*=============================================================*/
  517. /* Put the interrupt and function number into the separator    */
  518. /* line just above the intlist entry preceding the cursor pos  */
  519. /*=============================================================*/
  520.  
  521. int number_one_int()
  522. {
  523.    char func_num[13] ;            /* 2->int, 4->AX, 6->extra reg, NUL */
  524.    int oldpoint ;
  525.    
  526.    while (to_separator_line(-1))    /* find previous separator line */
  527.       {
  528.       oldpoint = point ;
  529.       if (grab_entry_number(func_num))    /* does it belong to an intlist entry? */
  530.      {                /*   if yes, success, else try again */
  531.      point = oldpoint + 11 ;    /* skip NL and first ten dashes */
  532.      delete(point,point+12) ;    /* replace 12 dashes by the function */
  533.      stuff(func_num) ;        /*   number and extra register */
  534.      point = oldpoint + 9 ;        /* back to category letter position */
  535.      return 1 ;
  536.      }
  537.       point = oldpoint ;
  538.       }
  539.    return 0 ;                /* if we get here, we failed */
  540. }
  541.  
  542. /*=============================================================*/
  543. /* Put the interrupt and function number into the separator    */
  544. /* line just above one or more intlist entries preceding the   */
  545. /* current cursor position, letting user know of progress      */
  546. /*=============================================================*/
  547.  
  548. command number_int() on intlist_tab[FKEY(12)]
  549. {
  550.    int i, hit_top = 0 ;
  551.    
  552.    for (i = 0 ; i < iter ; i++)
  553.       {
  554.       if (!number_one_int())
  555.      {
  556.      hit_top = 1 ;
  557.      say("No prior entry.") ;
  558.      break ;
  559.      }
  560.       if (((i+1) % 100) == 0)
  561.      say("%4d...",i+1) ;
  562.       }
  563.    if (iter > 1 && !hit_top)
  564.       say("Done.") ;
  565.    iter = 1 ;
  566. }
  567.  
  568. /*=============================================================*/
  569. /*=============================================================*/
  570.  
  571. int line_has_see_also()
  572. {
  573.    int len ;
  574.    
  575.    to_begin_line() ;
  576.    if ((len = parse_string(1,".*%([sS]ee ",NULL)) != 0)
  577.       {
  578.       point += len ;        /* go to start of cross-reference */
  579.       point += parse_string(1,"also ",NULL) ;
  580.       if (parse_string(1,"INT [0-9A-F]",NULL) ||
  581.       parse_string(1,"A[XHL] =",NULL)
  582.      )
  583.      {
  584.      point++ ;        /* move into reference */
  585.      return 1 ;
  586.      }
  587.       }
  588.    return 0 ;
  589. }
  590.  
  591. /*=============================================================*/
  592. /*=============================================================*/
  593.  
  594. int grab_int_reference(ref)
  595. char *ref ;
  596. {
  597.    int begin, start = point ;
  598.    
  599.    re_search(-1,"[, \t\n]") ;    /* backup to start of reference */
  600.    if (curchar() == '\n')    /* start of line? */
  601.       re_search(1,":[ \t]") ;    /* skip the SeeAlso: */
  602.    else if (character(point-1) == 'T' && character(point-2) == 'N')
  603.       point -= 3 ;
  604.    else
  605.       point++ ;            /* back to start of reference */
  606.    begin = point ;
  607.    re_search(1,"[,\n\"]") ;    /* find end of INT-spec */
  608.    point-- ;
  609.    if (curchar() == '\"')    /* extra string at end of INT-spec? */
  610.       {
  611.       point++ ;
  612.       re_search(1,"[\"\n]") ;    /* if yes, run to end of line or string */
  613.       }
  614.    grab(begin,point,ref) ;
  615.    point = start ;
  616.    return 0 ;
  617. }
  618.  
  619. /*=============================================================*/
  620. /*=============================================================*/
  621.  
  622. int parse_int_name(entry_name,id,extra_string)
  623. char *entry_name, *id, *extra_string ;
  624. {
  625.    int start = point ;
  626.    int i ;
  627.    char c, *last ;
  628.  
  629.    for (i = strlen(entry_name)-1 ; i >= 0 ; i--)
  630.       entry_name[i] = toupper(entry_name[i]) ;
  631.    strcpy(id,"------------") ;
  632.    if (strncmp(entry_name,"INT ",4) == 0)
  633.       {
  634.       id[0] = entry_name[4] ;
  635.       id[1] = entry_name[5] ;
  636.       entry_name += 6 ;
  637.       if (entry_name[0] == '/')
  638.      entry_name++ ;
  639.       }
  640.    else if (to_separator_line(-1))
  641.       {
  642.       id[0] = character(point+11) ;
  643.       id[1] = character(point+12) ;
  644.       }
  645.    point = start ;
  646.    c = entry_name[1] ;
  647.    if (entry_name[0] == 'A' && (c == 'X' || c == 'H' || c == 'L'))
  648.       {
  649.       entry_name += 2 ;
  650.       while (entry_name[0] == ' ' || entry_name[0] == '\t')
  651.      entry_name++ ;
  652.       if (entry_name[0] == '=')
  653.      entry_name++ ;
  654.       while (entry_name[0] == ' ' || entry_name[0] == '\t')
  655.      entry_name++ ;
  656.       if (c != 'L')
  657.      {
  658.          id[2] = entry_name[0] ;
  659.          id[3] = entry_name[1] ;
  660.      }
  661.       if (c == 'X')
  662.      {
  663.      id[4] = entry_name[2] ;
  664.      id[5] = entry_name[3] ;
  665.      entry_name += 4 ;
  666.      }
  667.       else
  668.      {
  669.      if (c == 'L')
  670.         {
  671.         id[2] = entry_name[0] ;
  672.         id[3] = entry_name[1] ;
  673.         }
  674.      entry_name += 2 ;
  675.      }
  676.       if (entry_name[0] == 'H')
  677.      entry_name++ ;
  678.       if (entry_name[0] == '/')
  679.      entry_name++ ;
  680.       }
  681.    if (index("ABCDES",entry_name[0]) && index("HILPSXF",entry_name[1]))
  682.       {
  683.       id[6] = entry_name[0] ;
  684.       c = id[7] = entry_name[1] ;
  685.       entry_name += 2 ;
  686.       while (entry_name[0] == ' ' || entry_name[0] == '\t')
  687.      entry_name++ ;
  688.       if (entry_name[0] == '=')
  689.      entry_name++ ;
  690.       while (entry_name[0] == ' ' || entry_name[0] == '\t')
  691.      entry_name++ ;
  692.       id[8] = entry_name[0] ;
  693.       id[9] = entry_name[1] ;
  694.       if (c != 'H' && c != 'L' && (c != 'F' || entry_name[2] != 'h'))
  695.      {
  696.      id[10] = entry_name[2] ;
  697.      id[11] = entry_name[3] ;
  698.      entry_name += 4 ;
  699.      }
  700.       else
  701.      entry_name += 2 ;
  702.       if (entry_name[0] == 'H')
  703.      entry_name++ ;
  704.       if (entry_name[0] == '/')
  705.      entry_name++ ;
  706.       }
  707.    if (entry_name[0] == '\"')
  708.       {
  709.       entry_name++ ;
  710.       strcpy(extra_string,entry_name) ;
  711.       last = index(extra_string,'\"') ;
  712.       if (last)
  713.      *last = '\0' ;
  714.       }
  715.    else
  716.       extra_string[0] = '\0' ;
  717.    return 0 ;
  718. }
  719.  
  720. /*=============================================================*/
  721. /*=============================================================*/
  722.  
  723. int hex2_to_int(c1,c2)
  724. char c1, c2 ;
  725. {
  726.    if (c1 >= '0' && c1 <= '9')
  727.       c1 -= '0' ;
  728.    else if (c1 >= 'A' && c1 <= 'F')
  729.       c1 = c1 - 'A' + 10 ;
  730.    else if (c1 >= 'a' && c1 <= 'f')
  731.       c1 = c1 - 'a' + 10 ;
  732.    else
  733.       return -1 ;
  734.    if (c2 >= '0' && c2 <= '9')
  735.       c2 -= '0' ;
  736.    else if (c2 >= 'A' && c2 <= 'F')
  737.       c2 = c2 - 'A' + 10 ;
  738.    else if (c2 >= 'a' && c2 <= 'f')
  739.       c2 = c2 - 'a' + 10 ;
  740.    else
  741.       return -1 ;
  742.    return 16*c1 + c2 ;
  743. }
  744.  
  745. /*=============================================================*/
  746. /*=============================================================*/
  747.  
  748. char hex_digit(val)
  749. int val ;
  750. {
  751.    if (val < 0)
  752.       return '-' ;
  753.    else
  754.       return (val > 9) ? ('A' + val - 10) : ('0' + val) ;
  755. }
  756.  
  757. /*=============================================================*/
  758. /*=============================================================*/
  759.  
  760. int scan_for_entry(entry,extra_str,first_entry)
  761. char *entry, *extra_str ;
  762. int *first_entry ;
  763. {
  764.    int ah, al, t1, t2, match, found ;
  765.    char buf[7] ;
  766.  
  767.    if (extra_str) extra_str = 0 ;  /* for now, to avoid compiler warning */
  768.    *first_entry = 0 ;
  769.    ah = hex2_to_int(entry[2],entry[3]) ;
  770.    while (1)
  771.       {
  772.       if (!to_separator_line(1))
  773.      return 0 ;    /* failed if hit end of file */
  774.       if (character(point+1) != entry[0] || character(point+2) != entry[1])
  775.      return 0 ;    /* failed if no longer on same interrupt */
  776.       t1 = hex2_to_int(character(point+3),character(point+4)) ;
  777.       if (t1 == ah)
  778.      break ;
  779.       else if (t1 > ah)
  780.      {
  781.      to_begin_line() ;
  782.      *first_entry = point ;
  783.      return 0 ;    /* no such entry */
  784.      }
  785.       }
  786.    nl_reverse() ;
  787.    *first_entry = point ;
  788.    found = 0 ;
  789.    al = hex2_to_int(entry[4],entry[5]) ;
  790.    while (1)
  791.       {
  792.       if (!to_separator_line(1))
  793.      return 0 ;    /* failed if hit end of file */
  794.       if (character(point+1) != entry[0] || character(point+2) != entry[1])
  795.      return 0 ;    /* failed if no longer on same interrupt */
  796.       t1 = hex2_to_int(character(point+3),character(point+4)) ;
  797.       if (t1 != ah)
  798.      return 0 ;    /* failed if no longer on same INT/AH combo */
  799.       t2 = hex2_to_int(character(point+5),character(point+6)) ;
  800.       if (t2 == al)
  801.      {
  802.      if (!found)
  803.         {
  804.         found = 1 ;
  805.         *first_entry = point ;
  806.         }
  807.      if (entry[6] != '-')
  808.         {
  809.         grab(point+7,point+12,buf) ;
  810.         match = strncmp(buf,entry+6,6) ;
  811.         if (match == 0)
  812.            {
  813.            *first_entry = point ;
  814.            break ;
  815.            }
  816.         else if (match > 0)
  817.            return 0 ;    /* no exact match, but return a partial match */
  818.         }
  819.      else
  820.         break ;
  821.      }
  822.       else if (t2 > al)
  823.      {
  824.      if (found)
  825.         break ;
  826.      else
  827.         {
  828.         to_begin_line() ;
  829.         *first_entry = point ;
  830.         return 0 ;    /* no such entry */
  831.         }
  832.      }
  833.       }
  834.    point = *first_entry ;    /* back to first matching entry */
  835.    
  836.    
  837.    return 1 ;            /* we were successful */
  838. }
  839.  
  840. /*=============================================================*/
  841. /*=============================================================*/
  842.  
  843. int goto_entry(entry_name)
  844. char *entry_name ;
  845. {
  846.    char int_id[13], extra_string[60] ;
  847.    int start = point, first_entry ;
  848.    int int_num, curr_int ;
  849.    char search_str[22] ;
  850.    
  851.    parse_int_name(entry_name,int_id,extra_string) ;
  852.    int_num = hex2_to_int(int_id[0],int_id[1]) ;
  853.    if (to_separator_line(-1))
  854.       {
  855.       if (character(point+11) == '-')
  856.      curr_int = -1 ;
  857.       else
  858.      curr_int = hex2_to_int(character(point+11),character(point+12)) ;
  859.       if (int_num <= 0)
  860.      point = 0 ;        /* go to top of file */
  861.       else
  862.      {
  863.      if (curr_int < 0)
  864.         point = 0 ;        /* go to top of file */
  865.      strcpy(search_str,"----------") ;
  866.      search_str[10] = hex_digit((int_num-1) / 16) ;
  867.      search_str[11] = hex_digit((int_num-1) % 16) ;
  868.      search_str[12] = '\0' ;
  869.      search( (int_num<=curr_int)?-1:1, search_str) ;
  870.      to_begin_line() ;
  871.      }
  872.       }
  873.    else
  874.       point = 0 ;
  875.    if (!scan_for_entry(int_id,extra_string,&first_entry))
  876.       {
  877.       say("%s not found.",entry_name) ;
  878.       if (first_entry)
  879.      {
  880.      mark = start ;
  881.      point = first_entry ;
  882.      }
  883.       else
  884.      point = start ;
  885.       }
  886.    if (has_arg)
  887.      iter = 1 ;                /* don't search repeatedly */
  888.    return 0 ;
  889. }
  890.  
  891. /*=============================================================*/
  892. /*=============================================================*/
  893.  
  894. command goto_int() on intlist_tab[FCTRL(12)]
  895. {
  896.    char entry_name[60], def_entry[60] ;
  897.    int start = point ;
  898.  
  899.    to_begin_line() ;
  900.    if (parse_string(1,"SeeAlso: ",NULL) != 0)
  901.       {
  902.       point += 9 ;        /* skip the SeeAlso: */
  903.       if (point < start)    /* if we were originally to the right of     */
  904.      point = start ;    /* current position, go back to original pos */
  905.       grab_int_reference(def_entry) ;
  906.       get_strdef(entry_name,"Goto Interrupt",def_entry) ;
  907.       }
  908.    else if (line_has_see_also())
  909.       {
  910.       grab_int_reference(def_entry) ;
  911.       get_strdef(entry_name,"Goto Interrupt",def_entry) ;
  912.       }
  913.    else
  914.       get_string(entry_name,"Goto Interrupt: ") ;
  915.    point = start ;
  916.    goto_entry(entry_name) ;
  917.    if (has_arg)
  918.       iter = 1 ;
  919. }
  920.  
  921. /*=============================================================*/
  922. /*=============================================================*/
  923.  
  924. void fix_unnumbered_tables()
  925. {
  926.    int matchsize ;
  927.    
  928.    point = 0 ;
  929.    while (search(1,"\n\n"))
  930.       {
  931.       switch(curchar())
  932.      {
  933.      case 'C':
  934.         if (parse_string(1,"Call ") != 0)
  935.            {
  936.            /* we got Call..., we know it doesn't have a table number */
  937.            insert_table_counter() ;
  938.            stuff("\n") ;
  939.            }
  940.         break ;
  941.      case 'V':
  942.         if (parse_string(1,"Values ") != 0)
  943.            {
  944.            /* we know this Values... doesn't have a table number */
  945.            insert_table_counter() ;
  946.            stuff("\n") ;
  947.            }
  948.         break ;
  949.      case 'B':
  950.         if (parse_string(1,"Bitfields ",0) == 0)
  951.            break ;
  952.         nl_forward() ;    /* skip to start of next line */
  953.         if (parse_string(1,".*\t%(Table ",0) == 0)
  954.            {
  955.            /* if the pattern didn't match, there is no table number, */
  956.            /* so add it */
  957.            to_end_line() ;
  958.            matchsize = parse_string(-1,"[ \t]+",0) ;
  959.            if (matchsize)
  960.           delete(point-matchsize,point) ;
  961.            stuff("\t") ;
  962.            insert_table_counter() ;
  963.            }
  964.         break ;
  965.      case 'F':
  966.         if (parse_string(1,"Format ",0) == 0)
  967.            break ;
  968.         nl_forward() ;    /* skip to start of next line */
  969.         if (parse_string(1,".*\t%(Table ",0) == 0)
  970.            {
  971.            /* if the pattern didn't match, there is no table number, */
  972.            /* so add it */
  973.            to_end_line() ;
  974.            matchsize = parse_string(-1,"[ \t]+",0) ;
  975.            if (matchsize)
  976.           delete(point-matchsize,point) ;
  977.            stuff("\t") ;
  978.            insert_table_counter() ;
  979.            }
  980.         break ;
  981.      default:
  982.         /* not a table header, so ignore it */
  983.         break ;
  984.      }
  985.       }
  986. }
  987.  
  988. /*=============================================================*/
  989. /*=============================================================*/
  990.  
  991. int *gather_table_numbers(number_of_tables)
  992. int *number_of_tables ;
  993. {
  994.    int i, num_tables ;
  995.    int tcount = 0 ;
  996.    char counter[5] ;
  997.    int *new_numbers ;
  998.    int old_number ;
  999.    save_var case_fold = 0 ;
  1000.    
  1001.    grab(*table_counter,*table_counter+4,counter) ;
  1002.    num_tables = strtoi(counter,10) ;
  1003.    new_numbers = (int *)malloc((num_tables+2)*sizeof(int)) ;
  1004.    for (i = 0 ; i <= num_tables ; i++)
  1005.       new_numbers[i] = 0 ;
  1006.    point = 0 ;
  1007.    while (search(1,"(Table "))
  1008.       {
  1009.       grab(point,point+4,counter) ;
  1010.       old_number = strtoi(counter,10) ;
  1011.       if (old_number > 0 && old_number <= num_tables)
  1012.      new_numbers[old_number] = ++tcount ;
  1013.       }
  1014.    if (number_of_tables)
  1015.       *number_of_tables = num_tables ;
  1016.    return new_numbers ;
  1017. }
  1018.  
  1019. /*=============================================================*/
  1020. /*=============================================================*/
  1021.  
  1022. int adjust_table_numbers(num_tables,new_numbers)
  1023. int num_tables ;
  1024. int *new_numbers ;
  1025. {
  1026.    char counter[5] ;
  1027.    int old_number ;
  1028.    int dangling = 0 ;
  1029.    
  1030.    point = 0 ;
  1031.    while (search(1,"(Table "))
  1032.       {
  1033.       grab(point,point+4,counter) ;
  1034.       old_number = strtoi(counter,10) ;
  1035.       if (old_number > 0 && old_number <= num_tables)
  1036.      {
  1037.      delete(point,point+4) ;
  1038.      bprintf("%04d",new_numbers[old_number]) ;
  1039.      }
  1040.       }
  1041.    point = 0 ;
  1042.    while (re_search(1,"[, \t]%#[0-9][0-9][0-9][0-9]"))
  1043.       {
  1044.       grab(point-4,point,counter) ;
  1045.       old_number = strtoi(counter,10) ;
  1046.       if (old_number > 0 && old_number <= num_tables)
  1047.      {
  1048.      if (new_numbers[old_number])
  1049.         {
  1050.         delete(point-4,point) ;
  1051.         bprintf("%04d",new_numbers[old_number]) ;
  1052.         }
  1053.      else /* dangling xref */
  1054.         {
  1055.         dangling++ ;
  1056.         point -= 4 ;
  1057.         stuff("?") ;
  1058.         point += 4 ;
  1059.         }
  1060.      }
  1061.       }
  1062.    return dangling ;
  1063. }
  1064.  
  1065. /*=============================================================*/
  1066. /*=============================================================*/
  1067.  
  1068. command renumber_tables()
  1069. {
  1070.    int number_of_tables ;
  1071.    int *new_numbers ;
  1072.    spot start = alloc_spot(1) ;
  1073.    int dangling ;
  1074.    
  1075.    *start = point ;
  1076.    say("Pass 1: numbering unnumbered tables") ;
  1077.    fix_unnumbered_tables() ;
  1078.    say("Pass 2: gathering table numbers") ;
  1079.    new_numbers = gather_table_numbers(&number_of_tables) ;
  1080.    say("Pass 3: adjusting table numbers") ;
  1081.    dangling = adjust_table_numbers(number_of_tables,new_numbers) ;
  1082.    free(new_numbers) ;
  1083.    if (dangling)
  1084.       say("%d dangling cross-references, search for '#?'",dangling) ;
  1085.    else
  1086.       say("Done") ;
  1087.    point = *start ;
  1088.    free_spot(start) ;
  1089. }
  1090.  
  1091. /*=============================================================*/
  1092. /*=============================================================*/
  1093.  
  1094. void find_table_counter()
  1095. {
  1096.    save_var point = (size() > 10000) ? size() - 10000 : 0 ;
  1097.  
  1098.    search(1,"Highest Table Number = ") ;
  1099.    table_counter = alloc_spot(1) ;
  1100. }
  1101.  
  1102. /*=============================================================*/
  1103. /* Put the current buffer into IntList major mode           */
  1104. /*=============================================================*/
  1105.  
  1106. command intlist_mode()
  1107. {
  1108.    mode_keys = intlist_tab ;
  1109.    intlist_tab[')'] = intlist_tab[']'] = (short) show_matching_delimiter;
  1110.    delete_hacking_tabs = 0 ;
  1111.    major_mode = strsave("IntList") ;
  1112.    make_mode() ;
  1113.    auto_indent = 0 ;
  1114.    margin_right = 79 ;
  1115.    want_backups = 1 ;
  1116.    undo_size = 100000 ;     /* less than default 500,000 since list is so big */
  1117.    find_table_counter() ;
  1118. }
  1119.  
  1120. when_loading()
  1121. {
  1122.    char *curbuf ;
  1123.  
  1124.    want_backups = want_backups.default = 1 ;
  1125.    strcpy(backup_name,"%pbak/%b%e") ;        /* put backups in BAK subdir */
  1126.    one_window() ;
  1127.    intlist_mode() ;
  1128.    if (exist("interrup.1st"))
  1129.       {
  1130.       curbuf = bufname ;
  1131.       bufname = "interrup.1st" ;
  1132.       intlist_mode() ;
  1133.       bufname = curbuf ;
  1134.       }
  1135. /* Epsilon v6.0+ */
  1136.    strcpy(mode_end," %d%p %S") ;
  1137. }
  1138.  
  1139. /*=============================================================*/
  1140. /* automagically switch into interrupt list mode on .LST and .1ST files */
  1141.  
  1142. suffix_lst()   { intlist_mode(); }
  1143. suffix_1st()   { intlist_mode(); }
  1144.  
  1145.  
  1146.