PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/V_33_62/pfe-33/pfe/zchar-ext.c

#
C | 361 lines | 315 code | 9 blank | 37 comment | 2 complexity | 60632d9980aab737c1e4bcb6f3cdac7c MD5 | raw file
Possible License(s): Zlib, LGPL-2.0, AGPL-3.0, LGPL-2.1
  1. /**
  2. *
  3. * Copyright (C) 2000 - 2004 Guido U. Draheim <guidod@gmx.de>
  4. * Copyright (C) 2005 - 2006 Guido U. Draheim <guidod@gmx.de>
  5. *
  6. * @see GNU LGPL
  7. * @author Guido U. Draheim (modified by $Author: guidod $)
  8. * @version $Revision: 1.2 $
  9. * (modified $Date: 2006-08-11 22:56:05 $)
  10. *
  11. * @description:
  12. * ZCHAR-EXT wordset - defines words for zero-terminated strings,
  13. * the datatype prefix is called "Z" which is usually a simple CHAR.
  14. * And CHAR can be either BCHAR or WCHAR depending on your platform.
  15. * Anyway, the words in this wordset should be largely modelled
  16. * after the examples found in other forth implementations - most
  17. * prominently MPE's forths.
  18. */
  19. #define _P4_SOURCE 1
  20. #include <pfe/pfe-base.h>
  21. #include <pfe/os-ctype.h>
  22. #include <pfe/os-string.h>
  23. #include <pfe/def-words.h>
  24. /* --------------------------------------------------------------------- */
  25. /** 'Z"' ( [chars<">] -- z* )
  26. * scan the input to the next doublequote and create a buffer
  27. * that holds the chars - return the address of that zero-terminated
  28. * string-buffer, either =>"POCKET-PAD" or =>"ALLOT"ed into the dictionary.
  29. */
  30. FCode(p4_z_quote)
  31. {
  32. register p4_byte_t* p;
  33. register p4ucell n;
  34. p4_word_parse ('"'); *DP=0; /* PARSE-NOHERE */
  35. n = PFE.word.len;
  36. if (STATE)
  37. {
  38. FX_COMPILE (p4_z_quote);
  39. DP += sizeof(short);
  40. p = DP;
  41. }else{
  42. p = p4_pocket ();
  43. n = PFE.word.len < P4_POCKET_SIZE ?
  44. PFE.word.len : P4_POCKET_SIZE;
  45. }
  46. p4_memcpy (p, PFE.word.ptr, n); p[PFE.word.len] = '\0';
  47. if (STATE)
  48. {
  49. DP += n+1;
  50. FX (p4_align);
  51. ((short*)p)[-1] = (DP - p);
  52. }else{
  53. FX_PUSH(p);
  54. }
  55. }
  56. FCode_XE (p4_z_quote_XT)
  57. { FX_USE_CODE_ADDR {
  58. short skip = *P4_INC(IP, short);
  59. FX_PUSH(IP);
  60. P4_ADD_(IP,skip,char);
  61. FX_USE_CODE_EXIT;
  62. }}
  63. p4xcode* p4_z_quote_SEE(p4xcode* ip, char* p, p4_Semant* s)
  64. {
  65. int skip = *P4_INC(ip,short);
  66. sprintf (p, "%.*s %.*s\" ",
  67. NFACNT(*s->name), s->name + 1,
  68. (int) skip, (char*) ip);
  69. P4_ADD_(ip,skip,char);
  70. return ip;
  71. }
  72. P4COMPILES(p4_z_quote, p4_z_quote_XT, p4_z_quote_SEE, 0);
  73. /** ZCOUNT ( z* -- z* len )
  74. * push length of z-string, additionally to the string addr itself.
  75. : ZSTRLEN ZCOUNT NIP ;
  76. * (see libc strlen(3)) / compare with => COUNT / => ZSTRLEN
  77. */
  78. FCode (p4_zcount)
  79. {
  80. /* FX_PUSH (p4_strlen ((char*)(*SP))) is wrong,
  81. * gcc may leave unintended behaviour
  82. */
  83. register int i = p4_strlen ((char*)(*SP));
  84. FX_PUSH(i);
  85. }
  86. /** ZSTRLEN ( z* -- len )
  87. * push length of z-string.
  88. : ZSTRLEN ZCOUNT NIP ;
  89. * (see libc strlen(3)) / compare with => ZMOVE / => CMOVE
  90. */
  91. FCode (p4_zstrlen)
  92. {
  93. *SP = p4_strlen ((char*)(*SP));
  94. }
  95. /** ZMOVE ( zsrc* zdest* -- )
  96. * copy a zero terminated string
  97. * (see libc strcpy(3)) / compare with => ZSTRLEN / => COUNT
  98. */
  99. FCode (p4_zmove)
  100. {
  101. p4_strcpy ((char*)(SP[0]), (char*)(SP[1]));
  102. FX_2DROP;
  103. }
  104. /** APPENDZ ( caddr* u zdest* -- )
  105. * Add the string defined by CADDR LEN to the zero terminated string
  106. * at ZDEST - actually a => SYNONYM of => +ZPLACE of the => ZPLACE family
  107. * (see strncat(3)) / compare with => ZPLACE / => +PLACE
  108. */
  109. /** +ZPLACE ( caddr* u zdest* -- )
  110. * Add the string defined by CADDR LEN to the zero terminated string
  111. * at ZDEST - (for older scripts the => SYNONYM named => APPENDZ exists)
  112. * (see libc strncat(3)) / compare with => ZPLACE / => +PLACE
  113. */
  114. FCode (p4_appendz)
  115. {
  116. p4_strncat ((char*)(SP[0]), (char*)(SP[2]), (int)(SP[1]));
  117. FX_3DROP;
  118. }
  119. /** ZPLACE ( addr* len zaddr* -- )
  120. * copy string and place as 0 terminated
  121. * (see libc strncpy(3)) / see also => +ZPLACE / => Z+PLACE
  122. */
  123. FCode (p4_zplace)
  124. {
  125. p4_strncpy ((char*)(SP[0]), (char*)(SP[2]), (int)(SP[1]));
  126. FX_3DROP;
  127. }
  128. /* ------------------------------------------------------------------- */
  129. /*
  130. * helper function used by all backslash-lit-strings
  131. * copies a string from input buffer to output buffer
  132. * thereby interpreting backlash-sequences. Returns
  133. * the number of chars copied.
  134. */
  135. p4ucell p4_backslash_parse_into (p4char delim, p4char* dst, int max,
  136. int refills)
  137. {
  138. register int i, j = 0;
  139. register const p4char* src; p4ucell len;
  140. parse:
  141. p4_word_parse (delim); *DP=0; /* PARSE-NOHERE */
  142. src = PFE.word.ptr; len = PFE.word.len;
  143. if (! len && refills--) { if (p4_refill ()) goto parse; }
  144. i = 0;
  145. while (i < len && j < max)
  146. {
  147. if (src[i] != '\\')
  148. {
  149. dst[j++] = src[i++];
  150. }else{
  151. if (++i == len) goto parse;
  152. switch (src[i])
  153. {
  154. case 'n': dst[j++] = '\n'; i++; break;
  155. case 'r': dst[j++] = '\r'; i++; break;
  156. case 'b': dst[j++] = '\b'; i++; break;
  157. case 'a': dst[j++] = '\a'; i++; break;
  158. case 'f': dst[j++] = '\f'; i++; break;
  159. case 'v': dst[j++] = '\v'; i++; break;
  160. case 'e': dst[j++] = '\33'; i++; break;
  161. case 'i': dst[j++] = '\''; i++; break; /* extra feature */
  162. case 'q': dst[j++] = '\"'; i++; break; /* extra feature */
  163. case 'x': i++;
  164. if (i < len && isxdigit(src[i]))
  165. {
  166. register p4char a = src[i++]-'0';
  167. if (a > '9') a -= 'A'-'9'+1;
  168. if (i < len && isxdigit (src[i]))
  169. {
  170. a <<= 4;
  171. if (src[i] <= '9') a |= src[i] - '0';
  172. else a |= src[i] - 'A' + 10;
  173. }
  174. dst[j++] = a;
  175. }else{
  176. p4_throw (P4_ON_INVALID_NUMBER);
  177. }
  178. break;
  179. default:
  180. if (! p4_isalnum (src[i]))
  181. dst[j++] = src[i++];
  182. else if (isdigit (src[i]))
  183. {
  184. register p4char a = src[i++]-'0';
  185. if (i < len && isdigit (src[i]))
  186. { a <<= 3; a |= src[i++]-'0'; }
  187. if (i < len && isdigit (src[i]))
  188. { a <<= 3; a |= src[i++]-'0'; }
  189. dst[j++] = a;
  190. }
  191. else if ('A' <= src[i] && src[i] <= 'Z')
  192. {
  193. dst[j++] = src[i++] & 31;
  194. }else{
  195. p4_throw (P4_ON_INVALID_NUMBER);
  196. }
  197. }
  198. }
  199. }
  200. dst[j] = '\0'; return j;
  201. }
  202. /** 'C\\\"' ( [backslashed-strings_<">] -- bstr* )
  203. * scan the following text to create a literal just
  204. * like =>'C"' does, but backslashes can be used to
  205. * escape special chars. The rules for the backslashes
  206. * follow C literals, implemented techniques are
  207. * \n \r \b \a \f \v \e \777
  208. * and all non-alnum chars represent themselves, esp.
  209. * \" \' \ \? \! \% \( \) \[ \] \{ \} etcetera.
  210. * most importantly the doublequote itself can be escaped.
  211. * but be also informed that the usage of \' and \" is not
  212. * portable as some systems preferred to map [\'] into ["].
  213. * Here I use the experimental addition to map [\q] to ["] and [\i] to [']
  214. */
  215. FCode (p4_c_backslash_quote)
  216. {
  217. p4char* p;
  218. p4ucell l;
  219. if (STATE)
  220. {
  221. FX_COMPILE(p4_c_backslash_quote);
  222. p = DP;
  223. }else{
  224. p = p4_pocket ();
  225. }
  226. p[0] = l = p4_backslash_parse_into ('"', p+1, 255, 127);
  227. if (STATE)
  228. {
  229. DP += l+1;
  230. FX (p4_align);
  231. }
  232. FX_PUSH (p);
  233. }
  234. P4COMPILES (p4_c_backslash_quote, p4_c_quote_execution,
  235. P4_SKIPS_STRING, P4_DEFAULT_STYLE);
  236. /** 'S\\\"' ( [backslashed-strings_<">] -- str cnt )
  237. * scan the following text to create a literal just
  238. * like =>'S"' does, but backslashes can be used to
  239. * escape special chars. The rules for the backslashes
  240. * follow C literals, implemented techniques are
  241. * \n \r \b \a \f \v \e \777
  242. * and all non-alnum chars represent themselves, esp.
  243. * \" \' \ \? \! \% \( \) \[ \] \{ \} etcetera.
  244. * most importantly the doublequote itself can be escaped.
  245. * but be also informed that the usage of \' and \" is not
  246. * portable as some systems preferred to map [\'] into ["].
  247. * Here I use the experimental addition to map [\q] to ["] and [\i] to [']
  248. */
  249. FCode (p4_s_backslash_quote)
  250. {
  251. p4char* p;
  252. p4ucell l;
  253. if (STATE)
  254. {
  255. FX_COMPILE(p4_s_backslash_quote);
  256. p = DP;
  257. }else{
  258. p = p4_pocket ();
  259. }
  260. p[0] = l = p4_backslash_parse_into ('"', p+1, 255, 127);
  261. if (STATE)
  262. {
  263. DP += l+1;
  264. FX (p4_align);
  265. }
  266. FX_PUSH (p+1);
  267. FX_PUSH (l);
  268. }
  269. P4COMPILES(p4_s_backslash_quote, p4_s_quote_execution,
  270. P4_SKIPS_STRING, P4_DEFAULT_STYLE);
  271. /** 'Z\\\"' ( [backslashed-strings_<">] -- zstr* )
  272. * scan the following text to create a literal just
  273. * like =>'Z"' does, but backslashes can be used to
  274. * escape special chars. The rules for the backslashes
  275. * follow C literals, implemented techniques are
  276. * \n \r \b \a \f \v \e \777
  277. * and all non-alnum chars represent themselves, esp.
  278. * \" \' \ \? \! \% \( \) \[ \] \{ \} etcetera.
  279. * most importantly the doublequote itself can be escaped
  280. * but be also informed that the usage of \' and \" is not
  281. * portable as some systems preferred to map [\'] into ["].
  282. * Here I use the experimental addition to map [\q] to ["] and [\i] to [']
  283. */
  284. FCode (p4_z_backslash_quote)
  285. {
  286. p4char* p;
  287. p4ucell l;
  288. if (STATE)
  289. {
  290. FX_COMPILE(p4_z_backslash_quote);
  291. p = DP;
  292. l = p4_backslash_parse_into ('"', p+sizeof(short), 65535, 32767);
  293. }else{
  294. p = p4_pocket ();
  295. l = p4_backslash_parse_into ('"', p+sizeof(short), 254, 126);
  296. }
  297. if (STATE)
  298. {
  299. DP += l+sizeof(short);
  300. FX (p4_align);
  301. (*(short*)p) = ((p4char*)DP - p);
  302. }
  303. FX_PUSH (p+sizeof(short));
  304. }
  305. P4COMPILES(p4_z_backslash_quote, p4_z_quote_XT,
  306. p4_z_quote_SEE, P4_DEFAULT_STYLE);
  307. P4_LISTWORDS(zchar) =
  308. {
  309. P4_INTO ("FORTH", 0 ),
  310. P4_SXco ("Z\"", p4_z_quote),
  311. P4_FXco ("ZCOUNT", p4_zcount),
  312. P4_FXco ("ZSTRLEN", p4_zstrlen),
  313. P4_FXco ("ZMOVE", p4_zmove),
  314. P4_FXco ("ZPLACE", p4_zplace),
  315. P4_FXco ("+ZPLACE", p4_appendz),
  316. P4_FNYM ("APPENDZ", "+ZPLACE"),
  317. P4_SXco ("S\\\"", p4_s_backslash_quote),
  318. P4_SXco ("C\\\"", p4_c_backslash_quote),
  319. P4_SXco ("Z\\\"", p4_z_backslash_quote),
  320. P4_INTO ("ENVIRONMENT", 0 ),
  321. P4_OCON ("ZCHAR-EXT", 2000 ),
  322. };
  323. P4_COUNTWORDS(zchar, "ZCHAR-EXT - zero-terminated C-like charstrings");
  324. /*
  325. * Local variables:
  326. * c-file-style: "stroustrup"
  327. * End:
  328. */