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

/tags/V_34_10/libpfe/src/main/c/zchar-ext.c

#
C | 368 lines | 322 code | 9 blank | 37 comment | 2 complexity | a397df143990f3caa9f7efb2dcdda3bc 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 - 2008 Guido U. Draheim <guidod@gmx.de>
  5. *
  6. * @see GNU LGPL
  7. * @author Guido U. Draheim (modified by $Author: guidod $)
  8. * @version $Revision: 1.7 $
  9. * (modified $Date: 2008-09-11 01:27:20 $)
  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. NAMELEN(s->name), NAMEPTR(s->name),
  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 'z': dst[j++] = '\0'; i++; break;
  155. case 't': dst[j++] = '\t'; i++; break;
  156. case 'n': dst[j++] = '\n'; i++; break;
  157. case 'l': dst[j++] = '\n'; i++; break;
  158. case 'r': dst[j++] = '\r'; i++; break;
  159. case 'm': dst[j++] = '\r'; i++;
  160. dst[j++] = '\n'; i++; break;
  161. case 'b': dst[j++] = '\b'; i++; break;
  162. case 'a': dst[j++] = '\a'; i++; break;
  163. case 'f': dst[j++] = '\f'; i++; break;
  164. case 'v': dst[j++] = '\v'; i++; break;
  165. case 'e': dst[j++] = '\33'; i++; break;
  166. case 'i': dst[j++] = '\''; i++; break; /* extra feature */
  167. case 'q': dst[j++] = '\"'; i++; break; /* extra feature */
  168. case 'x': i++;
  169. if (i < len && isxdigit(src[i]))
  170. {
  171. register p4char a = src[i++]-'0';
  172. if (a > '9') a -= 'A'-'9'+1;
  173. if (i < len && isxdigit (src[i]))
  174. {
  175. a <<= 4;
  176. if (src[i] <= '9') a |= src[i] - '0';
  177. else a |= src[i] - 'A' + 10;
  178. }
  179. dst[j++] = a;
  180. }else{
  181. p4_throw (P4_ON_INVALID_NUMBER);
  182. }
  183. break;
  184. default:
  185. if (! p4_isalnum (src[i]))
  186. dst[j++] = src[i++];
  187. else if (isdigit (src[i]))
  188. {
  189. register p4char a = src[i++]-'0';
  190. if (i < len && isdigit (src[i]))
  191. { a <<= 3; a |= src[i++]-'0'; }
  192. if (i < len && isdigit (src[i]))
  193. { a <<= 3; a |= src[i++]-'0'; }
  194. dst[j++] = a;
  195. }
  196. else if ('A' <= src[i] && src[i] <= 'Z')
  197. {
  198. dst[j++] = src[i++] & 31;
  199. }else{
  200. p4_throw (P4_ON_INVALID_NUMBER);
  201. }
  202. }
  203. }
  204. }
  205. dst[j] = '\0'; return j;
  206. }
  207. /** 'C\\\"' ( [backslashed-strings_<">] -- bstr* )
  208. * scan the following text to create a literal just
  209. * like =>'C"' does, but backslashes can be used to
  210. * escape special chars. The rules for the backslashes
  211. * follow C literals, implemented techniques are
  212. * \n \r \b \a \f \v \e \777
  213. * and all non-alnum chars represent themselves, esp.
  214. * \" \' \ \? \! \% \( \) \[ \] \{ \} etcetera.
  215. * most importantly the doublequote itself can be escaped.
  216. * but be also informed that the usage of \' and \" is not
  217. * portable as some systems preferred to map [\'] into ["].
  218. * Here I use the experimental addition to map [\q] to ["] and [\i] to [']
  219. */
  220. FCode (p4_c_backslash_quote)
  221. {
  222. p4char* p;
  223. p4ucell l;
  224. if (STATE)
  225. {
  226. FX_COMPILE(p4_c_backslash_quote);
  227. p = DP;
  228. }else{
  229. p = p4_pocket ();
  230. }
  231. p[0] = l = p4_backslash_parse_into ('"', p+1, 255, 127);
  232. if (STATE)
  233. {
  234. DP += l+1;
  235. FX (p4_align);
  236. }
  237. FX_PUSH (p);
  238. }
  239. P4COMPILES (p4_c_backslash_quote, p4_c_quote_execution,
  240. P4_SKIPS_STRING, P4_DEFAULT_STYLE);
  241. /** 'S\\\"' ( [backslashed-strings_<">] -- str cnt )
  242. * scan the following text to create a literal just
  243. * like =>'S"' does, but backslashes can be used to
  244. * escape special chars. The rules for the backslashes
  245. * follow C literals, implemented techniques are
  246. * \n \r \b \a \f \v \e \777
  247. * and all non-alnum chars represent themselves, esp.
  248. * \" \' \ \? \! \% \( \) \[ \] \{ \} etcetera.
  249. * most importantly the doublequote itself can be escaped.
  250. * but be also informed that the usage of \' and \" is not
  251. * portable as some systems preferred to map [\'] into ["].
  252. * Here I use the experimental addition to map [\q] to ["] and [\i] to [']
  253. */
  254. FCode (p4_s_backslash_quote)
  255. {
  256. p4char* p;
  257. p4ucell l;
  258. if (STATE)
  259. {
  260. FX_COMPILE(p4_s_backslash_quote);
  261. p = DP;
  262. }else{
  263. p = p4_pocket ();
  264. }
  265. p[0] = l = p4_backslash_parse_into ('"', p+1, 255, 127);
  266. if (STATE)
  267. {
  268. DP += l+1;
  269. FX (p4_align);
  270. }
  271. FX_PUSH (p+1);
  272. FX_PUSH (l);
  273. }
  274. P4COMPILES(p4_s_backslash_quote, p4_s_quote_execution,
  275. P4_SKIPS_STRING, P4_DEFAULT_STYLE);
  276. /** 'Z\\\"' ( [backslashed-strings_<">] -- zstr* )
  277. * scan the following text to create a literal just
  278. * like =>'Z"' does, but backslashes can be used to
  279. * escape special chars. The rules for the backslashes
  280. * follow C literals, implemented techniques are
  281. * \n \r \b \a \f \v \e \777
  282. * and all non-alnum chars represent themselves, esp.
  283. * \" \' \ \? \! \% \( \) \[ \] \{ \} etcetera.
  284. * most importantly the doublequote itself can be escaped
  285. * but be also informed that the usage of \' and \" is not
  286. * portable as some systems preferred to map [\'] into ["].
  287. * Here I use the experimental addition to map [\q] to ["] and [\i] to [']
  288. */
  289. FCode (p4_z_backslash_quote)
  290. {
  291. p4char* p;
  292. p4ucell l;
  293. if (STATE)
  294. {
  295. FX_COMPILE(p4_z_backslash_quote);
  296. p = DP;
  297. l = p4_backslash_parse_into ('"', p+sizeof(short), 65535, 32767);
  298. }else{
  299. p = p4_pocket ();
  300. l = p4_backslash_parse_into ('"', p+sizeof(short), 254, 126);
  301. }
  302. if (STATE)
  303. {
  304. DP += l+sizeof(short);
  305. FX (p4_align);
  306. (*(short*)p) = ((p4char*)DP - p);
  307. }
  308. FX_PUSH (p+sizeof(short));
  309. }
  310. P4COMPILES(p4_z_backslash_quote, p4_z_quote_XT,
  311. p4_z_quote_SEE, P4_DEFAULT_STYLE);
  312. P4_LISTWORDS(zchar) =
  313. {
  314. P4_INTO ("FORTH", 0 ),
  315. P4_SXco ("Z\"", p4_z_quote),
  316. P4_FXco ("ZCOUNT", p4_zcount),
  317. P4_FXco ("ZSTRLEN", p4_zstrlen),
  318. P4_FXco ("ZMOVE", p4_zmove),
  319. P4_FXco ("ZPLACE", p4_zplace),
  320. P4_FXco ("+ZPLACE", p4_appendz),
  321. P4_FNYM ("APPENDZ", "+ZPLACE"),
  322. P4_SXco ("S\\\"", p4_s_backslash_quote),
  323. P4_SXco ("C\\\"", p4_c_backslash_quote),
  324. P4_SXco ("Z\\\"", p4_z_backslash_quote),
  325. P4_INTO ("ENVIRONMENT", 0 ),
  326. P4_OCON ("ZCHAR-EXT", 2000 ),
  327. P4_OCON ("forth200x/escaped-strings", 2007 ),
  328. P4_SHOW ("X:escaped-strings", "forth200x/escaped-strings 2007" ),
  329. };
  330. P4_COUNTWORDS(zchar, "ZCHAR-EXT - zero-terminated C-like charstrings");
  331. /*
  332. * Local variables:
  333. * c-file-style: "stroustrup"
  334. * End:
  335. */