PageRenderTime 54ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

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

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