home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 24 / CD_ASCQ_24_0995.iso / dos / tools / inter47 / intlist.e < prev    next >
Text File  |  1995-08-12  |  37KB  |  1,291 lines

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