Leaked source code of windows server 2003
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.

544 lines
15 KiB

  1. #define EXT_ID "pmatch ver 1.02 "##__DATE__##" "##__TIME__
  2. #include "ext.h"
  3. /*
  4. * Modifications
  5. * 12-Sep-1988 mz Made WhenLoaded match declaration
  6. *
  7. */
  8. #define fLeftSide(ch) ((ch) == '[' || (ch) == '{' || (ch) == '(' || (ch) == '<' )
  9. #define EOF (int)0xFFFFFFFF
  10. #define BOF (int)0xFFFFFFFE
  11. #define EOL (int)0xFFFFFFFD
  12. #ifndef TRUE
  13. #define FALSE 0
  14. #define TRUE (!FALSE)
  15. #endif
  16. #ifndef NULL
  17. #define NULL ((void *) 0)
  18. #endif
  19. #define SQ '\''
  20. #define DQ '\"'
  21. #define ANYCHAR '\0'
  22. #define BACKSLASH '\\'
  23. /****************************************************************************
  24. * *
  25. * Handle apostrophes ( which look like single quotes, but don't come in *
  26. * pairs ) by defining a maximum number of chars that can come between *
  27. * single quotes. 4 will handle '\000' and '\x00' *
  28. * *
  29. ****************************************************************************/
  30. #define SQTHRESH 4
  31. flagType pascal EXTERNAL PMatch (unsigned, ARG far *, flagType);
  32. char MatChar (char);
  33. void openZFile (void);
  34. void lopen (PFILE, int, int) ;
  35. int rgetc (void);
  36. int ngetc (void);
  37. int lgetc (void);
  38. void pos (COL far *, LINE far *);
  39. flagType ParenMatch (int, flagType);
  40. /****************************************************************************
  41. * *
  42. * PMatch(argData, pArg, fMeta) *
  43. * *
  44. * argData - ignored *
  45. * pArg - ignored *
  46. * fMeta - TRUE means search for first matchable character *
  47. * *
  48. * RETURNS: *
  49. * *
  50. * TRUE if matching character was found. *
  51. * FALSE if not. *
  52. * *
  53. * SIDE EFFECTS: *
  54. * *
  55. * Changes location of cursor. *
  56. * *
  57. * DESCRIPTION: *
  58. * *
  59. * <pmatch>: If the cursor is on a "match" character, find the *
  60. * match and move the cursor there. If not, do *
  61. * nothing. *
  62. * *
  63. * <arg><pmatch>: Same as <pmatch>, but search forward for a "match" *
  64. * character if we're not on one. *
  65. * *
  66. * Always ignore characters between quotes. *
  67. * *
  68. * Match characters currently supported are: *
  69. * *
  70. * '{' and '}' *
  71. * '[' and ']' *
  72. * '(' and ')' *
  73. * '<' and '>' *
  74. * *
  75. * NOTES: *
  76. * *
  77. * This is defined as a CURSORFUNC, and therefore can be used to *
  78. * select text as part of an argument. For example, to grab the body *
  79. * of a function, go to the opening brace of the body and do *
  80. * <arg><pmatch><pick>. *
  81. * *
  82. ****************************************************************************/
  83. flagType pascal EXTERNAL PMatch (
  84. unsigned int argData,
  85. ARG far * pArg,
  86. flagType fMeta
  87. )
  88. {
  89. COL x;
  90. LINE y;
  91. char ch;
  92. //
  93. // Unreferenced parameters
  94. //
  95. (void)argData;
  96. (void)pArg;
  97. /* Set up file functions */
  98. openZFile ();
  99. /* If current character has no match ... */
  100. if (!MatChar (ch = (char)ngetc()))
  101. {
  102. if (fMeta)
  103. { /* Move forward looking for first matchable character */
  104. if (!ParenMatch (ANYCHAR, TRUE)) return FALSE;
  105. pos ((COL far *)&x, (LINE far *)&y);
  106. MoveCur (x, y);
  107. return TRUE;
  108. }
  109. else return FALSE;
  110. }
  111. if (ParenMatch ((int)ch, (flagType)fLeftSide(ch)))
  112. { /* We got one */
  113. pos ((COL far *)&x, (LINE far *)&y);
  114. MoveCur (x, y);
  115. return TRUE;
  116. }
  117. return FALSE; /* No match found */
  118. }
  119. /****************************************************************************
  120. * *
  121. * ParenMatch (chOrig, fForward) *
  122. * *
  123. * chOrig - character we are trying to match. *
  124. * fForward - TRUE means search forward, FALSE search backwards *
  125. * Returns TRUE if match found, false otherwise *
  126. * *
  127. * RETURNS: * *
  128. * *
  129. * TRUE if matching character found, FALSE if not. *
  130. * *
  131. * SIDE EFFECTS: *
  132. * *
  133. * Changes internal cursor location *
  134. * *
  135. * DESCRIPTION: *
  136. * *
  137. * Search for the next character that "pairs" with 'ch'. Account for * *
  138. * nesting. Ignore all characters between double quotes and single *
  139. * quotes. Recognize escaped quotes. Account for apostrophes. *
  140. * *
  141. ****************************************************************************/
  142. flagType ParenMatch (
  143. int chOrig,
  144. flagType fForward
  145. )
  146. {
  147. int lvl = 0, state = 0, sqcnt = 0;
  148. int (*nextch)(void) = (int (*)(void))(fForward ? rgetc : lgetc);
  149. int (*_ungetch)(void) = (int (*)(void))(fForward ? lgetc : rgetc);
  150. int ch, chMatch;
  151. if (chOrig) chMatch = (int)MatChar ((char)chOrig);
  152. while ((ch = (*nextch)()) >= 0)
  153. switch (state)
  154. {
  155. case 0: /* Regular text */
  156. if (ch == SQ)
  157. if (fForward) state = 1;
  158. else state = 5;
  159. else if (ch == DQ)
  160. if (fForward) state = 3;
  161. else state = 7;
  162. else
  163. if (chOrig != ANYCHAR)
  164. if (ch == chOrig) lvl++; /* Nest in one */
  165. else
  166. {
  167. if (ch == chMatch) /* Nest out or ...*/
  168. if (!lvl--) goto found;/* Found it! */
  169. }
  170. else
  171. if ((flagType)MatChar ((char)ch)) goto found; /* Found one! */
  172. break;
  173. case 1: /* Single quote moving forwards */
  174. sqcnt++;
  175. if (ch == BACKSLASH) state = 2;
  176. else if (ch == SQ || /* We matched the ', or ... */
  177. sqcnt > SQTHRESH ) /* ... we gave up trying */
  178. {
  179. sqcnt = 0;
  180. state = 0;
  181. }
  182. break;
  183. case 2: /* Escaped character inside single quotes */
  184. sqcnt++;
  185. state = 1;
  186. break;
  187. case 3: /* Double quote moving forwards */
  188. if (ch == BACKSLASH) state = 4;
  189. else if (ch == DQ) state = 0;
  190. break;
  191. case 4: /* Escaped character inside double quotes */
  192. state = 3;
  193. break;
  194. case 5: /* Single quote moving backwards */
  195. sqcnt++;
  196. if (ch == SQ) state = 6;
  197. else if (sqcnt > SQTHRESH)
  198. {
  199. sqcnt = 0;
  200. state = 0;
  201. }
  202. break;
  203. case 6: /* Check for escaped single quote moving backwards */
  204. sqcnt++;
  205. if (ch == BACKSLASH) state = 5;
  206. else
  207. {
  208. sqcnt = 0;
  209. (*_ungetch)();
  210. state = 0;
  211. }
  212. break;
  213. case 7: /* Double quote moving backwards */
  214. if (ch == DQ) state = 8;
  215. break;
  216. case 8: /* Check for escaped double quote moving backwards */
  217. if (ch == BACKSLASH) state = 7;
  218. else
  219. {
  220. (*_ungetch)();
  221. state = 0;
  222. }
  223. break;
  224. }
  225. return FALSE;
  226. found: return TRUE;
  227. }
  228. /****************************************************************************
  229. * *
  230. * MatChar(ch) *
  231. * *
  232. * ch - Character to match *
  233. * *
  234. * RETURNS: *
  235. * *
  236. * Character that matches the argument *
  237. * *
  238. * SIDE EFFECTS: *
  239. * *
  240. * None. *
  241. * *
  242. * DESCRIPTION *
  243. * *
  244. * Given one character out of one of the pairs {}, [], (), <>, return *
  245. * the other one. *
  246. * *
  247. ****************************************************************************/
  248. char MatChar (
  249. char ch
  250. )
  251. {
  252. switch (ch)
  253. {
  254. case '{': return '}';
  255. case '}': return '{';
  256. case '[': return ']';
  257. case ']': return '[';
  258. case '(': return ')';
  259. case ')': return '(';
  260. case '<': return '>';
  261. case '>': return '<';
  262. default : return '\0';
  263. }
  264. }
  265. /****************************************************************************
  266. * *
  267. * Extension specific file reading state. *
  268. * *
  269. * The static globals record the current state of file reading. The *
  270. * pmatch extension reads through the file either forwards or backwards. *
  271. * The state is kept as the current column and row, the contents of the *
  272. * current line, the length of the current line and the file, and some *
  273. * flags. *
  274. * *
  275. ****************************************************************************/
  276. static char LineBuf[BUFLEN]; /* Text of current line in file */
  277. static COL col ; /* Current column in file (0-based) */
  278. static LINE line ; /* Current line in file (0-based) */
  279. static int numCols ; /* Columns of text on curent line */
  280. static LINE numLines; /* Number of lines in the file */
  281. static PFILE pFile ; /* File to be reading from */
  282. static flagType fEof ; /* TRUE ==> end-of-file reached last time */
  283. static flagType fBof ; /* TRUE ==> begin-of-file reached last time */
  284. char CurFile[] = "" ; /* Current file to Z */
  285. /****************************************************************************
  286. * *
  287. * openZFile() *
  288. * *
  289. * SIDE EFFECTS: *
  290. * *
  291. * Changes globals pFile, fEof, fBof, col, line, numCols, numLines *
  292. * and LineBuf *
  293. * *
  294. * DESCRIPTION: *
  295. * *
  296. * Opens the current file. This must be called before trying to read *
  297. * the file. This is not a true "open" because it need not be closed *
  298. * *
  299. ****************************************************************************/
  300. void openZFile ()
  301. {
  302. COL x;
  303. LINE y;
  304. GetTextCursor ((COL far *)&x, (LINE far *)&y);
  305. /* Get Z handle for current file */
  306. pFile = FileNameToHandle (CurFile, CurFile);
  307. fEof = FALSE; /* We haven't read the end of file */
  308. fBof = FALSE; /* We haven't read the beginning of file */
  309. col = x; /* We start where Z is now in the file */
  310. line = y; /* We start where Z is now in the file */
  311. /* We pre-read the current line */
  312. numCols = GetLine (line, (char far *)LineBuf, pFile);
  313. /* We find the length of file (in lines) */
  314. numLines = FileLength (pFile);
  315. }
  316. /****************************************************************************
  317. * *
  318. * rgetc () *
  319. * *
  320. * RETURNS: *
  321. * *
  322. * Next character in file, not including line terminators. EOF if *
  323. * there are no more. *
  324. * *
  325. * SIDE EFFECTS: *
  326. * *
  327. * Changes globals col, numCols, numLines, LineBuf, fEof, fBof and *
  328. * line. *
  329. * *
  330. * DESCRIPTION: *
  331. * *
  332. * Advances current file position to the right, then returns the *
  333. * character found there. Reads through blank lines if necessary *
  334. * *
  335. ****************************************************************************/
  336. int
  337. rgetc ()
  338. {
  339. if (fEof) return (int)EOF; /* We already hit EOF last time */
  340. if (++col >= numCols) /* If next character is on the next line ... */
  341. {
  342. /* ... get next non-blank line (or EOF) */
  343. while ( ++line < numLines &&
  344. !(numCols = GetLine (line, (char far *)LineBuf, pFile)));
  345. if (line >= numLines)
  346. { /* Oh, no more lines */
  347. fEof = TRUE;
  348. return (int)EOF;
  349. }
  350. col = 0; /* We got a line, so start in column 0 */
  351. }
  352. fBof = FALSE; /* We got something, so we can't be at BOF */
  353. return LineBuf[col];
  354. }
  355. /****************************************************************************
  356. * *
  357. * ngetc() *
  358. * *
  359. * RETURNS: *
  360. * *
  361. * Character at current position. EOF or BOF if we are at end or top *
  362. * of file. *
  363. * *
  364. ****************************************************************************/
  365. int
  366. ngetc()
  367. {
  368. if (fEof) return (int)EOF;
  369. if (fBof) return (int)BOF;
  370. return LineBuf[col];
  371. }
  372. /****************************************************************************
  373. * *
  374. * lgetc () *
  375. * *
  376. * RETURNS: *
  377. * *
  378. * Previous character in file, not including line terminators. EOF *
  379. * if there are no more. *
  380. * *
  381. * SIDE EFFECTS: *
  382. * *
  383. * Changes globals col, numCols, numLines, LineBuf, fEof, fBof and *
  384. * line. *
  385. * *
  386. * DESCRIPTION: *
  387. * *
  388. * Decrements current file position to the right, then returns the *
  389. * character found there. Reads through blank lines if necessary *
  390. * *
  391. ****************************************************************************/
  392. int
  393. lgetc ()
  394. {
  395. if (fBof) return (int)BOF; /* We already it BOF last time */
  396. if (--col < 0)
  397. { /* If prev character is on prev line ... */
  398. /* ... get prev non-blank line (or BOF) */
  399. while ( --line >= 0 &&
  400. !(numCols = GetLine (line, (char far *)LineBuf, pFile)));
  401. if (line < 0)
  402. { /* We're at the top of the file */
  403. fBof = TRUE;
  404. return (int)BOF;
  405. }
  406. col = numCols - 1; /* We got a line, so start at last character */
  407. }
  408. fEof = (int)FALSE;
  409. return LineBuf[col];
  410. }
  411. /****************************************************************************
  412. * *
  413. * pos (&x, &y) *
  414. * *
  415. * SIDE EFFECTS: *
  416. * *
  417. * Fills memory at *x and *y with current file position. *
  418. * *
  419. * DESCRIPTION: *
  420. * *
  421. * Gets the current file position. Far pointers are needed because *
  422. * SS != DS. *
  423. * *
  424. ****************************************************************************/
  425. void pos (fpx, fpy)
  426. COL far *fpx;
  427. LINE far *fpy;
  428. {
  429. *fpx = col;
  430. *fpy = line;
  431. }
  432. /****************************************************************************
  433. * *
  434. * No special switches. *
  435. * *
  436. ****************************************************************************/
  437. struct swiDesc swiTable[] =
  438. {
  439. { NULL, NULL, (INT_PTR)NULL }
  440. };
  441. /****************************************************************************
  442. * *
  443. * <pmatch> is a cursor func, takes no arguments. *
  444. * *
  445. ****************************************************************************/
  446. struct cmdDesc cmdTable[] =
  447. {
  448. { "pmatch", (funcCmd) PMatch, 0, CURSORFUNC },
  449. { NULL, NULL, (UINT_PTR)NULL, (UINT_PTR)NULL }
  450. };
  451. /****************************************************************************
  452. * *
  453. * WhenLoaded () *
  454. * *
  455. * DESCRIPTION: *
  456. * *
  457. * Attach to ALT+P and issue sign-on message. *
  458. * *
  459. ****************************************************************************/
  460. void EXTERNAL WhenLoaded ()
  461. {
  462. DoMessage (EXT_ID);
  463. SetKey ("pmatch", "alt+p");
  464. }