]>
cvs.zerfleddert.de Git - micropolis/blob - src/tclx/src/tclxstr.c
4 * Extended TCL string and character manipulation commands.
5 *-----------------------------------------------------------------------------
6 * Copyright 1992 Karl Lehenbauer and Mark Diekhans.
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation for any purpose and without fee is hereby granted, provided
10 * that the above copyright notice appear in all copies. Karl Lehenbauer and
11 * Mark Diekhans make no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
14 *-----------------------------------------------------------------------------
15 * $Id: tclXstring.c,v 2.0 1992/10/16 04:51:16 markd Rel $
16 *-----------------------------------------------------------------------------
22 * Prototypes of internal functions.
25 ExpandString
_ANSI_ARGS_((unsigned char *s
,
26 unsigned char buf
[]));
30 *-----------------------------------------------------------------------------
33 * Implements the cindex TCL command:
34 * cindex string indexExpr
37 * Returns the character indexed by index (zero based) from
40 *-----------------------------------------------------------------------------
43 Tcl_CindexCmd (clientData
, interp
, argc
, argv
)
44 ClientData clientData
;
52 Tcl_AppendResult (interp
, tclXWrongArgs
, argv
[0],
53 " string indexExpr", (char *) NULL
);
57 if (Tcl_ExprLong (interp
, argv
[2], &index
) != TCL_OK
)
59 if (index
>= strlen (argv
[1]))
62 interp
->result
[0] = argv
[1][index
];
63 interp
->result
[1] = 0;
69 *-----------------------------------------------------------------------------
72 * Implements the clength TCL command:
76 * Returns the length of string in characters.
78 *-----------------------------------------------------------------------------
81 Tcl_ClengthCmd (clientData
, interp
, argc
, argv
)
82 ClientData clientData
;
89 Tcl_AppendResult (interp
, tclXWrongArgs
, argv
[0], " string",
94 sprintf (interp
->result
, "%d", strlen (argv
[1]));
97 } /* Tcl_ClengthCmd */
100 *-----------------------------------------------------------------------------
103 * Implements the crange and csubstr TCL commands:
104 * crange string firstExpr lastExpr
105 * csubstr string firstExpr lengthExpr
108 * Standard Tcl result.
109 *-----------------------------------------------------------------------------
112 Tcl_CrangeCmd (clientData
, interp
, argc
, argv
)
113 ClientData clientData
;
122 int isRange
= (argv
[0][1] == 'r'); /* csubstr or crange */
125 Tcl_AppendResult (interp
, tclXWrongArgs
, argv
[0],
126 " string firstExpr ",
127 (isRange
) ? "lastExpr" : "lengthExpr",
132 if (Tcl_ExprLong (interp
, argv
[2], &first
) != TCL_OK
)
135 fullLen
= strlen (argv
[1]);
136 if (first
>= fullLen
)
139 if (STREQU (argv
[3], "end"))
140 subLen
= fullLen
- first
;
142 if (Tcl_ExprLong (interp
, argv
[3], &subLen
) != TCL_OK
)
146 if (subLen
< first
) {
147 Tcl_AppendResult (interp
, "last is before first",
151 subLen
= subLen
- first
+1;
154 if (first
+ subLen
> fullLen
)
155 subLen
= fullLen
- first
;
158 strPtr
= argv
[1] + first
;
160 holdChar
= strPtr
[subLen
];
161 strPtr
[subLen
] = '\0';
162 Tcl_SetResult (interp
, strPtr
, TCL_VOLATILE
);
163 strPtr
[subLen
] = holdChar
;
167 } /* Tcl_CrangeCmd */
170 *-----------------------------------------------------------------------------
172 * Tcl_ReplicateCmd --
173 * Implements the replicate TCL command:
174 * replicate string countExpr
175 * See the string(TCL) manual page.
178 * Returns string replicated count times.
180 *-----------------------------------------------------------------------------
183 Tcl_ReplicateCmd (clientData
, interp
, argc
, argv
)
184 ClientData clientData
;
190 register char *srcPtr
, *scanPtr
, *newPtr
;
191 register long newLen
, cnt
;
194 Tcl_AppendResult (interp
, tclXWrongArgs
, argv
[0],
195 " string countExpr", (char *) NULL
);
199 if (Tcl_ExprLong (interp
, argv
[2], &repCount
) != TCL_OK
)
203 newLen
= strlen (srcPtr
) * repCount
;
204 if (newLen
>= TCL_RESULT_SIZE
)
205 Tcl_SetResult (interp
, ckalloc ((unsigned) newLen
+ 1), TCL_DYNAMIC
);
207 newPtr
= interp
->result
;
208 for (cnt
= 0; cnt
< repCount
; cnt
++) {
209 for (scanPtr
= srcPtr
; *scanPtr
!= 0; scanPtr
++)
210 *newPtr
++ = *scanPtr
;
216 } /* Tcl_ReplicateCmd */
219 *-----------------------------------------------------------------------------
222 * Build an expand version of a translit range specification.
225 * TRUE it the expansion is ok, FALSE it its too long.
227 *-----------------------------------------------------------------------------
229 #define MAX_EXPANSION 255
232 ExpandString (s
, buf
)
239 while((*s
!=0) && i
< MAX_EXPANSION
) {
240 if(s
[1] == '-' && s
[2] > s
[0]) {
241 for(j
= s
[0]; j
<= s
[2]; j
++)
248 return (i
< MAX_EXPANSION
);
252 *-----------------------------------------------------------------------------
255 * Implements the TCL translit command:
256 * translit inrange outrange string
259 * Standard TCL results.
261 *-----------------------------------------------------------------------------
264 Tcl_TranslitCmd (clientData
, interp
, argc
, argv
)
265 ClientData clientData
;
270 unsigned char from
[MAX_EXPANSION
+1];
271 unsigned char to
[MAX_EXPANSION
+1];
272 unsigned char map
[MAX_EXPANSION
+1];
273 unsigned char *s
, *t
;
277 Tcl_AppendResult (interp
, tclXWrongArgs
, argv
[0],
278 " from to string", (char *) NULL
);
282 if (!ExpandString ((unsigned char *) argv
[1], from
)) {
283 interp
->result
= "inrange expansion too long";
287 if (!ExpandString ((unsigned char *) argv
[2], to
)) {
288 interp
->result
= "outrange expansion too long";
292 for (idx
= 0; idx
<= MAX_EXPANSION
; idx
++)
295 for (idx
= 0; to
[idx
] != '\0'; idx
++) {
296 if (from
[idx
] != '\0')
297 map
[from
[idx
]] = to
[idx
];
301 if (to
[idx
] != '\0') {
302 interp
->result
= "inrange longer than outrange";
306 for (; from
[idx
] != '\0'; idx
++)
307 map
[from
[idx
]] = 0;
309 for (s
= t
= (unsigned char *) argv
[3]; *s
!= '\0'; s
++) {
315 Tcl_SetResult (interp
, argv
[3], TCL_VOLATILE
);
321 *-----------------------------------------------------------------------------
325 * This function implements the 'ctype' command:
328 * Where class is one of the following:
329 * digit, xdigit, lower, upper, alpha, alnum,
330 * space, cntrl, punct, print, graph, ascii, char or ord.
333 * One or zero: Depending if all the characters in the string are of
334 * the desired class. Char and ord provide conversions and return the
337 *-----------------------------------------------------------------------------
340 Tcl_CtypeCmd (clientData
, interp
, argc
, argv
)
341 ClientData clientData
;
346 register char *class;
347 register char *scanPtr
= argv
[2];
350 Tcl_AppendResult (interp
, tclXWrongArgs
, argv
[0], " class string",
358 * Handle conversion requests.
360 if (STREQU (class, "char")) {
363 if (Tcl_GetInt (interp
, argv
[2], &number
) != TCL_OK
)
365 if ((number
< 0) || (number
> 255)) {
366 Tcl_AppendResult (interp
, "number must be in the range 0..255",
371 interp
->result
[0] = number
;
372 interp
->result
[1] = 0;
376 if (STREQU (class, "ord")) {
377 if (strlen (argv
[2]) != 1) {
378 Tcl_AppendResult (interp
, "string to convert must be only one",
379 " character", (char *) NULL
);
383 sprintf(interp
->result
, "%d", (int)(*argv
[2]));
388 * Select based on the first letter of the 'class' argument to chose the
389 * macro to test characters with. In some cases another character must be
390 * switched on to determine which macro to use. This is gross, but better
391 * we only have to do a string compare once to test if class is correct.
393 if ((class [2] == 'n') && STREQU (class, "alnum")) {
394 for (; *scanPtr
!= 0; scanPtr
++) {
395 if (!isalnum (*scanPtr
))
400 if ((class [2] == 'p') && STREQU (class, "alpha")) {
401 for (; *scanPtr
!= 0; scanPtr
++) {
402 if (! isalpha (*scanPtr
))
407 if ((class [1] == 's') && STREQU (class, "ascii")) {
408 for (; *scanPtr
!= 0; scanPtr
++) {
409 if (!isascii (*scanPtr
))
414 if (STREQU (class, "cntrl")) {
415 for (; *scanPtr
!= 0; scanPtr
++) {
416 if (!iscntrl (*scanPtr
))
421 if (STREQU (class, "digit")) {
422 for (; *scanPtr
!= 0; scanPtr
++) {
423 if (!isdigit (*scanPtr
))
428 if (STREQU (class, "graph")) {
429 for (; *scanPtr
!= 0; scanPtr
++) {
430 if (!isgraph (*scanPtr
))
435 if (STREQU (class, "lower")) {
436 for (; *scanPtr
!= 0; scanPtr
++) {
437 if (!islower (*scanPtr
))
442 if ((class [1] == 'r') && STREQU (class, "print")) {
443 for (; *scanPtr
!= 0; scanPtr
++) {
444 if (!isprint (*scanPtr
))
449 if ((class [1] == 'u') && STREQU (class, "punct")) {
450 for (; *scanPtr
!= 0; scanPtr
++) {
451 if (!ispunct (*scanPtr
))
456 if (STREQU (class, "space")) {
457 for (; *scanPtr
!= 0; scanPtr
++) {
458 if (!isspace (*scanPtr
))
463 if (STREQU (class, "upper")) {
464 for (; *scanPtr
!= 0; scanPtr
++) {
465 if (!isupper (*scanPtr
))
470 if (STREQU (class, "xdigit")) {
471 for (; *scanPtr
!= 0; scanPtr
++) {
472 if (!isxdigit (*scanPtr
))
478 * No match on subcommand.
480 Tcl_AppendResult (interp
, "unrecognized class specification: \"", class,
481 "\", expected one of: alnum, alpha, ascii, char, ",
482 "cntrl, digit, graph, lower, ord, print, punct, space, ",
483 "upper or xdigit", (char *) NULL
);
487 * Return true or false, depending if the end was reached. Always return
488 * false for a null string.
491 if ((*scanPtr
== 0) && (scanPtr
!= argv
[2]))
492 interp
->result
= "1";
494 interp
->result
= "0";