TEACL is a fork of TECOC created for the purpose of describing diffs in a document being collaboratively edited
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1095 lines
49 KiB

  1. /*****************************************************************************
  2. TECO-C (version number is defined as TVERSION in file TECOC.H)
  3. Copyright 1983, 1990 by Pete Siemsen. This software is provided to
  4. you free of charge for your own use. Use it as you see fit; if it doesn't
  5. work, I disclaim all responsibility. You may re-distribute this software
  6. UNCHANGED only if you include this copy-right notice. Alternatively, if
  7. you change this software, you may re-distribute the result only if you
  8. include BOTH this copyright notice, AND an additional notice identifying
  9. you and indicating that you have changed the software.
  10. This program is still under development. See file PROBLEMS.TXT for
  11. notes I've written to myself about things to do to the program. If you
  12. modify this code to enhance it or fix a bug, please communicate the changes
  13. to me. My address is
  14. Pete Siemsen
  15. 645 Ohio Avenue #302
  16. Long Beach, Ca. 90814
  17. (213) 433-3059 (home)
  18. (213) 740-7391 (work)
  19. Internet: siemsen@usc.edu
  20. The file PG.MEM (programmer's guide) contains documentation explaining
  21. algorithms used in TECO-C. File PROBLEMS.TXT is a notes file listing ideas
  22. and known bugs.
  23. Global variable declarations for system-independent variables are
  24. in this file.
  25. *****************************************************************************/
  26. #include "zport.h" /* define portability identifiers */
  27. #include "tecoc.h" /* define general identifiers */
  28. #include "defext.h" /* define external global variables */
  29. #include "deferr.h" /* define identifiers for error messages */
  30. #include "dscren.h" /* define UNTERM */
  31. /*****************************************************************************
  32. Test for inconsistencies in the identifiers defined in the include
  33. files. The ANSI C way to complain is to use #error, but some compilers
  34. will complain even when the tests succeed, because they don't recognize the
  35. #error directive while they scan for #endif. The goofy "include" statements
  36. are used to generate a compile-time error.
  37. *****************************************************************************/
  38. #if GAPMIN > EBFINIT
  39. #include ">>> GAPMIN can't be greater than EBFINIT <<<"
  40. #endif
  41. #if IBFMIN > IBFINIT
  42. #include ">>> IBFMIN can't be greater than IBFINIT <<<"
  43. #endif
  44. #if IBFEXP < IBFMIN
  45. #include ">>> IBFEXP can't be less than IBFMIN <<<"
  46. #endif
  47. #if NIFDBS < 3
  48. #include ">>> NIFDBS can't be less than 3 <<<"
  49. #endif
  50. #if ZBFEXP < ZBFMIN
  51. #include ">>> ZBFEXP can't be less than ZBFMIN <<<"
  52. #endif
  53. /*****************************************************************************
  54. These pointers point to the first and last characters in an "area",
  55. which is specified when an m,n argument pair precedes a TECO command. For
  56. instance, when the command 10,25T is executed, the GetAra function is called
  57. to set these pointers, which are then used to display the text.
  58. *****************************************************************************/
  59. GLOBAL charptr AraBeg; /* start of m,n area */
  60. GLOBAL charptr AraEnd; /* end of m,n area */
  61. /*****************************************************************************
  62. ArgPtr points to the first character of the text argument associated
  63. with a TECO-C command. It is set by the FindES (find end-of-string) function.
  64. When a command that has a text argument is executed, FindES is called to
  65. locate the end of the text argument. FindES moves the command pointer CBfPtr
  66. to the end of the text argument, and remembers where the beginning was using
  67. ArgPtr.
  68. *****************************************************************************/
  69. GLOBAL charptr ArgPtr; /* start of text argument of a cmd */
  70. /*****************************************************************************
  71. These variables point to the beginning and end of the command string
  72. buffer. Memory for the command string buffer is allocated in the MemIni
  73. function. CBfBeg always points to this buffer, but CStBeg changes when an M
  74. or EI command is executed.
  75. *****************************************************************************/
  76. GLOBAL charptr CBfBeg; /* command buffer beginning */
  77. GLOBAL charptr CBfEnd; /* command buffer end */
  78. /*****************************************************************************
  79. CBfPtr is the command string buffer pointer, which moves across a
  80. command string as it is executed. CBfPtr usually points into the command
  81. string buffer pointed to by CBfBeg, but it points elsewhere when an M or EI
  82. command is being executed.
  83. *****************************************************************************/
  84. GLOBAL charptr CBfPtr; /* command buffer pointer */
  85. /*****************************************************************************
  86. When TECO-C is executing a command string, it looks at each command
  87. (1 or 2 characters) and calls a function to implement the command. Some
  88. commands can be modified by preceding the command with a modifier character.
  89. CmdMod contains bits which are set when a modifier character is "executed".
  90. This variable is cleared by most commands before they successfully return.
  91. The bits in CmdMod relate to the at-sign (@), colon (:), double-colon (::)
  92. modifiers. There is also a bit which indicates that a command has 2 numeric
  93. arguments separated by a comma.
  94. *****************************************************************************/
  95. GLOBAL char CmdMod;
  96. /*****************************************************************************
  97. These variables point to the beginning and end of the executing
  98. command string, whether that command string is in the command buffer, a
  99. q-register or the EI buffer.
  100. *****************************************************************************/
  101. GLOBAL charptr CStBeg; /* start of command string */
  102. GLOBAL charptr CStEnd; /* end of command string */
  103. /*****************************************************************************
  104. CurInp and CurOut are indices into the IFiles and OFiles arrays,
  105. respectively. They indicate the entries for the current input stream and
  106. current output stream.
  107. *****************************************************************************/
  108. GLOBAL DEFAULT CurInp = PINPFL;
  109. GLOBAL DEFAULT CurOut = POUTFL;
  110. /*****************************************************************************
  111. These variables point to the digit buffer. When TECO-C needs to
  112. convert a binary number into an ASCII string, the string is generated in this
  113. buffer. The buffer is large enough to hold the largest integer represented
  114. by 32 bits, plus an optional sign and maybe a carriage-return/line-feed pair.
  115. *****************************************************************************/
  116. GLOBAL charptr DBfBeg; /* digit buffer */
  117. GLOBAL charptr DBfPtr; /* digit buffer pointer */
  118. /*****************************************************************************
  119. These variables point to the first and last characters in the edit
  120. buffer. See file PG.MEM for a description of memory management.
  121. *****************************************************************************/
  122. GLOBAL charptr EBfBeg; /* first character in edit buffer */
  123. GLOBAL charptr EBfEnd; /* last character in edit buffer */
  124. /*****************************************************************************
  125. EBPtr1 is used when a search is being performed. It is adjusted when
  126. the edit buffer is being scanned for the first character of the search string.
  127. When a search command succeeds, this pointer is left pointing to the first
  128. character of the found string.
  129. *****************************************************************************/
  130. GLOBAL charptr EBPtr1;
  131. /*****************************************************************************
  132. EBPtr2 is used when a search is being performed. After a character
  133. matching the first character of the search string is found, this pointer is
  134. adjusted as each remaining character of the search string is compared with
  135. the edit buffer. When a search command succeeds, this pointer is left
  136. pointing to the last character of the found string.
  137. *****************************************************************************/
  138. GLOBAL charptr EBPtr2;
  139. /*****************************************************************************
  140. Bits within EdFlag have the following meanings:
  141. 1 Allow caret (^) in search strings
  142. 2 Allow Y and _ commands to destroy edit buffer
  143. 4 Don't arbitrarily expand memory
  144. 16 preserve dot on failing searches
  145. 64 only move dot by one on multiple occurrence searches
  146. *****************************************************************************/
  147. GLOBAL WORD EdFlag = 0; /* ED mode control flag */
  148. /*****************************************************************************
  149. Bits within EhFlag have the following meanings:
  150. 3 how much error message to display
  151. 4 display failing command string after errors
  152. *****************************************************************************/
  153. GLOBAL WORD EhFlag = 0; /* EH mode control flag */
  154. /*****************************************************************************
  155. EndSAr is used by search code to point to the end of the area to be
  156. searched.
  157. *****************************************************************************/
  158. GLOBAL charptr EndSAr; /* end of search area */
  159. /*****************************************************************************
  160. Several TECO error messages take an argument. For instance, the
  161. "illegal command" error message shows the user the illegal command. When
  162. these kinds of messages are required, ErrTxt is used to send the text
  163. of the argument to the error display function (ErrMsg).
  164. *****************************************************************************/
  165. GLOBAL char ErrTxt[6]; /* holds part of error message */
  166. /*****************************************************************************
  167. The EsFlag flag controls what is displayed on the terminal after every
  168. successful search command completes. EsFlag has the following meanings:
  169. 0 don't display anything
  170. -1 display the line containing the found string
  171. 1-31 display the line containing the found string,
  172. with a line feed at the character position
  173. 32-126 display the line containing the found string,
  174. with the character whose ASCII code is represented
  175. by ES at the character position
  176. m*265+n n has the meanings defined above. m is the number
  177. of lines above and below the found string to be
  178. displayed.
  179. *****************************************************************************/
  180. GLOBAL WORD EsFlag = 0; /* ES mode control flag */
  181. /*****************************************************************************
  182. The expression stack contains the components of TECO's numeric
  183. expressions. Each entry on the expression stack is either an OPERAND or
  184. an OPERATOR (like +, -, /, *).
  185. *****************************************************************************/
  186. GLOBAL struct EStck EStack[EXS_SIZE]; /* expression stack */
  187. GLOBAL WORD EStBot; /* expression stack bottom */
  188. GLOBAL WORD EStTop; /* top of expression stack */
  189. /*****************************************************************************
  190. Bits in EtFlag control TECO's handling of the terminal. Definitions
  191. of masks for each bit and the meaning of each bit can be found in TECOC.H.
  192. Bits in EtFlag are initialized when the terminal is set up in the ZTrmnl
  193. function.
  194. *****************************************************************************/
  195. GLOBAL WORD EtFlag = 0; /* ET mode control flag */
  196. /*****************************************************************************
  197. The EuFlag is TECO's case mode control flag. This flag allows TECO to
  198. be used to input and output upper and lower case characters even if the
  199. terminal being used is capable of displaying only uppercase characters. If
  200. the EU flag is -1, no case flagging is performed on type-out. If the EU flag
  201. is 0, lowercase characters are converted to uppercase on type-out, and are
  202. preceded by a ' character. If the EU flag is 1, then lowercase characters
  203. are converted to uppercase on type-out, but uppercase characters are
  204. preceded by a ' character.
  205. *****************************************************************************/
  206. GLOBAL WORD EuFlag = EU_NONE; /* EU mode control flag */
  207. /*****************************************************************************
  208. The EV mode control flag controls what is displayed on the terminal
  209. after every successful command string completes. By default, nothing is
  210. displayed (EV is 0). EV has the following meanings:
  211. 0 don't display anything
  212. -1 display the line containing the character position
  213. 1-31 display the line containing the character position,
  214. with a line feed at the character position
  215. 32-126 display the line containing the character position,
  216. with the character whose ASCII code is represented
  217. by ES at the character position
  218. m*265+n n has the meanings defined above. m is the number
  219. of lines above and below the character position to be
  220. displayed.
  221. *****************************************************************************/
  222. GLOBAL WORD EvFlag = 0; /* EV mode control flag */
  223. /*****************************************************************************
  224. These variables point to the filename buffer.
  225. *****************************************************************************/
  226. GLOBAL charptr FBfBeg; /* first char of filename buffer */
  227. GLOBAL charptr FBfEnd; /* last chr (+1) of filename buffer */
  228. GLOBAL charptr FBfPtr; /* pointer into file spec buffer */
  229. /*****************************************************************************
  230. Bits in the EzFlag are system-specific. See the system-specific
  231. file for each operating system (like ZVMS.C, ZUNIX.C, etc) for the meanings
  232. of these bits.
  233. *****************************************************************************/
  234. GLOBAL WORD EzFlag = 0; /* EZ mode control flag */
  235. /*****************************************************************************
  236. FFPage is the value which is returned by the ^E command. It is -1 if
  237. the buffer currently contains a page of text that was terminated by a form
  238. feed in the input file. It is 0 if the buffer contains only part of a page
  239. from the input file (because the input page filled the text buffer before it
  240. was completely read in). The FFPage flag is tested by the P command and
  241. related operations to determine if a form feed should be appended to the
  242. contents of the buffer when it is output.
  243. *****************************************************************************/
  244. GLOBAL LONG FFPage = 0; /* form feed flag (see ^E command) */
  245. /*****************************************************************************
  246. These variables point to the first and last characters in the edit
  247. buffer gap. See file PG.MEM for a description of memory management.
  248. *****************************************************************************/
  249. GLOBAL charptr GapBeg; /* first char in edit buffer gap */
  250. GLOBAL charptr GapEnd; /* last char in edit buffer gap */
  251. /*****************************************************************************
  252. GotCtC indicates that the user has interrupted the normal execution
  253. of TECO-C by typing a control-C. This variable is set by the special
  254. interrupt-handling function executed when a control-C is struck, and is
  255. cleared before a command string is entered. It is tested each time a command
  256. terminates and when certain commands execute time-consuming loops.
  257. *****************************************************************************/
  258. GLOBALV BOOLEAN GotCtC = FALSE;
  259. /*****************************************************************************
  260. IBfEnd is the end of the input buffer. See file PG.MEM for a
  261. description of memory management.
  262. *****************************************************************************/
  263. GLOBAL charptr IBfEnd;
  264. /*****************************************************************************
  265. IniSrM is the initial search mode. It is used when parsing search
  266. strings and filenames. The value of this variable is set by ^V and
  267. ^W characters and is used to explicitly control the case (upper or lower) of
  268. characters in a string. It can take on the values LOWER, UPPER or NONE,
  269. which are defined in TECOC.H.
  270. *****************************************************************************/
  271. GLOBAL int IniSrM = NONE;
  272. /*****************************************************************************
  273. IsOpnI and IsOpnO contain indicators about the status of the file
  274. data blocks in the IFiles and OFiles arrays, respectively. An element has
  275. the value TRUE when the corresponding file data block reflects an opened file.
  276. IsEofI indicates that the corresponding element of IFiles reflects a file
  277. that has reached the end.
  278. *****************************************************************************/
  279. GLOBAL BOOLEAN IsEofI[NIFDBS];
  280. GLOBAL BOOLEAN IsOpnI[NIFDBS];
  281. GLOBAL BOOLEAN IsOpnO[NOFDBS];
  282. /*****************************************************************************
  283. LstErr holds the code for the last error reported by TECO-C. It is
  284. set in the error display function (ErrMsg) and used when the user executes
  285. the ? or / immediate mode commands, to print out more information about the
  286. last error that occurred.
  287. *****************************************************************************/
  288. GLOBAL WORD LstErr = ERR_XXX; /* number of last error message */
  289. /*****************************************************************************
  290. The loop stack maintains pointers to the first character of each loop
  291. (the character following the "<"). LStTop is the element of LStack that
  292. relates to the most recently executed "<" command. LStBot is the index of
  293. the bottom of the stack, so that if (LStTop == LStBot), we're not in a loop
  294. in the current macro level. When a macro is entered, LStTop and LStBot are
  295. saved on the macro stack, and LStBot is set to LStTop, so that LStBot
  296. defines the bottom of the LStack frame for the new macro level.
  297. *****************************************************************************/
  298. GLOBAL WORD LStBot; /* bottom of loop stack */
  299. GLOBAL struct LStck LStack[LPS_SIZE]; /* loop stack */
  300. GLOBAL WORD LStTop; /* top of loop stack */
  301. /*****************************************************************************
  302. MArgmt contains the m part of an m,n argument pair that precedes a
  303. TECO command. For instance, MArgmt would contain 10 when the command
  304. 10,45T is being executed.
  305. *****************************************************************************/
  306. GLOBAL LONG MArgmt; /* m part of m,n numeric arguments */
  307. /*****************************************************************************
  308. MAtchd is used to indicate that a match has been found for a search
  309. string. It is only used when a search command is being executed.
  310. *****************************************************************************/
  311. GLOBAL BOOLEAN Matchd; /* indicates successful search */
  312. /*****************************************************************************
  313. These variables implement the macro stack. When TECO executes a
  314. macro, it must first save the current state, so that the state can be
  315. restored when the macro has finished executing. Each entry in the macro
  316. stack preserves the critical variables for one macro call.
  317. *****************************************************************************/
  318. GLOBAL struct MStck MStack[MCS_SIZE]; /* macro stack */
  319. GLOBAL WORD MStTop = -1; /* top of macro stack */
  320. /*****************************************************************************
  321. NArgmt holds the numeric argument that precedes a command. It is set
  322. by a call to the GetNmA function. When the command is preceded by an m,n
  323. argument pair, NArgmt holds the value of the n argument.
  324. *****************************************************************************/
  325. GLOBAL LONG NArgmt; /* n argument (n part of m,n) */
  326. /*****************************************************************************
  327. QR is a pointer to a structure which defines a q-register.
  328. It is set by calling the FindQR function. Whenever a command that uses a
  329. q-register is executed, FindQR is called first to set QR.
  330. *****************************************************************************/
  331. GLOBAL QRptr QR;
  332. /*****************************************************************************
  333. The structures in the QRgstr array represent the global and main-level
  334. local q-registers. The 0-9 elements are for global digit q-registers (0-9),
  335. the 10-35 elements are for global alphabetic q-registers (a-z or A-Z), the
  336. 36-45 elements are for main-level local digit q-registers (.0-.9) and the
  337. 46-71 elements are for main-level local alphabetic q-registers (.a-.z or
  338. .A-.Z). Local q-registers at macro levels other than the main level are
  339. allocated dynamically.
  340. *****************************************************************************/
  341. GLOBAL struct QReg QRgstr[72];
  342. /*****************************************************************************
  343. QStack is the q-register stack, accessed via the [ and ] commands.
  344. *****************************************************************************/
  345. GLOBAL struct QReg QStack[QRS_SIZE]; /* q-register stack */
  346. GLOBAL WORD QStTop = -1; /* top of q-register stack */
  347. /*****************************************************************************
  348. RefLen is the length of the last inserted string or found search
  349. string. It is accessed by the ^S command.
  350. *****************************************************************************/
  351. GLOBAL LONG RefLen = 0; /* returned by ^S */
  352. /*****************************************************************************
  353. Radix is TECO's radix, usually 10. It is set by the ^D, ^O and ^R
  354. commands.
  355. *****************************************************************************/
  356. GLOBAL DEFAULT Radix = 10; /* TECO's current radix */
  357. /*****************************************************************************
  358. When searching, this pointer points to the farthest-right character
  359. in the area to be searched. It is used after the first character of a string
  360. has been found, to indicate the limit of the area in the edit buffer that
  361. should be checked against the remaining characters in the search string.
  362. *****************************************************************************/
  363. GLOBAL charptr RhtSid;
  364. /*****************************************************************************
  365. These variables point to the search string buffer. The search buffer
  366. is allocated by function MemIni.
  367. *****************************************************************************/
  368. GLOBAL charptr SBfBeg = NULL; /* start of search buffer */
  369. GLOBAL charptr SBfEnd; /* end search buffer */
  370. GLOBAL charptr SBfPtr; /* end of search string buffer */
  371. /*****************************************************************************
  372. SIncrm is the value added to the search pointer when the edit buffer
  373. is being searched. If SIncrm is 1, then the search proceeds in a forward
  374. direction. If SIncrm is -1, then the search proceeds in a backward
  375. direction. By using this variable, the rather complex code that implements
  376. searching can easily be used to search in either direction.
  377. *****************************************************************************/
  378. GLOBAL LONG SIncrm; /* search increment */
  379. /*****************************************************************************
  380. SMFlag is TECOC's search mode flag, and controls case sensitivity
  381. during searches. This variable holds the value of the ^X command.
  382. *****************************************************************************/
  383. GLOBAL WORD SMFlag = 0; /* search mode control flag (^X) */
  384. /*****************************************************************************
  385. SrcTyp is used to "remember" the kind of search command that we're
  386. working on. The same search code is used by all the search commands, but
  387. each search command is slightly different than the others. The common
  388. search code tests this variable to implement the differences.
  389. *****************************************************************************/
  390. GLOBAL WORD SrcTyp; /* type of search (E_SEARCH, etc) */
  391. /*****************************************************************************
  392. SStPtr points into the search buffer, and is used only by the search
  393. code.
  394. *****************************************************************************/
  395. GLOBAL charptr SStPtr; /* search string pointer */
  396. /*****************************************************************************
  397. This table serves two functions. It is used by the character macros
  398. defined in CHMACS.H. It is also used by the command line input code in
  399. function ReadCS.
  400. The top four bits of each mask are used by the functions in CHMACS.H.
  401. The top four bits are masks used to represent "uppercase", "lowercase",
  402. "digit" and "line terminator".
  403. The bottom four bits of each mask are used by function ReadCS. They
  404. are treated as a number and are used in a SWITCH statement. In ReadCS, the
  405. top four bits of each mask are not used.
  406. *****************************************************************************/
  407. unsigned char ChrMsk[256] =
  408. {
  409. RCS_DEF, /* null */
  410. RCS_CCH, /* ^A */
  411. RCS_CCH, /* ^B */
  412. RCS_CTC, /* ^C */
  413. RCS_CCH, /* ^D */
  414. RCS_CCH, /* ^E */
  415. RCS_CCH, /* ^F */
  416. RCS_CTG, /* ^G (bell) */
  417. RCS_BS, /* ^H (bs) */
  418. RCS_DEF, /* ^I (tab) */
  419. RCS_LF | CM_LINE_TERM, /* ^J (lf) */
  420. RCS_VF | CM_LINE_TERM, /* ^K (vt) */
  421. RCS_VF | CM_LINE_TERM, /* ^L (ff) */
  422. RCS_CR, /* ^M (cr) */
  423. RCS_CCH, /* ^N */
  424. RCS_CCH, /* ^O */
  425. RCS_CCH, /* ^P */
  426. RCS_CCH, /* ^Q */
  427. RCS_CCH, /* ^R */
  428. RCS_CCH, /* ^S */
  429. RCS_CCH, /* ^T */
  430. RCS_CTU, /* ^U */
  431. RCS_CCH, /* ^V */
  432. RCS_CCH, /* ^W */
  433. RCS_CCH, /* ^X */
  434. RCS_CCH, /* ^Y */
  435. RCS_CTZ, /* ^Z */
  436. 0, /* escape */
  437. RCS_CCH, /* FS */
  438. RCS_CCH, /* GS */
  439. RCS_CCH, /* RS */
  440. RCS_CCH, /* US */
  441. RCS_SP, /* space */
  442. RCS_DEF, /* ! */
  443. RCS_DEF, /* " */
  444. RCS_DEF, /* # */
  445. RCS_DEF, /* $ */
  446. RCS_DEF, /* % */
  447. RCS_DEF, /* | */
  448. RCS_DEF, /* ' */
  449. RCS_DEF, /* ( */
  450. RCS_DEF, /* ) */
  451. RCS_AST, /* * */
  452. RCS_DEF, /* + */
  453. RCS_DEF, /* , */
  454. RCS_DEF, /* - */
  455. RCS_DEF, /* . */
  456. RCS_DEF, /* / */
  457. RCS_DEF | CM_DIGIT, /* 0 */
  458. RCS_DEF | CM_DIGIT, /* 1 */
  459. RCS_DEF | CM_DIGIT, /* 2 */
  460. RCS_DEF | CM_DIGIT, /* 3 */
  461. RCS_DEF | CM_DIGIT, /* 4 */
  462. RCS_DEF | CM_DIGIT, /* 5 */
  463. RCS_DEF | CM_DIGIT, /* 6 */
  464. RCS_DEF | CM_DIGIT, /* 7 */
  465. RCS_DEF | CM_DIGIT, /* 8 */
  466. RCS_DEF | CM_DIGIT, /* 9 */
  467. RCS_DEF, /* : */
  468. RCS_DEF, /* ; */
  469. RCS_DEF, /* < */
  470. RCS_DEF, /* = */
  471. RCS_DEF, /* > */
  472. RCS_DEF, /* ? */
  473. RCS_DEF, /* @ */
  474. RCS_DEF | CM_UPPER, /* A */
  475. RCS_DEF | CM_UPPER, /* B */
  476. RCS_DEF | CM_UPPER, /* C */
  477. RCS_DEF | CM_UPPER, /* D */
  478. RCS_DEF | CM_UPPER, /* E */
  479. RCS_DEF | CM_UPPER, /* F */
  480. RCS_DEF | CM_UPPER, /* G */
  481. RCS_DEF | CM_UPPER, /* H */
  482. RCS_DEF | CM_UPPER, /* I */
  483. RCS_DEF | CM_UPPER, /* J */
  484. RCS_DEF | CM_UPPER, /* K */
  485. RCS_DEF | CM_UPPER, /* L */
  486. RCS_DEF | CM_UPPER, /* M */
  487. RCS_DEF | CM_UPPER, /* N */
  488. RCS_DEF | CM_UPPER, /* O */
  489. RCS_DEF | CM_UPPER, /* P */
  490. RCS_DEF | CM_UPPER, /* Q */
  491. RCS_DEF | CM_UPPER, /* R */
  492. RCS_DEF | CM_UPPER, /* S */
  493. RCS_DEF | CM_UPPER, /* T */
  494. RCS_DEF | CM_UPPER, /* U */
  495. RCS_DEF | CM_UPPER, /* V */
  496. RCS_DEF | CM_UPPER, /* W */
  497. RCS_DEF | CM_UPPER, /* X */
  498. RCS_DEF | CM_UPPER, /* Y */
  499. RCS_DEF | CM_UPPER, /* Z */
  500. RCS_DEF, /* [ */
  501. RCS_DEF, /* \ */
  502. RCS_DEF, /* ] */
  503. RCS_DEF, /* ^ */
  504. RCS_DEF, /* _ */
  505. RCS_GRV, /* ` */
  506. RCS_LWR | CM_LOWER, /* a */
  507. RCS_LWR | CM_LOWER, /* b */
  508. RCS_LWR | CM_LOWER, /* c */
  509. RCS_LWR | CM_LOWER, /* d */
  510. RCS_LWR | CM_LOWER, /* e */
  511. RCS_LWR | CM_LOWER, /* f */
  512. RCS_LWR | CM_LOWER, /* g */
  513. RCS_LWR | CM_LOWER, /* h */
  514. RCS_LWR | CM_LOWER, /* i */
  515. RCS_LWR | CM_LOWER, /* j */
  516. RCS_LWR | CM_LOWER, /* k */
  517. RCS_LWR | CM_LOWER, /* l */
  518. RCS_LWR | CM_LOWER, /* m */
  519. RCS_LWR | CM_LOWER, /* n */
  520. RCS_LWR | CM_LOWER, /* o */
  521. RCS_LWR | CM_LOWER, /* p */
  522. RCS_LWR | CM_LOWER, /* q */
  523. RCS_LWR | CM_LOWER, /* r */
  524. RCS_LWR | CM_LOWER, /* s */
  525. RCS_LWR | CM_LOWER, /* t */
  526. RCS_LWR | CM_LOWER, /* u */
  527. RCS_LWR | CM_LOWER, /* v */
  528. RCS_LWR | CM_LOWER, /* w */
  529. RCS_LWR | CM_LOWER, /* x */
  530. RCS_LWR | CM_LOWER, /* y */
  531. RCS_LWR | CM_LOWER, /* z */
  532. RCS_DEF, /* { */
  533. RCS_DEF, /* | */
  534. RCS_DEF, /* } */
  535. RCS_DEF, /* ~ */
  536. RCS_DEL, /* delete */
  537. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  538. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  539. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  540. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  541. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  542. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  543. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  544. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  545. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  546. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  547. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  548. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  549. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  550. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  551. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,
  552. RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF,RCS_DEF
  553. };
  554. /*****************************************************************************
  555. TraceM is the trace mode flag. This variable is set to TRUE when
  556. TECO's trace mode is on. When it is set, commands are echoed to the terminal
  557. as they are executed. This mode is used to aid in debugging TECO macros, and
  558. is toggled by the ? command.
  559. If you want to trace the command line parsing macro executed in
  560. ZPrsCL(), set this to TRUE; otherwise, set it to FALSE.
  561. *****************************************************************************/
  562. GLOBAL BOOLEAN TraceM = FALSE; /* trace mode flag */
  563. /*****************************************************************************
  564. CrType is the terminal type. It is used by the ZScrOp function to
  565. drive the few screen capabilities of TECOC. See ZScrOp for a list of the
  566. values that CrType can take.
  567. *****************************************************************************/
  568. GLOBAL DEFAULT CrType = UNTERM; /* terminal type */
  569. #if VIDEO
  570. GLOBAL DEFAULT HldFlg; /* value of 5:W (hold mode flag) */
  571. GLOBAL DEFAULT HtSize; /* value of 1:W (screen width) */
  572. GLOBAL DEFAULT MrkFlg; /* value of 4:W */
  573. GLOBAL DEFAULT ScroLn; /* value of 7:W */
  574. GLOBAL DEFAULT SeeAll; /* value of 3:W */
  575. GLOBAL DEFAULT TopDot; /* value of 6:W */
  576. GLOBAL DEFAULT VtSize; /* value of 2:W (screen height) */
  577. #if CURSES
  578. GLOBAL DEFAULT SpcMrk = 0; /* value of 8:W */
  579. GLOBAL DEFAULT KeyPad; /* value of 9:W */
  580. #endif
  581. #endif
  582. /*****************************************************************************
  583. S t a r t H e r e
  584. *****************************************************************************/
  585. int _Cdecl main(argc, argv) /* _Cdecl defined in ZPORT.H */
  586. int argc;
  587. char **argv;
  588. {
  589. #if CHECKSUM_CODE /* MS-DOS debugging code */
  590. init_code_checksums (); /* calculate code checksums */
  591. #endif
  592. Init(argc, argv); /* initialize TECO */
  593. /*
  594. * read a command string and then execute it. This loop is infinite.
  595. * TECO-C is exited explicitly when a lower-level function calls TAbort.
  596. */
  597. CStBeg = CStEnd = CBfBeg;
  598. CStEnd--;
  599. FOREVER { /* loop forever */
  600. ReadCS(); /* read command string */
  601. CBfPtr = CBfBeg; /* initialize command string ptr */
  602. CmdMod = '\0'; /* clear modifiers flags */
  603. EStTop = EStBot = /* clear expression stack */
  604. LStTop = LStBot = /* clear loop stack */
  605. MStTop = -1; /* clear macro stack */
  606. ExeCSt(); /* execute command string */
  607. }
  608. }
  609. /*****************************************************************************
  610. The following code is support routines for the imbedded debugging code
  611. in TECO-C. If the "DEBUGGING" macro in ZPORT.H is set to "FALSE", then none
  612. of this code is compiled.
  613. *****************************************************************************/
  614. #if DEBUGGING
  615. #include <ctype.h> /* isprint() macro */
  616. #include "dchars.h" /* define identifiers for characters */
  617. static DEFAULT DbgInd = 0; /* debugging indent level */
  618. static DEFAULT DbgLvl = 0; /* debugging message level */
  619. #define DBGSBF 4000 /* huge buffer to avoid overruns */
  620. GLOBAL char DbgSBf[DBGSBF+1]; /* sprintf() buffer for debugging messages */
  621. #if USE_PROTOTYPES
  622. static VVOID DbgDMs( /* debugging, display message */
  623. int DbgFLv, /* function display level */
  624. char *DbgFNm, /* function name */
  625. char *DbgWht, /* "called", "returning", or blank */
  626. char *DbgMsg); /* message to display */
  627. static VVOID DbgDsA(void); /* display address variables */
  628. static VVOID DbgEBf(void); /* display edit buffer details */
  629. static VVOID DbgHlp(void); /* display help message */
  630. static VVOID DbgLSt(void); /* display loop stack details */
  631. static VVOID DbgMSt(void); /* display macro stack details */
  632. static VVOID DbgPrP( /* display a pointer */
  633. char *s,
  634. voidptr ptr);
  635. static VVOID DbgQRg(void); /* display Q-register's */
  636. static VVOID DbgQSt(void); /* display Q-register stack */
  637. static VVOID DbgSLv(void); /* set debugging message level */
  638. #endif
  639. /*****************************************************************************
  640. DbgDsA()
  641. This function displays details about address variables for 1^P.
  642. *****************************************************************************/
  643. static VVOID DbgPrP (s, ptr) /* display a pointer */
  644. char *s;
  645. voidptr ptr;
  646. {
  647. printf ("%s %lu", s, Zcp2ul(ptr));
  648. }
  649. static VVOID DbgDsA()
  650. {
  651. int length;
  652. DbgPrP ("\r\nAraBeg =", AraBeg);
  653. DbgPrP ("\tEBfBeg =", EBfBeg);
  654. DbgPrP ("\tGapBeg =", GapBeg);
  655. DbgPrP ("\r\nAraEnd =", AraEnd);
  656. DbgPrP ("\tEBfEnd =", EBfEnd);
  657. DbgPrP ("\tGapEnd =", GapEnd);
  658. DbgPrP ("\r\nCBfBeg =", CBfBeg);
  659. DbgPrP ("\tCStBeg =", CStBeg);
  660. DbgPrP ("\tFBfBeg =", FBfBeg);
  661. DbgPrP ("\r\nCBfEnd =", CBfEnd);
  662. DbgPrP ("\tCStEnd =", CStEnd);
  663. DbgPrP ("\tFBfEnd =", FBfEnd);
  664. DbgPrP ("\r\nSBfBeg =", SBfBeg);
  665. DbgPrP ("\tEBPtr1 =", EBPtr1);
  666. DbgPrP ("\tEBPtr2 =", EBPtr2);
  667. DbgPrP ("\r\nSBfPtr =", SBfPtr);
  668. DbgPrP ("\tCBfPtr =", CBfPtr);
  669. DbgPrP ("\r\nSBfEnd =", SBfEnd);
  670. DbgPrP ("\tSStPtr =", SStPtr);
  671. printf ("\r\nsearch buffer = \"");
  672. if (SBfPtr != NULL) {
  673. length = (int) (SBfPtr-SBfBeg);
  674. if (length > 40) {
  675. length = 40;
  676. }
  677. printf ("%.*s", length, SBfBeg);
  678. } else {
  679. length = 0;
  680. }
  681. printf("\"\r\n");
  682. }
  683. /*****************************************************************************
  684. DbgEBf()
  685. This function displays details about the edit buffer for 2^P.
  686. *****************************************************************************/
  687. static VVOID DbgEBf()
  688. {
  689. charptr DbgPtr;
  690. DbgPrP ("\r\nEBfBeg =", EBfBeg);
  691. DbgPrP ("\tGapBeg =", GapBeg);
  692. printf (" (%ld bytes)", (LONG) (GapBeg - EBfBeg));
  693. DbgPrP ("\r\nGapBeg =", GapBeg);
  694. DbgPrP ("\tGapEnd =", GapEnd);
  695. printf (" (%ld bytes)", (LONG) (GapEnd - GapBeg));
  696. DbgPrP ("\r\nGapEnd =", GapEnd);
  697. DbgPrP ("\tEBfEnd =", EBfEnd);
  698. printf (" (%ld bytes)", (LONG) (EBfEnd - GapEnd));
  699. DbgPrP ("\r\nEBfEnd =", EBfEnd);
  700. DbgPrP ("\tIBfEnd =", IBfEnd);
  701. printf (" (%ld bytes)", (LONG) (IBfEnd - EBfEnd));
  702. DbgPrP ("\r\nEBfBeg =", EBfBeg);
  703. DbgPrP ("\tIBfEnd =", IBfEnd);
  704. printf (" (%ld bytes)", (LONG) (IBfEnd - EBfBeg));
  705. for (DbgPtr = EBfBeg; DbgPtr < GapBeg; ++DbgPtr) {
  706. DbgPrP ("\r\nDbgEBf: first half, char at", DbgPtr);
  707. printf((isprint(*DbgPtr) ? " '%c'" : " <%d>"), *DbgPtr);
  708. }
  709. for (DbgPtr = (GapEnd+1); DbgPtr <= EBfEnd; ++DbgPtr) {
  710. DbgPrP ("\r\nDbgEBf: second half, char at", DbgPtr);
  711. printf((isprint(*DbgPtr) ? " '%c'" : " <%d>"), *DbgPtr);
  712. }
  713. puts ("\r");
  714. }
  715. /*****************************************************************************
  716. DbgHlp()
  717. This function displays help on ^P commands for ^P with no arguments.
  718. *****************************************************************************/
  719. static VVOID DbgHlp()
  720. {
  721. puts("\r\n\tArguments to ^P have the following meanings:\r\n");
  722. puts("\t\t^P\tno arguments - display help about ^P\r");
  723. puts("\t\tm,0\tset debugging message level to m (0-5)\r");
  724. puts("\t\t1\tdisplay global address variables\r");
  725. puts("\t\t2\tdisplay details about the edit buffer\r");
  726. puts("\t\t3\tdisplay the loop stack\r");
  727. puts("\t\t4\tdisplay the macro stack\r");
  728. puts("\t\t5\tdisplay details about the q-registers\r");
  729. puts("\t\t6\tdisplay the q-register stack\r\r\r");
  730. }
  731. /*****************************************************************************
  732. DbgLSt ()
  733. This function displays details about the loop stack for 3^P.
  734. *****************************************************************************/
  735. static VVOID DbgLSt()
  736. {
  737. int i;
  738. printf ("\r\nLoop stack: LStBot = %d, LstTop = %d\r\n\n", LStBot, LStTop);
  739. printf (" # LIndex LAddr\r\n");
  740. printf ("-- ---------- ----------\r\n");
  741. for (i = 0; i <= LStTop; ++i) {
  742. printf("%2d %10ld %10lu\r\n",
  743. i, LStack[i].LIndex, Zcp2ul(LStack[i].LAddr));
  744. }
  745. }
  746. /*****************************************************************************
  747. DbgDMs()
  748. This function displays a debugging message at the right indentation
  749. level, in reverse video, if the debugging level is appropriate for the
  750. message. It also optionally calls the consistency_check() and the
  751. check_code_checksums() routines while debugging.
  752. The debugging levels are:
  753. 1 command functions
  754. 2 functions called by command functions
  755. 3 everything but stuff that's too noisy
  756. 4 everything
  757. *****************************************************************************/
  758. static VVOID DbgDMs(DbgFLv, DbgFNm, DbgWht, DbgMsg)
  759. int DbgFLv; /* function display level */
  760. char *DbgFNm; /* function name */
  761. char *DbgWht; /* "called", "returning", or blank */
  762. char *DbgMsg; /* message to display */
  763. {
  764. if (DbgFLv <= DbgLvl) { /* is message at right level */
  765. printf ("%*s", DbgInd, ""); /* indent message */
  766. ZScrOp(SCR_RON); /* turn on reverse video */
  767. printf ("%s: %s %s\r\n",
  768. DbgFNm,
  769. DbgWht,
  770. (DbgMsg == NULL) ? "" : DbgMsg);
  771. ZScrOp(SCR_ROF); /* turn off reverse video */
  772. }
  773. if (DbgMsg == DbgSBf) { /* clear sprintf() buffer */
  774. DbgSBf[0] = '\0';
  775. }
  776. if (DbgSBf[DBGSBF] != '\0') { /* check sprintf() overrun */
  777. puts("DbgSBf[] overrun");
  778. exit(EXIT_FAILURE);
  779. }
  780. /*
  781. * If you enable consistency checking and code checksumming here, pointers
  782. * and code will be checked on every function entry and exit in addition to
  783. * being checked after every successful command execution in ExeCSt().
  784. *
  785. * Enabling code checksumming here r-e-a-l-l-y slows things down.
  786. */
  787. #if CONSISTENCY_CHECKING
  788. check_consistency ();
  789. #endif
  790. #if 0 && CHECKSUM_CODE /* MS-DOS debugging code */
  791. check_code_checksums ();
  792. #endif
  793. }
  794. /*****************************************************************************
  795. DbgFEn()
  796. This function is called as the first thing upon entry to a function.
  797. *****************************************************************************/
  798. VVOID DbgFEn(DbgFLv, DbgFNm, DbgMsg) /* debugging, function entry */
  799. int DbgFLv; /* function display level */
  800. char *DbgFNm; /* function name */
  801. char *DbgMsg; /* a function entry message */
  802. {
  803. DbgInd += 2;
  804. DbgDMs(DbgFLv, DbgFNm, "called", DbgMsg);
  805. }
  806. /*****************************************************************************
  807. DbgFEx()
  808. This function is called as the last thing before a function returns.
  809. *****************************************************************************/
  810. VVOID DbgFEx(DbgFLv, DbgFNm, DbgMsg)
  811. int DbgFLv;
  812. char *DbgFNm;
  813. char *DbgMsg;
  814. {
  815. DbgDMs(DbgFLv, DbgFNm, "returning", DbgMsg);
  816. DbgInd -= 2;
  817. }
  818. /*****************************************************************************
  819. DbgFMs()
  820. This function is called in the middle of a routine if the routine
  821. has something special to say.
  822. *****************************************************************************/
  823. VVOID DbgFMs(DbgFLv, DbgFNm, DbgMsg) /* debugging, function message */
  824. int DbgFLv; /* function display level */
  825. char *DbgFNm; /* function name */
  826. char *DbgMsg; /* a debugging message */
  827. {
  828. DbgDMs(DbgFLv, DbgFNm, "", DbgMsg);
  829. }
  830. /*****************************************************************************
  831. DbgMSt()
  832. This function displays details about the macro stack for 4^P.
  833. *****************************************************************************/
  834. static VVOID DbgMSt()
  835. {
  836. int i;
  837. MSptr MSp;
  838. printf("Macro Stack, MStTop = %d\r\n\n", MStTop);
  839. printf(" # CStBeg CBfPtr CStEnd EStBot EStTop LStBot LStTop QRgstr\r\n");
  840. printf("-- -------- -------- -------- ------ ------ ------ ------ --------\r\n");
  841. for (MSp = MStack, i = 0; i <= MStTop; ++i, ++MSp) {
  842. printf("%2d %8lu %8lu %8lu %6d %6d %6d %6d %8lu\r\n",
  843. i,
  844. Zcp2ul(MSp->CStBeg),
  845. Zcp2ul(MSp->CBfPtr),
  846. Zcp2ul(MSp->CStEnd),
  847. MSp->EStBot,
  848. MSp->EStTop,
  849. MSp->LStBot,
  850. MSp->LStTop,
  851. Zcp2ul(MSp->QRgstr));
  852. }
  853. }
  854. /*****************************************************************************
  855. DbgQRg()
  856. This function displays details about global Q-registers for 5^P.
  857. *****************************************************************************/
  858. static VVOID DbgQRg()
  859. {
  860. int i;
  861. int length;
  862. charptr cp;
  863. QRptr QRp;
  864. printf ("Non-empty Q-registers:\r\n\n");
  865. printf (" # Number Start End_P1 Text (possibly truncated)\r\n");
  866. printf ("-- ------- ------- ------- --------------------------------------------------\r\n");
  867. for (i = 0, QRp = QRgstr; i < 72; ++i, ++QRp) {
  868. if (QRp->Number != 0 || QRp->Start != NULL) {
  869. printf ("%c%c %7ld %7lu %7lu \"",
  870. (i < 36) ? ' ' : '.',
  871. i + ((i <= 9) ? '0' : 'A' - 10),
  872. QRp->Number,
  873. Zcp2ul(QRp->Start),
  874. Zcp2ul(QRp->End_P1));
  875. if (QRp->Start != NULL) {
  876. length = (int) (QRp->End_P1 - QRp->Start);
  877. if (length > 50) {
  878. length = 50;
  879. }
  880. cp = QRp->Start;
  881. while (length-- > 0) {
  882. if (*cp < ' ') {
  883. ZDspCh ('^');
  884. ZDspCh (*cp + '@');
  885. --length;
  886. } else {
  887. ZDspCh (*cp);
  888. }
  889. ++cp;
  890. }
  891. }
  892. printf ("\"\r\n");
  893. }
  894. }
  895. printf ("\r\n");
  896. }
  897. /*****************************************************************************
  898. DbgQSt()
  899. This function displays details about the Q-register stack for 6^P.
  900. *****************************************************************************/
  901. static VVOID DbgQSt()
  902. {
  903. int i;
  904. int length;
  905. charptr cp;
  906. QRptr QRp;
  907. printf("Q-register Stack, QStTop = %d\r\n\n", QStTop);
  908. printf ("# Number Start End_P1 Text (possibly truncated)\r\n");
  909. printf ("-- ------- ------- ------- --------------------------------------------------\r\n");
  910. for (QRp = QStack, i = 0; i <= QStTop; ++i, ++QRp) {
  911. printf ("%2d %7ld %7lu %7lu \"",
  912. i,
  913. QRp->Number,
  914. Zcp2ul(QRp->Start),
  915. Zcp2ul(QRp->End_P1));
  916. if (QRp->Start != NULL) {
  917. length = (int) (QRp->End_P1 - QRp->Start);
  918. if (length > 50) {
  919. length = 50;
  920. }
  921. cp = QRp->Start;
  922. while (length-- > 0) {
  923. if (*cp < ' ') {
  924. ZDspCh ('^');
  925. ZDspCh (*cp + '@');
  926. } else {
  927. ZDspCh (*cp);
  928. }
  929. ++cp;
  930. }
  931. }
  932. printf ("\"\r\n");
  933. }
  934. printf ("\r\n");
  935. }
  936. /*****************************************************************************
  937. DbgSLv()
  938. This function sets DbgLvl, which controls how much debugging
  939. information is displayed as TECO executes. If DbgLvl is 0, no debugging
  940. messages are displayed. If (DbgLvl>=1), then messages are displayed by
  941. all "Exexxx" functions. This means that a message is displayed for each
  942. entry and exit of execution of a single command. If (DbgLvl>=1) then in
  943. addition to the messages displayed for entry and exit of Exexxx functions,
  944. a message is displayed for the "next level down" functions. This scheme
  945. is continued for DbgLvl >= 3, DbgLvl >= 4, etc.
  946. In most cases, setting DbgLvl to 1 and then executing a TECO
  947. command string will reveal an error. For more detail, DbgLvl can be set
  948. to successively higher values. Using DbgLvl, you can trade-off the amount
  949. of time you wait for the messages to go by on the screen with the amount
  950. of detail that's needed.
  951. By using this system, debug messages that are placed into new code
  952. in order to debug it can be left in the code so they're useful later.
  953. *****************************************************************************/
  954. static VVOID DbgSLv()
  955. {
  956. DbgLvl = (DEFAULT)MArgmt;
  957. }
  958. /*****************************************************************************
  959. DbgDsp()
  960. This function provides control of the imbedded debugging system in
  961. TECO-C. An unused command character (currently control-P), when executed by
  962. the user, causes this function to be executed.
  963. Arguments to ^P have the following meanings:
  964. no argument - display help about ^P
  965. m,0 set debugging message level to m
  966. 1 display global address variables
  967. 2 display details about the edit buffer
  968. 3 display the loop stack
  969. 4 display the macro stack
  970. 5 display details about the q-registers
  971. *****************************************************************************/
  972. DEFAULT DbgDsp()
  973. {
  974. if (EStTop == EStBot) { /* if no numeric argument */
  975. ZScrOp(SCR_RON); /* turn on reverse video */
  976. DbgHlp(); /* display debugging help */
  977. ZScrOp(SCR_ROF); /* turn off reverse video */
  978. return SUCCESS;
  979. }
  980. if (GetNmA() == FAILURE) { /* get numeric argument */
  981. return FAILURE;
  982. }
  983. if (CmdMod & MARGIS) { /* if it's m,n^P */
  984. DbgSLv(); /* set DbgLvl */
  985. return SUCCESS;
  986. }
  987. ZScrOp(SCR_RON); /* turn on reverse video */
  988. switch ((int)NArgmt) {
  989. case 1: DbgDsA(); break; /* display address variable details */
  990. case 2: DbgEBf(); break; /* display edit buffer details */
  991. case 3: DbgLSt(); break; /* display loop stack */
  992. case 4: DbgMSt(); break; /* display macro stack */
  993. case 5: DbgQRg(); break; /* display q-registers */
  994. case 6: DbgQSt(); break; /* display q-register stack */
  995. default:
  996. printf("bad argument to ^P command\r\n");
  997. ZScrOp(SCR_ROF); /* turn off reverse video */
  998. return FAILURE;
  999. }
  1000. ZScrOp(SCR_ROF); /* turn off reverse video */
  1001. return SUCCESS;
  1002. }
  1003. #endif /* #if DEBUGGING */
  1004. /*****************************************************************************
  1005. The following code was needed while debugging TECO-C on the IBM PC
  1006. with it's brain-damaged memory addressing scheme. This code checks the
  1007. "consistency" of various pointers, making sure some don't change throughout
  1008. the execution of TECO-C and making sure others are in the right order.
  1009. After init_consistency_check() is called in Init(), the
  1010. check_consistency() code is called in ExeCSt() after the successful
  1011. completion of each command. For more frequent checking, it can also
  1012. be called in the DbgDMs() routine above but then the "DEBUGGING" macro
  1013. in ZPORT.H has to be set to "TRUE" as well.
  1014. If the "CONSISTENCY_CHECKING" macro in ZPORT.H is set to "FALSE",
  1015. then none of this code is compiled.
  1016. *****************************************************************************/
  1017. #if CONSISTENCY_CHECKING
  1018. #if USE_PROTOTYPES
  1019. static int errprt(char *str, voidptr p1, voidptr p2);
  1020. #endif
  1021. static charptr ss_CBfBeg;
  1022. static charptr ss_CBfEnd;
  1023. static charptr ss_FBfBeg;
  1024. static charptr ss_FBfEnd;
  1025. static charptr ss_SBfBeg;
  1026. static charptr ss_SBfEnd;
  1027. VVOID init_consistency_check()
  1028. {
  1029. ss_CBfBeg = CBfBeg;
  1030. ss_CBfEnd = CBfEnd;
  1031. ss_FBfBeg = FBfBeg;
  1032. ss_FBfEnd = FBfEnd;
  1033. ss_SBfBeg = SBfBeg;
  1034. ss_SBfEnd = SBfEnd;
  1035. }
  1036. static int errprt(str, p1, p2)
  1037. char *str;
  1038. voidptr p1;
  1039. voidptr p2;
  1040. {
  1041. printf ("%s (%lu,%lu)\r\n", str, Zcp2ul(p1), Zcp2ul(p2));
  1042. return EXIT_FAILURE;
  1043. }
  1044. #if defined(__TURBOC__) && (__TURBOC__ >= 0x0295)
  1045. #include <alloc.h> /* prototype for heapcheck() */
  1046. #endif
  1047. VVOID check_consistency()
  1048. {
  1049. int ex = EXIT_SUCCESS;
  1050. /*
  1051. * is the heap corrupted?
  1052. */
  1053. #if defined(__TURBOC__) && (__TURBOC__ >= 0x0295)
  1054. if (heapcheck () < 0) {
  1055. puts ("check_consistency: heapcheck failed");
  1056. ex = EXIT_FAILURE;
  1057. }
  1058. #endif
  1059. /*
  1060. * the following point to the start and end of various buffers which are
  1061. * initialized at program startup and should not have changed.
  1062. */
  1063. if (ss_CBfBeg != CBfBeg) ex=errprt("ss_CBfBeg != CBfBeg",ss_CBfBeg,CBfBeg);
  1064. if (ss_CBfEnd != CBfEnd) ex=errprt("ss_CBfEnd != CBfEnd",ss_CBfEnd,CBfEnd);
  1065. if (ss_FBfBeg != FBfBeg) ex=errprt("ss_FBfBeg != FBfBeg",ss_FBfBeg,FBfBeg);
  1066. if (ss_FBfEnd != FBfEnd) ex=errprt("ss_FBfEnd != FBfEnd",ss_FBfEnd,FBfEnd);
  1067. if (ss_SBfBeg != SBfBeg) ex=errprt("ss_SBfBeg != SBfBeg",ss_SBfBeg,SBfBeg);
  1068. if (ss_SBfEnd != SBfEnd) ex=errprt("ss_SBfEnd != SBfEnd",ss_SBfEnd,SBfEnd);
  1069. /*
  1070. * make sure the pointers into the above buffers are between the start
  1071. * and end of the buffers
  1072. *
  1073. * Note: while doing an EI or M command, CBfPtr can point outside of
  1074. * [CBfBeg..CBfEnd] but it is always within [CStBeg..CStEnd].
  1075. */
  1076. if (CBfPtr < CStBeg) ex=errprt("CBfPtr < CStBeg",CBfPtr,CStBeg);
  1077. if (CBfPtr > CStEnd) ex=errprt("CBfPtr > CStEnd",CBfPtr,CStEnd);
  1078. if (FBfPtr < FBfBeg) ex=errprt("FBfPtr < FBfBeg",FBfPtr,FBfBeg);
  1079. if (FBfPtr > FBfEnd) ex=errprt("FBfPtr > FBfEnd",FBfPtr,FBfEnd);
  1080. if (SBfPtr < SBfBeg) ex=errprt("SBfPtr < SBfBeg",SBfPtr,SBfBeg);
  1081. if (SBfPtr > SBfEnd) ex=errprt("SBfPtr > SBfEnd",SBfPtr,SBfEnd);
  1082. /*
  1083. * The order of pointers into the editing buffer should be:
  1084. *
  1085. * EBfBeg <= GapBeg <= GapEnd <= EBfEnd <= IBfEnd
  1086. */
  1087. if (EBfBeg > GapBeg) ex=errprt("EBfBeg > GapBeg",EBfBeg,GapBeg);
  1088. if (GapBeg > GapEnd) ex=errprt("GapBeg > GapEnd",GapBeg,GapEnd);
  1089. if (GapEnd > EBfEnd) ex=errprt("GapEnd > EBfEnd",GapEnd,EBfEnd);
  1090. if (EBfEnd > IBfEnd) ex=errprt("EBfEnd > IBfEnd",EBfEnd,IBfEnd);
  1091. if (ex == EXIT_FAILURE) {
  1092. exit(EXIT_FAILURE);
  1093. }
  1094. }
  1095. #endif /* #if CONSISTENCY_CHECKING */