/Pristine-Pro/POCO/CHOPPER.C

http://github.com/AnimatorPro/Animator-Pro · C · 296 lines · 211 code · 26 blank · 59 comment · 26 complexity · 1c16357fdb49188aac03531939b92057 MD5 · raw file

  1. /*****************************************************************************
  2. * chopper.c - Routines to read lines and manipultate strings in lines.
  3. *
  4. * po_get_csource_line() - The source of lines for the preprocessor
  5. * po_chop_to() - Chop chars from line into word, up to specified char
  6. * po_skip_space() - Return pointer to char following leading whitespace
  7. *
  8. * MAINTENANCE
  9. * 09/01/90 (Ian)
  10. * The check for line-too-long is now only done if there is no
  11. * \n at EOL, since by definition if we got \n it's a good line.
  12. *
  13. * Moved the setting of t->line_buf to the top of the function,
  14. * so that when we report an error such as 'NL in string' it
  15. * displays the line on which the error occurred.
  16. * 09/07/90 (Ian)
  17. * Single-quoted strings are now handled like double-quoted:
  18. * they must be terminated on the same line they start on.
  19. * Also, fixed bug that was causing quotes to be checked inside
  20. * of comments, yielding bogus 'NL in string' errors.
  21. * 10/01/90 (Ian)
  22. * Fixed a bug that was causing bogus 'line too long' errors in
  23. * big multiline comments. Inserted 'icount = 0;' just before
  24. * the continue statement in the read loop.
  25. ****************************************************************************/
  26. #include <ctype.h>
  27. #include <string.h>
  28. #include "poco.h"
  29. #ifdef DEADWOOD
  30. static Boolean po_is_all_white(register char *buf)
  31. /*****************************************************************************
  32. * is_all_white - Decide whether string is all whitespace.
  33. ****************************************************************************/
  34. {
  35. while (isspace(*buf))
  36. ++buf;
  37. return(*buf == '\0');
  38. }
  39. #endif
  40. char *po_get_csource_line(Poco_cb *pcb)
  41. /*****************************************************************************
  42. * po_get_csource_line - Like fgets(), but understands the C concept of a 'line'.
  43. ****************************************************************************/
  44. {
  45. Boolean splice = FALSE; /* Are we splicing lines? */
  46. Boolean mlcomment = FALSE; /* Are we doing ml comment? */
  47. int buflen = SZTOKE-1; /* Max logical line size. */
  48. int icount = 0; /* Significant character counter*/
  49. Token *t = &pcb->t; /* -> Token struct in pcb */
  50. File_stack *fstack = t->file_stack; /* -> File_stack struct in pcb */
  51. char *lbuf = t->line_b1; /* -> Line buffer in Token */
  52. char *buf = lbuf; /* -> Cur I/O location in buf */
  53. char *subbuf; /* -> Cur scan location in buf */
  54. char *endcomment; /* -> End of inline comment */
  55. char c;
  56. t->line_buf = lbuf; /* So that errors can display the current line */
  57. /*
  58. * if we report an error, make sure it carries the right line
  59. * number in the report. if we don't report an error, this'll
  60. * get zeroed before we return to the caller.
  61. */
  62. pcb->error_line_number = fstack->line_count;
  63. /*----------------------------------------------------------------------------
  64. * Loop to assemble a significant logical line.
  65. * This loop will continue until a non-blank logical line is built. A
  66. * logical line has all comments stripped from it, and has had continuation
  67. * lines spliced together.
  68. *--------------------------------------------------------------------------*/
  69. do {
  70. /*------------------------------------------------------------------------
  71. * Loop to splice together physical lines that are related.
  72. * If the outer level loop has set the 'mlcomment' (multi-line comment)
  73. * flag, we stay in this loop until we read a line that has the closing
  74. * comment delimiter on it.
  75. * This loop handles splicing of physical lines ending in '\' into a
  76. * single logical line.
  77. *----------------------------------------------------------------------*/
  78. icount = 0;
  79. do {
  80. if (NULL == fgets(buf+icount, buflen-icount, fstack->source.file))
  81. {
  82. if (mlcomment) /* EOF in multi-line comment */
  83. po_say_fatal(pcb, "EOF in comment");
  84. else if (splice) /* EOF instead of continuation */
  85. po_expecting_got_str(pcb, "EOF", "continuation line");
  86. else /* Normal EOF */
  87. {
  88. lbuf = NULL;
  89. goto NORMAL_EXIT;
  90. }
  91. }
  92. else /* Not EOF, we got a line.... */
  93. {
  94. pcb->error_line_number = ++fstack->line_count; /* Count the line*/
  95. icount = strlen(buf) - 1; /* Size of string, less \n char.*/
  96. if ('\n' == buf[icount]) /* If the last char is a \n, */
  97. { /* truncate at the \n; count has*/
  98. buf[icount] = '\0'; /* already been adjusted above. */
  99. }
  100. else
  101. {
  102. if (buflen == 2 + icount) /* If there is no \n at */
  103. { /* EOL, check for buffer*/
  104. po_say_fatal(pcb,"line too long"); /* overflow. If not */
  105. } /* it means last line */
  106. ++icount; /* has no CRLF; adjust */
  107. } /* the count to match. */
  108. if (icount == 0)
  109. continue; /* Empty line-try again.*/
  110. if (mlcomment) /* If doing multi-line comment */
  111. {
  112. if (NULL == strstr(buf, "*/"))
  113. {
  114. icount = 0; /* no significant chars on line */
  115. continue; /* No delim, read next physline */
  116. }
  117. else
  118. mlcomment = FALSE; /* Found delim, end of ml state */
  119. }
  120. if ('\\' == buf[icount-1]) /* If the last char on the line */
  121. { /* is a backslash, splice the */
  122. --icount; /* next physical line onto this */
  123. splice = TRUE; /* line, overlaying the \ char. */
  124. }
  125. else
  126. splice = FALSE;
  127. }
  128. } while (splice || mlcomment || icount == 0);
  129. /*------------------------------------------------------------------------
  130. * Loop to process double-quotes and comments.
  131. *----------------------------------------------------------------------*/
  132. subbuf = lbuf;
  133. while (NULL != (subbuf = po_cmatch_scan(subbuf)))
  134. {
  135. /*--------------------------------------------------------------------
  136. * Handle quotes --
  137. * We have to ignore everything inside the quotes, so we scan for
  138. * a closing quote, which must be on the same line as the opener.
  139. * We also watch out for escaped quotes (\") and ignore them.
  140. *------------------------------------------------------------------*/
  141. c = *subbuf;
  142. if (c == '"' || c == '\'')
  143. {
  144. Boolean found_end = FALSE;
  145. while (found_end == FALSE)
  146. {
  147. ++subbuf;
  148. if (NULL == (subbuf = strchr(subbuf, c)))
  149. po_say_fatal(pcb, "strings cannot span lines without continuation (\\)");
  150. if (!('\\' == subbuf[-1] && '\\' != subbuf[-2]))
  151. {
  152. ++subbuf;
  153. found_end = TRUE;
  154. }
  155. } /* END while (found_end == FALSE) */
  156. } /* END handling for a double-quote character */
  157. else /* Not a quote, must've been a slash... */
  158. /*----------------------------------------------------------------
  159. * Handle comments --
  160. * The C++ type comment (//) is allowed because it's easy; we
  161. * just truncate the line at that point.
  162. * When we encounter a normal C comment, we scan the remainder
  163. * of the line to see if it's closed on the same line. If so,
  164. * we wipe the comment and continue. If the comment is not
  165. * closed on the same line, we set the multi-line comment flag
  166. * and loop back to perform what is essentially a splice
  167. * operation. When the jgetline() routine sees the mlcomment
  168. * flag, it knows not to return until a line containing the
  169. * closing comment delimiter is seen.
  170. *--------------------------------------------------------------*/
  171. {
  172. switch (subbuf[1])
  173. {
  174. case '/': /* C++ comment (//)... */
  175. *subbuf = '\0';
  176. break;
  177. case '*': /* Normal C comment... */
  178. subbuf +=2;
  179. if (NULL == (endcomment = strstr(subbuf, "*/")))
  180. {
  181. *subbuf = '\0'; /* We have a multi-line */
  182. buflen -= strlen(buf); /* comment, set up to splice*/
  183. buf = subbuf; /* more physical lines onto */
  184. mlcomment = TRUE; /* current logical line. */
  185. goto ENDLOOP;
  186. }
  187. else
  188. {
  189. subbuf -=2;
  190. *(++endcomment) = ' '; /* In-line comment, */
  191. strcpy(subbuf, endcomment); /* replace w/space. */
  192. }
  193. break;
  194. default: /* Not a comment at all... */
  195. ++subbuf;
  196. break;
  197. } /* END switch (subbuf[1]) */
  198. } /* END handling for a slash character */
  199. } /* END while slash or quote found in buffer */
  200. ENDLOOP:
  201. ;
  202. } while (TRUE == mlcomment || NULL == po_skip_space(buf = lbuf));
  203. #ifdef DEBUG_JGETS
  204. printf("po_get_csource_line: '%s'\n",lbuf);
  205. #endif
  206. NORMAL_EXIT:
  207. pcb->error_line_number = 0; /* no error, clear this */
  208. return lbuf;
  209. }
  210. #ifdef DEADWOOD
  211. char *po_skip_space(register char *line)
  212. /*****************************************************************************
  213. * po_skip_space - Skip leading whitespace.
  214. ****************************************************************************/
  215. {
  216. register char c;
  217. if (!line)
  218. return(NULL);
  219. for (;;)
  220. {
  221. if (0 == (c = *line++))
  222. return(NULL);
  223. if (!isspace(c))
  224. break;
  225. }
  226. return(--line);
  227. }
  228. #endif
  229. char *po_chop_to(char *line, char *word, char letter)
  230. /*****************************************************************************
  231. * po_chop_to - Copy chars from line to word until specified delim is found.
  232. ****************************************************************************/
  233. {
  234. register char c;
  235. for (;;)
  236. {
  237. if (0 == (c = *line++))
  238. break;
  239. if (c == letter)
  240. break;
  241. *word++ = c;
  242. }
  243. *word = '\0';
  244. return(--line);
  245. }
  246.