codetools.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /* Copyright (C) 2005-2010 Valeriy Argunov (nporep AT mail DOT ru) */
  2. /*
  3. * This library is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU Lesser General Public License as published by
  5. * the Free Software Foundation; either version 2.1 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public License
  14. * along with this library; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. */
  17. #include "codetools.h"
  18. #include "statements.h"
  19. #include "text.h"
  20. static int qspProcessPreformattedStrings(QSP_CHAR *, QSPLineOfCode **);
  21. static int qspProcessEOLExtensions(QSPLineOfCode *, int, QSPLineOfCode **);
  22. void qspFreePrepLines(QSPLineOfCode *strs, int count)
  23. {
  24. if (strs)
  25. {
  26. while (--count >= 0)
  27. {
  28. free(strs[count].Str);
  29. if (strs[count].Label) free(strs[count].Label);
  30. if (strs[count].Stats) free(strs[count].Stats);
  31. }
  32. free(strs);
  33. }
  34. }
  35. void qspCopyPrepLines(QSPLineOfCode **dest, QSPLineOfCode *src, int start, int end)
  36. {
  37. QSPLineOfCode *line;
  38. int i, count = end - start;
  39. if (src && count)
  40. {
  41. *dest = (QSPLineOfCode *)malloc(count * sizeof(QSPLineOfCode));
  42. line = *dest;
  43. while (start < end)
  44. {
  45. line->Str = qspGetNewText(src[start].Str, -1);
  46. line->LineNum = src[start].LineNum;
  47. count = line->StatsCount = src[start].StatsCount;
  48. if (count)
  49. {
  50. line->Stats = (QSPCachedStat *)malloc(count * sizeof(QSPCachedStat));
  51. for (i = 0; i < count; ++i)
  52. {
  53. line->Stats[i].Stat = src[start].Stats[i].Stat;
  54. line->Stats[i].EndPos = src[start].Stats[i].EndPos;
  55. line->Stats[i].ParamPos = src[start].Stats[i].ParamPos;
  56. }
  57. }
  58. else
  59. line->Stats = 0;
  60. line->IsMultiline = src[start].IsMultiline;
  61. if (src[start].Label)
  62. line->Label = qspGetNewText(src[start].Label, -1);
  63. else
  64. line->Label = 0;
  65. ++line;
  66. ++start;
  67. }
  68. }
  69. else
  70. *dest = 0;
  71. }
  72. QSP_CHAR *qspJoinPrepLines(QSPLineOfCode *s, int count, QSP_CHAR *delim)
  73. {
  74. int i, txtLen = 0, txtRealLen = 0, bufSize = 256, lastIndex = count - 1, delimLen = qspStrLen(delim);
  75. QSP_CHAR *txt = (QSP_CHAR *)malloc(bufSize * sizeof(QSP_CHAR));
  76. *txt = 0;
  77. for (i = 0; i < count; ++i)
  78. {
  79. if ((txtLen += qspStrLen(s[i].Str)) >= bufSize)
  80. {
  81. bufSize = txtLen + 128;
  82. txt = (QSP_CHAR *)realloc(txt, bufSize * sizeof(QSP_CHAR));
  83. }
  84. qspStrCopy(txt + txtRealLen, s[i].Str);
  85. if (i == lastIndex) break;
  86. txtRealLen = txtLen;
  87. if ((txtLen += delimLen) >= bufSize)
  88. {
  89. bufSize = txtLen + 128;
  90. txt = (QSP_CHAR *)realloc(txt, bufSize * sizeof(QSP_CHAR));
  91. }
  92. qspStrCopy(txt + txtRealLen, delim);
  93. txtRealLen = txtLen;
  94. }
  95. return txt;
  96. }
  97. static int qspProcessPreformattedStrings(QSP_CHAR *data, QSPLineOfCode **strs)
  98. {
  99. QSPLineOfCode *ret, *line;
  100. QSP_BOOL isNewLine;
  101. QSP_CHAR *str, quot = 0;
  102. int lineNum = 0, lastLineNum = 0, count = 0, quotsCount = 0, strLen = 0, bufSize = 8, strBufSize = 256;
  103. str = (QSP_CHAR *)malloc(strBufSize * sizeof(QSP_CHAR));
  104. ret = (QSPLineOfCode *)malloc(bufSize * sizeof(QSPLineOfCode));
  105. while (*data)
  106. {
  107. isNewLine = (qspStrsNComp(data, QSP_STRSDELIM, QSP_LEN(QSP_STRSDELIM)) == 0);
  108. if (isNewLine) ++lineNum;
  109. if (quotsCount || quot || !isNewLine)
  110. {
  111. if (++strLen >= strBufSize)
  112. {
  113. strBufSize = strLen + 256;
  114. str = (QSP_CHAR *)realloc(str, strBufSize * sizeof(QSP_CHAR));
  115. }
  116. str[strLen - 1] = *data;
  117. if (quot)
  118. {
  119. if (*data == quot)
  120. {
  121. if (*(data + 1) == quot)
  122. {
  123. if (++strLen >= strBufSize)
  124. {
  125. strBufSize = strLen + 256;
  126. str = (QSP_CHAR *)realloc(str, strBufSize * sizeof(QSP_CHAR));
  127. }
  128. str[strLen - 1] = *data++;
  129. }
  130. else
  131. quot = 0;
  132. }
  133. }
  134. else
  135. {
  136. if (*data == QSP_LQUOT[0])
  137. ++quotsCount;
  138. else if (*data == QSP_RQUOT[0])
  139. {
  140. if (quotsCount) --quotsCount;
  141. }
  142. else if (qspIsInList(QSP_QUOTS, *data))
  143. quot = *data;
  144. }
  145. ++data;
  146. }
  147. else
  148. {
  149. str[strLen] = 0;
  150. if (++count >= bufSize)
  151. {
  152. bufSize = count + 16;
  153. ret = (QSPLineOfCode *)realloc(ret, bufSize * sizeof(QSPLineOfCode));
  154. }
  155. line = ret + count - 1;
  156. line->Str = qspDelSpc(str);
  157. line->LineNum = lastLineNum;
  158. line->Label = 0;
  159. line->Stats = 0;
  160. lastLineNum = lineNum;
  161. strLen = 0;
  162. data += QSP_LEN(QSP_STRSDELIM);
  163. }
  164. }
  165. str[strLen] = 0;
  166. if (++count > bufSize)
  167. ret = (QSPLineOfCode *)realloc(ret, count * sizeof(QSPLineOfCode));
  168. line = ret + count - 1;
  169. line->Str = qspDelSpc(str);
  170. line->LineNum = lastLineNum;
  171. line->Label = 0;
  172. line->Stats = 0;
  173. free(str);
  174. *strs = ret;
  175. return count;
  176. }
  177. static int qspProcessEOLExtensions(QSPLineOfCode *s, int count, QSPLineOfCode **strs)
  178. {
  179. QSPLineOfCode *ret;
  180. QSP_CHAR *str;
  181. int len, lastNum = 0, i = 0, bufSize = 8, newCount = 0;
  182. ret = (QSPLineOfCode *)malloc(bufSize * sizeof(QSPLineOfCode));
  183. while (i < count)
  184. {
  185. len = qspAddText(&str, s[i].Str, 0, -1, QSP_TRUE);
  186. if (len >= QSP_LEN(QSP_PREEOLEXT QSP_EOLEXT))
  187. {
  188. while (!qspStrsComp(str + len - QSP_LEN(QSP_PREEOLEXT QSP_EOLEXT), QSP_PREEOLEXT QSP_EOLEXT))
  189. {
  190. if (++i == count) break;
  191. len = qspAddText(&str, s[i].Str, len - QSP_LEN(QSP_EOLEXT), -1, QSP_FALSE);
  192. }
  193. }
  194. if (++newCount >= bufSize)
  195. {
  196. bufSize = newCount + 16;
  197. ret = (QSPLineOfCode *)realloc(ret, bufSize * sizeof(QSPLineOfCode));
  198. }
  199. qspInitLineOfCode(ret + newCount - 1, str, lastNum);
  200. ++i;
  201. lastNum = s[i].LineNum;
  202. }
  203. *strs = ret;
  204. return newCount;
  205. }
  206. int qspPreprocessData(QSP_CHAR *data, QSPLineOfCode **strs)
  207. {
  208. QSPLineOfCode *s;
  209. int res, count = qspProcessPreformattedStrings(data, &s);
  210. res = qspProcessEOLExtensions(s, count, strs);
  211. qspFreePrepLines(s, count);
  212. return res;
  213. }