string.c revision f14f4646
15dfecf96Smrg/* 25dfecf96Smrg * Copyright (c) 2001 by The XFree86 Project, Inc. 35dfecf96Smrg * 45dfecf96Smrg * Permission is hereby granted, free of charge, to any person obtaining a 55dfecf96Smrg * copy of this software and associated documentation files (the "Software"), 65dfecf96Smrg * to deal in the Software without restriction, including without limitation 75dfecf96Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 85dfecf96Smrg * and/or sell copies of the Software, and to permit persons to whom the 95dfecf96Smrg * Software is furnished to do so, subject to the following conditions: 105dfecf96Smrg * 115dfecf96Smrg * The above copyright notice and this permission notice shall be included in 125dfecf96Smrg * all copies or substantial portions of the Software. 135dfecf96Smrg * 145dfecf96Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 155dfecf96Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 165dfecf96Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 175dfecf96Smrg * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 185dfecf96Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 195dfecf96Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 205dfecf96Smrg * SOFTWARE. 215dfecf96Smrg * 225dfecf96Smrg * Except as contained in this notice, the name of the XFree86 Project shall 235dfecf96Smrg * not be used in advertising or otherwise to promote the sale, use or other 245dfecf96Smrg * dealings in this Software without prior written authorization from the 255dfecf96Smrg * XFree86 Project. 265dfecf96Smrg * 275dfecf96Smrg * Author: Paulo César Pereira de Andrade 285dfecf96Smrg */ 295dfecf96Smrg 30f14f4646Smrg/* $XdotOrg: xc/programs/xedit/lisp/string.c,v 1.2 2004/04/23 19:54:44 eich Exp $ */ 315dfecf96Smrg/* $XFree86: xc/programs/xedit/lisp/string.c,v 1.24tsi Exp $ */ 325dfecf96Smrg 335dfecf96Smrg#include "lisp/helper.h" 345dfecf96Smrg#include "lisp/read.h" 355dfecf96Smrg#include "lisp/string.h" 365dfecf96Smrg#include "lisp/private.h" 375dfecf96Smrg#include <ctype.h> 385dfecf96Smrg 395dfecf96Smrg#define CHAR_LESS 1 405dfecf96Smrg#define CHAR_LESS_EQUAL 2 415dfecf96Smrg#define CHAR_EQUAL 3 425dfecf96Smrg#define CHAR_GREATER_EQUAL 4 435dfecf96Smrg#define CHAR_GREATER 5 445dfecf96Smrg#define CHAR_NOT_EQUAL 6 455dfecf96Smrg 465dfecf96Smrg#define CHAR_ALPHAP 1 475dfecf96Smrg#define CHAR_DOWNCASE 2 485dfecf96Smrg#define CHAR_UPCASE 3 495dfecf96Smrg#define CHAR_INT 4 505dfecf96Smrg#define CHAR_BOTHP 5 515dfecf96Smrg#define CHAR_UPPERP 6 525dfecf96Smrg#define CHAR_LOWERP 7 535dfecf96Smrg#define CHAR_GRAPHICP 8 545dfecf96Smrg 555dfecf96Smrg#ifndef MIN 565dfecf96Smrg#define MIN(a, b) ((a) < (b) ? (a) : (b)) 575dfecf96Smrg#endif 585dfecf96Smrg 595dfecf96Smrg/* 605dfecf96Smrg * Prototypes 615dfecf96Smrg */ 625dfecf96Smrgstatic LispObj *LispCharCompare(LispBuiltin*, int, int); 635dfecf96Smrgstatic LispObj *LispStringCompare(LispBuiltin*, int, int); 645dfecf96Smrgstatic LispObj *LispCharOp(LispBuiltin*, int); 655dfecf96Smrgstatic LispObj *LispStringTrim(LispBuiltin*, int, int, int); 665dfecf96Smrgstatic LispObj *LispStringUpcase(LispBuiltin*, int); 675dfecf96Smrgstatic LispObj *LispStringDowncase(LispBuiltin*, int); 685dfecf96Smrgstatic LispObj *LispStringCapitalize(LispBuiltin*, int); 695dfecf96Smrg 705dfecf96Smrg/* 715dfecf96Smrg * Implementation 725dfecf96Smrg */ 735dfecf96Smrgstatic LispObj * 745dfecf96SmrgLispCharCompare(LispBuiltin *builtin, int operation, int ignore_case) 755dfecf96Smrg{ 765dfecf96Smrg LispObj *object; 775dfecf96Smrg int cmp, value, next_value; 785dfecf96Smrg 795dfecf96Smrg LispObj *character, *more_characters; 805dfecf96Smrg 815dfecf96Smrg more_characters = ARGUMENT(1); 825dfecf96Smrg character = ARGUMENT(0); 835dfecf96Smrg 845dfecf96Smrg CHECK_SCHAR(character); 855dfecf96Smrg value = SCHAR_VALUE(character); 865dfecf96Smrg if (ignore_case && islower(value)) 875dfecf96Smrg value = toupper(value); 885dfecf96Smrg 895dfecf96Smrg if (!CONSP(more_characters)) 905dfecf96Smrg return (T); 915dfecf96Smrg 925dfecf96Smrg /* First check if all parameters are characters */ 935dfecf96Smrg for (object = more_characters; CONSP(object); object = CDR(object)) 945dfecf96Smrg CHECK_SCHAR(CAR(object)); 955dfecf96Smrg 965dfecf96Smrg /* All characters in list must be different */ 975dfecf96Smrg if (operation == CHAR_NOT_EQUAL) { 985dfecf96Smrg /* Compare all characters */ 995dfecf96Smrg do { 1005dfecf96Smrg for (object = more_characters; CONSP(object); object = CDR(object)) { 1015dfecf96Smrg character = CAR(object); 1025dfecf96Smrg next_value = SCHAR_VALUE(character); 1035dfecf96Smrg if (ignore_case && islower(next_value)) 1045dfecf96Smrg next_value = toupper(next_value); 1055dfecf96Smrg if (value == next_value) 1065dfecf96Smrg return (NIL); 1075dfecf96Smrg } 1085dfecf96Smrg value = SCHAR_VALUE(CAR(more_characters)); 1095dfecf96Smrg if (ignore_case && islower(value)) 1105dfecf96Smrg value = toupper(value); 1115dfecf96Smrg more_characters = CDR(more_characters); 1125dfecf96Smrg } while (CONSP(more_characters)); 1135dfecf96Smrg 1145dfecf96Smrg return (T); 1155dfecf96Smrg } 1165dfecf96Smrg 1175dfecf96Smrg /* Linearly compare characters */ 1185dfecf96Smrg for (; CONSP(more_characters); more_characters = CDR(more_characters)) { 1195dfecf96Smrg character = CAR(more_characters); 1205dfecf96Smrg next_value = SCHAR_VALUE(character); 1215dfecf96Smrg if (ignore_case && islower(next_value)) 1225dfecf96Smrg next_value = toupper(next_value); 1235dfecf96Smrg 1245dfecf96Smrg switch (operation) { 1255dfecf96Smrg case CHAR_LESS: cmp = value < next_value; break; 1265dfecf96Smrg case CHAR_LESS_EQUAL: cmp = value <= next_value; break; 1275dfecf96Smrg case CHAR_EQUAL: cmp = value == next_value; break; 1285dfecf96Smrg case CHAR_GREATER_EQUAL: cmp = value >= next_value; break; 1295dfecf96Smrg case CHAR_GREATER: cmp = value > next_value; break; 1305dfecf96Smrg default: cmp = 0; break; 1315dfecf96Smrg } 1325dfecf96Smrg 1335dfecf96Smrg if (!cmp) 1345dfecf96Smrg return (NIL); 1355dfecf96Smrg value = next_value; 1365dfecf96Smrg } 1375dfecf96Smrg 1385dfecf96Smrg return (T); 1395dfecf96Smrg} 1405dfecf96Smrg 1415dfecf96SmrgLispObj * 1425dfecf96SmrgLisp_CharLess(LispBuiltin *builtin) 1435dfecf96Smrg/* 1445dfecf96Smrg char< character &rest more-characters 1455dfecf96Smrg */ 1465dfecf96Smrg{ 1475dfecf96Smrg return (LispCharCompare(builtin, CHAR_LESS, 0)); 1485dfecf96Smrg} 1495dfecf96Smrg 1505dfecf96SmrgLispObj * 1515dfecf96SmrgLisp_CharLessEqual(LispBuiltin *builtin) 1525dfecf96Smrg/* 1535dfecf96Smrg char<= character &rest more-characters 1545dfecf96Smrg */ 1555dfecf96Smrg{ 1565dfecf96Smrg return (LispCharCompare(builtin, CHAR_LESS_EQUAL, 0)); 1575dfecf96Smrg} 1585dfecf96Smrg 1595dfecf96SmrgLispObj * 1605dfecf96SmrgLisp_CharEqual_(LispBuiltin *builtin) 1615dfecf96Smrg/* 1625dfecf96Smrg char= character &rest more-characters 1635dfecf96Smrg */ 1645dfecf96Smrg{ 1655dfecf96Smrg return (LispCharCompare(builtin, CHAR_EQUAL, 0)); 1665dfecf96Smrg} 1675dfecf96Smrg 1685dfecf96SmrgLispObj * 1695dfecf96SmrgLisp_CharGreater(LispBuiltin *builtin) 1705dfecf96Smrg/* 1715dfecf96Smrg char> character &rest more-characters 1725dfecf96Smrg */ 1735dfecf96Smrg{ 1745dfecf96Smrg return (LispCharCompare(builtin, CHAR_GREATER, 0)); 1755dfecf96Smrg} 1765dfecf96Smrg 1775dfecf96SmrgLispObj * 1785dfecf96SmrgLisp_CharGreaterEqual(LispBuiltin *builtin) 1795dfecf96Smrg/* 1805dfecf96Smrg char>= character &rest more-characters 1815dfecf96Smrg */ 1825dfecf96Smrg{ 1835dfecf96Smrg return (LispCharCompare(builtin, CHAR_GREATER_EQUAL, 0)); 1845dfecf96Smrg} 1855dfecf96Smrg 1865dfecf96SmrgLispObj * 1875dfecf96SmrgLisp_CharNotEqual_(LispBuiltin *builtin) 1885dfecf96Smrg/* 1895dfecf96Smrg char/= character &rest more-characters 1905dfecf96Smrg */ 1915dfecf96Smrg{ 1925dfecf96Smrg return (LispCharCompare(builtin, CHAR_NOT_EQUAL, 0)); 1935dfecf96Smrg} 1945dfecf96Smrg 1955dfecf96SmrgLispObj * 1965dfecf96SmrgLisp_CharLessp(LispBuiltin *builtin) 1975dfecf96Smrg/* 1985dfecf96Smrg char-lessp character &rest more-characters 1995dfecf96Smrg */ 2005dfecf96Smrg{ 2015dfecf96Smrg return (LispCharCompare(builtin, CHAR_LESS, 1)); 2025dfecf96Smrg} 2035dfecf96Smrg 2045dfecf96SmrgLispObj * 2055dfecf96SmrgLisp_CharNotGreaterp(LispBuiltin *builtin) 2065dfecf96Smrg/* 2075dfecf96Smrg char-not-greaterp character &rest more-characters 2085dfecf96Smrg */ 2095dfecf96Smrg{ 2105dfecf96Smrg return (LispCharCompare(builtin, CHAR_LESS_EQUAL, 1)); 2115dfecf96Smrg} 2125dfecf96Smrg 2135dfecf96SmrgLispObj * 2145dfecf96SmrgLisp_CharEqual(LispBuiltin *builtin) 2155dfecf96Smrg/* 2165dfecf96Smrg char-equalp character &rest more-characters 2175dfecf96Smrg */ 2185dfecf96Smrg{ 2195dfecf96Smrg return (LispCharCompare(builtin, CHAR_EQUAL, 1)); 2205dfecf96Smrg} 2215dfecf96Smrg 2225dfecf96SmrgLispObj * 2235dfecf96SmrgLisp_CharGreaterp(LispBuiltin *builtin) 2245dfecf96Smrg/* 2255dfecf96Smrg char-greaterp character &rest more-characters 2265dfecf96Smrg */ 2275dfecf96Smrg{ 2285dfecf96Smrg return (LispCharCompare(builtin, CHAR_GREATER, 1)); 2295dfecf96Smrg} 2305dfecf96Smrg 2315dfecf96SmrgLispObj * 2325dfecf96SmrgLisp_CharNotLessp(LispBuiltin *builtin) 2335dfecf96Smrg/* 2345dfecf96Smrg char-not-lessp &rest more-characters 2355dfecf96Smrg */ 2365dfecf96Smrg{ 2375dfecf96Smrg return (LispCharCompare(builtin, CHAR_GREATER_EQUAL, 1)); 2385dfecf96Smrg} 2395dfecf96Smrg 2405dfecf96SmrgLispObj * 2415dfecf96SmrgLisp_CharNotEqual(LispBuiltin *builtin) 2425dfecf96Smrg/* 2435dfecf96Smrg char-not-equal character &rest more-characters 2445dfecf96Smrg */ 2455dfecf96Smrg{ 2465dfecf96Smrg return (LispCharCompare(builtin, CHAR_NOT_EQUAL, 1)); 2475dfecf96Smrg} 2485dfecf96Smrg 2495dfecf96Smrgstatic LispObj * 2505dfecf96SmrgLispCharOp(LispBuiltin *builtin, int operation) 2515dfecf96Smrg{ 2525dfecf96Smrg int value; 2535dfecf96Smrg LispObj *result, *character; 2545dfecf96Smrg 2555dfecf96Smrg character = ARGUMENT(0); 2565dfecf96Smrg CHECK_SCHAR(character); 2575dfecf96Smrg value = (int)SCHAR_VALUE(character); 2585dfecf96Smrg 2595dfecf96Smrg switch (operation) { 2605dfecf96Smrg case CHAR_ALPHAP: 2615dfecf96Smrg result = isalpha(value) ? T : NIL; 2625dfecf96Smrg break; 2635dfecf96Smrg case CHAR_DOWNCASE: 2645dfecf96Smrg result = SCHAR(tolower(value)); 2655dfecf96Smrg break; 2665dfecf96Smrg case CHAR_UPCASE: 2675dfecf96Smrg result = SCHAR(toupper(value)); 2685dfecf96Smrg break; 2695dfecf96Smrg case CHAR_INT: 2705dfecf96Smrg result = FIXNUM(value); 2715dfecf96Smrg break; 2725dfecf96Smrg case CHAR_BOTHP: 2735dfecf96Smrg result = isupper(value) || islower(value) ? T : NIL; 2745dfecf96Smrg break; 2755dfecf96Smrg case CHAR_UPPERP: 2765dfecf96Smrg result = isupper(value) ? T : NIL; 2775dfecf96Smrg break; 2785dfecf96Smrg case CHAR_LOWERP: 2795dfecf96Smrg result = islower(value) ? T : NIL; 2805dfecf96Smrg break; 2815dfecf96Smrg case CHAR_GRAPHICP: 2825dfecf96Smrg result = value == ' ' || isgraph(value) ? T : NIL; 2835dfecf96Smrg break; 2845dfecf96Smrg default: 2855dfecf96Smrg result = NIL; 2865dfecf96Smrg break; 2875dfecf96Smrg } 2885dfecf96Smrg 2895dfecf96Smrg return (result); 2905dfecf96Smrg} 2915dfecf96Smrg 2925dfecf96SmrgLispObj * 2935dfecf96SmrgLisp_AlphaCharP(LispBuiltin *builtin) 2945dfecf96Smrg/* 2955dfecf96Smrg alpha-char-p char 2965dfecf96Smrg */ 2975dfecf96Smrg{ 2985dfecf96Smrg return (LispCharOp(builtin, CHAR_ALPHAP)); 2995dfecf96Smrg} 3005dfecf96Smrg 3015dfecf96SmrgLispObj * 3025dfecf96SmrgLisp_CharDowncase(LispBuiltin *builtin) 3035dfecf96Smrg/* 3045dfecf96Smrg char-downcase character 3055dfecf96Smrg */ 3065dfecf96Smrg{ 3075dfecf96Smrg return (LispCharOp(builtin, CHAR_DOWNCASE)); 3085dfecf96Smrg} 3095dfecf96Smrg 3105dfecf96SmrgLispObj * 3115dfecf96SmrgLisp_CharInt(LispBuiltin *builtin) 3125dfecf96Smrg/* 3135dfecf96Smrg char-int character 3145dfecf96Smrg char-code character 3155dfecf96Smrg */ 3165dfecf96Smrg{ 3175dfecf96Smrg return (LispCharOp(builtin, CHAR_INT)); 3185dfecf96Smrg} 3195dfecf96Smrg 3205dfecf96SmrgLispObj * 3215dfecf96SmrgLisp_CharUpcase(LispBuiltin *builtin) 3225dfecf96Smrg/* 3235dfecf96Smrg char-upcase character 3245dfecf96Smrg */ 3255dfecf96Smrg{ 3265dfecf96Smrg return (LispCharOp(builtin, CHAR_UPCASE)); 3275dfecf96Smrg} 3285dfecf96Smrg 3295dfecf96SmrgLispObj * 3305dfecf96SmrgLisp_BothCaseP(LispBuiltin *builtin) 3315dfecf96Smrg/* 3325dfecf96Smrg both-case-p character 3335dfecf96Smrg */ 3345dfecf96Smrg{ 3355dfecf96Smrg return (LispCharOp(builtin, CHAR_BOTHP)); 3365dfecf96Smrg} 3375dfecf96Smrg 3385dfecf96SmrgLispObj * 3395dfecf96SmrgLisp_UpperCaseP(LispBuiltin *builtin) 3405dfecf96Smrg/* 3415dfecf96Smrg upper-case-p character 3425dfecf96Smrg */ 3435dfecf96Smrg{ 3445dfecf96Smrg return (LispCharOp(builtin, CHAR_UPPERP)); 3455dfecf96Smrg} 3465dfecf96Smrg 3475dfecf96SmrgLispObj * 3485dfecf96SmrgLisp_LowerCaseP(LispBuiltin *builtin) 3495dfecf96Smrg/* 3505dfecf96Smrg upper-case-p character 3515dfecf96Smrg */ 3525dfecf96Smrg{ 3535dfecf96Smrg return (LispCharOp(builtin, CHAR_LOWERP)); 3545dfecf96Smrg} 3555dfecf96Smrg 3565dfecf96SmrgLispObj * 3575dfecf96SmrgLisp_GraphicCharP(LispBuiltin *builtin) 3585dfecf96Smrg/* 3595dfecf96Smrg graphic-char-p char 3605dfecf96Smrg */ 3615dfecf96Smrg{ 3625dfecf96Smrg return (LispCharOp(builtin, CHAR_GRAPHICP)); 3635dfecf96Smrg} 3645dfecf96Smrg 3655dfecf96SmrgLispObj * 3665dfecf96SmrgLisp_Char(LispBuiltin *builtin) 3675dfecf96Smrg/* 3685dfecf96Smrg char string index 3695dfecf96Smrg schar simple-string index 3705dfecf96Smrg */ 3715dfecf96Smrg{ 3725dfecf96Smrg unsigned char *string; 3735dfecf96Smrg long offset, length; 3745dfecf96Smrg 3755dfecf96Smrg LispObj *ostring, *oindex; 3765dfecf96Smrg 3775dfecf96Smrg oindex = ARGUMENT(1); 3785dfecf96Smrg ostring = ARGUMENT(0); 3795dfecf96Smrg 3805dfecf96Smrg CHECK_STRING(ostring); 3815dfecf96Smrg CHECK_INDEX(oindex); 3825dfecf96Smrg offset = FIXNUM_VALUE(oindex); 3835dfecf96Smrg string = (unsigned char*)THESTR(ostring); 3845dfecf96Smrg length = STRLEN(ostring); 3855dfecf96Smrg 3865dfecf96Smrg if (offset >= length) 3875dfecf96Smrg LispDestroy("%s: index %ld too large for string length %ld", 3885dfecf96Smrg STRFUN(builtin), offset, length); 3895dfecf96Smrg 3905dfecf96Smrg return (SCHAR(string[offset])); 3915dfecf96Smrg} 3925dfecf96Smrg 3935dfecf96Smrg/* helper function for setf 3945dfecf96Smrg * DONT explicitly call. Non standard function 3955dfecf96Smrg */ 3965dfecf96SmrgLispObj * 3975dfecf96SmrgLisp_XeditCharStore(LispBuiltin *builtin) 3985dfecf96Smrg/* 3995dfecf96Smrg xedit::char-store string index value 4005dfecf96Smrg */ 4015dfecf96Smrg{ 4025dfecf96Smrg int character; 4035dfecf96Smrg long offset, length; 4045dfecf96Smrg LispObj *ostring, *oindex, *ovalue; 4055dfecf96Smrg 4065dfecf96Smrg ovalue = ARGUMENT(2); 4075dfecf96Smrg oindex = ARGUMENT(1); 4085dfecf96Smrg ostring = ARGUMENT(0); 4095dfecf96Smrg 4105dfecf96Smrg CHECK_STRING(ostring); 4115dfecf96Smrg CHECK_INDEX(oindex); 4125dfecf96Smrg length = STRLEN(ostring); 4135dfecf96Smrg offset = FIXNUM_VALUE(oindex); 4145dfecf96Smrg if (offset >= length) 4155dfecf96Smrg LispDestroy("%s: index %ld too large for string length %ld", 4165dfecf96Smrg STRFUN(builtin), offset, length); 4175dfecf96Smrg CHECK_SCHAR(ovalue); 4185dfecf96Smrg CHECK_STRING_WRITABLE(ostring); 4195dfecf96Smrg 4205dfecf96Smrg character = SCHAR_VALUE(ovalue); 4215dfecf96Smrg 4225dfecf96Smrg if (character < 0 || character > 255) 4235dfecf96Smrg LispDestroy("%s: cannot represent character %d", 4245dfecf96Smrg STRFUN(builtin), character); 4255dfecf96Smrg 4265dfecf96Smrg THESTR(ostring)[offset] = character; 4275dfecf96Smrg 4285dfecf96Smrg return (ovalue); 4295dfecf96Smrg} 4305dfecf96Smrg 4315dfecf96SmrgLispObj * 4325dfecf96SmrgLisp_Character(LispBuiltin *builtin) 4335dfecf96Smrg/* 4345dfecf96Smrg character object 4355dfecf96Smrg */ 4365dfecf96Smrg{ 4375dfecf96Smrg LispObj *object; 4385dfecf96Smrg 4395dfecf96Smrg object = ARGUMENT(0); 4405dfecf96Smrg 4415dfecf96Smrg return (LispCharacterCoerce(builtin, object)); 4425dfecf96Smrg} 4435dfecf96Smrg 4445dfecf96SmrgLispObj * 4455dfecf96SmrgLisp_Characterp(LispBuiltin *builtin) 4465dfecf96Smrg/* 4475dfecf96Smrg characterp object 4485dfecf96Smrg */ 4495dfecf96Smrg{ 4505dfecf96Smrg LispObj *object; 4515dfecf96Smrg 4525dfecf96Smrg object = ARGUMENT(0); 4535dfecf96Smrg 4545dfecf96Smrg return (SCHARP(object) ? T : NIL); 4555dfecf96Smrg} 4565dfecf96Smrg 4575dfecf96SmrgLispObj * 4585dfecf96SmrgLisp_DigitChar(LispBuiltin *builtin) 4595dfecf96Smrg/* 4605dfecf96Smrg digit-char weight &optional radix 4615dfecf96Smrg */ 4625dfecf96Smrg{ 4635dfecf96Smrg long radix = 10, weight; 4645dfecf96Smrg LispObj *oweight, *oradix, *result = NIL; 4655dfecf96Smrg 4665dfecf96Smrg oradix = ARGUMENT(1); 4675dfecf96Smrg oweight = ARGUMENT(0); 4685dfecf96Smrg 4695dfecf96Smrg CHECK_FIXNUM(oweight); 4705dfecf96Smrg weight = FIXNUM_VALUE(oweight); 4715dfecf96Smrg 4725dfecf96Smrg if (oradix != UNSPEC) { 4735dfecf96Smrg CHECK_INDEX(oradix); 4745dfecf96Smrg radix = FIXNUM_VALUE(oradix); 4755dfecf96Smrg } 4765dfecf96Smrg if (radix < 2 || radix > 36) 4775dfecf96Smrg LispDestroy("%s: radix must be >= 2 and <= 36, not %ld", 4785dfecf96Smrg STRFUN(builtin), radix); 4795dfecf96Smrg 4805dfecf96Smrg if (weight >= 0 && weight < radix) { 4815dfecf96Smrg if (weight < 9) 4825dfecf96Smrg weight += '0'; 4835dfecf96Smrg else 4845dfecf96Smrg weight += 'A' - 10; 4855dfecf96Smrg result = SCHAR(weight); 4865dfecf96Smrg } 4875dfecf96Smrg 4885dfecf96Smrg return (result); 4895dfecf96Smrg} 4905dfecf96Smrg 4915dfecf96SmrgLispObj * 4925dfecf96SmrgLisp_DigitCharP(LispBuiltin *builtin) 4935dfecf96Smrg/* 4945dfecf96Smrg digit-char-p character &optional radix 4955dfecf96Smrg */ 4965dfecf96Smrg{ 4975dfecf96Smrg long radix = 10, character; 4985dfecf96Smrg LispObj *ochar, *oradix, *result = NIL; 4995dfecf96Smrg 5005dfecf96Smrg oradix = ARGUMENT(1); 5015dfecf96Smrg ochar = ARGUMENT(0); 5025dfecf96Smrg 5035dfecf96Smrg CHECK_SCHAR(ochar); 5045dfecf96Smrg character = SCHAR_VALUE(ochar); 5055dfecf96Smrg if (oradix != UNSPEC) { 5065dfecf96Smrg CHECK_INDEX(oradix); 5075dfecf96Smrg radix = FIXNUM_VALUE(oradix); 5085dfecf96Smrg } 5095dfecf96Smrg if (radix < 2 || radix > 36) 5105dfecf96Smrg LispDestroy("%s: radix must be >= 2 and <= 36, not %ld", 5115dfecf96Smrg STRFUN(builtin), radix); 5125dfecf96Smrg 5135dfecf96Smrg if (character >= '0' && character <= '9') 5145dfecf96Smrg character -= '0'; 5155dfecf96Smrg else if (character >= 'A' && character <= 'Z') 5165dfecf96Smrg character -= 'A' - 10; 5175dfecf96Smrg else if (character >= 'a' && character <= 'z') 5185dfecf96Smrg character -= 'a' - 10; 5195dfecf96Smrg if (character < radix) 5205dfecf96Smrg result = FIXNUM(character); 5215dfecf96Smrg 5225dfecf96Smrg return (result); 5235dfecf96Smrg} 5245dfecf96Smrg 5255dfecf96SmrgLispObj * 5265dfecf96SmrgLisp_IntChar(LispBuiltin *builtin) 5275dfecf96Smrg/* 5285dfecf96Smrg int-char integer 5295dfecf96Smrg code-char integer 5305dfecf96Smrg */ 5315dfecf96Smrg{ 5325dfecf96Smrg long character = 0; 5335dfecf96Smrg LispObj *integer; 5345dfecf96Smrg 5355dfecf96Smrg integer = ARGUMENT(0); 5365dfecf96Smrg 5375dfecf96Smrg CHECK_FIXNUM(integer); 5385dfecf96Smrg character = FIXNUM_VALUE(integer); 5395dfecf96Smrg 5405dfecf96Smrg return (character >= 0 && character < 0xff ? SCHAR(character) : NIL); 5415dfecf96Smrg} 5425dfecf96Smrg 5435dfecf96Smrg/* XXX ignoring element-type */ 5445dfecf96SmrgLispObj * 5455dfecf96SmrgLisp_MakeString(LispBuiltin *builtin) 5465dfecf96Smrg/* 5475dfecf96Smrg make-string size &key initial-element element-type 5485dfecf96Smrg */ 5495dfecf96Smrg{ 5505dfecf96Smrg long length; 5515dfecf96Smrg char *string, initial; 5525dfecf96Smrg 5535dfecf96Smrg LispObj *size, *initial_element; 5545dfecf96Smrg 5555dfecf96Smrg initial_element = ARGUMENT(1); 5565dfecf96Smrg size = ARGUMENT(0); 5575dfecf96Smrg 5585dfecf96Smrg CHECK_INDEX(size); 5595dfecf96Smrg length = FIXNUM_VALUE(size); 5605dfecf96Smrg if (initial_element != UNSPEC) { 5615dfecf96Smrg CHECK_SCHAR(initial_element); 5625dfecf96Smrg initial = SCHAR_VALUE(initial_element); 5635dfecf96Smrg } 5645dfecf96Smrg else 5655dfecf96Smrg initial = 0; 5665dfecf96Smrg 5675dfecf96Smrg string = LispMalloc(length + 1); 5685dfecf96Smrg memset(string, initial, length); 5695dfecf96Smrg string[length] = '\0'; 5705dfecf96Smrg 5715dfecf96Smrg return (LSTRING2(string, length)); 5725dfecf96Smrg} 5735dfecf96Smrg 5745dfecf96SmrgLispObj * 5755dfecf96SmrgLisp_ParseInteger(LispBuiltin *builtin) 5765dfecf96Smrg/* 5775dfecf96Smrg parse-integer string &key start end radix junk-allowed 5785dfecf96Smrg */ 5795dfecf96Smrg{ 5805dfecf96Smrg GC_ENTER(); 5815dfecf96Smrg char *ptr, *string; 5825dfecf96Smrg int character, junk, sign, overflow; 5835dfecf96Smrg long i, start, end, radix, length, integer, check; 5845dfecf96Smrg LispObj *result; 5855dfecf96Smrg 5865dfecf96Smrg LispObj *ostring, *ostart, *oend, *oradix, *junk_allowed; 5875dfecf96Smrg 5885dfecf96Smrg junk_allowed = ARGUMENT(4); 5895dfecf96Smrg oradix = ARGUMENT(3); 5905dfecf96Smrg oend = ARGUMENT(2); 5915dfecf96Smrg ostart = ARGUMENT(1); 5925dfecf96Smrg ostring = ARGUMENT(0); 5935dfecf96Smrg 5945dfecf96Smrg start = end = radix = 0; 5955dfecf96Smrg result = NIL; 5965dfecf96Smrg 5975dfecf96Smrg CHECK_STRING(ostring); 5985dfecf96Smrg LispCheckSequenceStartEnd(builtin, ostring, ostart, oend, 5995dfecf96Smrg &start, &end, &length); 6005dfecf96Smrg string = THESTR(ostring); 6015dfecf96Smrg if (oradix == UNSPEC) 6025dfecf96Smrg radix = 10; 6035dfecf96Smrg else { 6045dfecf96Smrg CHECK_INDEX(oradix); 6055dfecf96Smrg radix = FIXNUM_VALUE(oradix); 6065dfecf96Smrg } 6075dfecf96Smrg if (radix < 2 || radix > 36) 6085dfecf96Smrg LispDestroy("%s: :RADIX %ld must be in the range 2 to 36", 6095dfecf96Smrg STRFUN(builtin), radix); 6105dfecf96Smrg 6115dfecf96Smrg integer = check = 0; 6125dfecf96Smrg ptr = string + start; 6135dfecf96Smrg sign = overflow = 0; 6145dfecf96Smrg 6155dfecf96Smrg /* Skip leading white spaces */ 6165dfecf96Smrg for (i = start; i < end && *ptr && isspace(*ptr); ptr++, i++) 6175dfecf96Smrg ; 6185dfecf96Smrg 6195dfecf96Smrg /* Check for sign specification */ 6205dfecf96Smrg if (i < end && (*ptr == '-' || *ptr == '+')) { 6215dfecf96Smrg sign = *ptr == '-'; 6225dfecf96Smrg ++ptr; 6235dfecf96Smrg ++i; 6245dfecf96Smrg } 6255dfecf96Smrg 6265dfecf96Smrg for (junk = 0; i < end; i++, ptr++) { 6275dfecf96Smrg character = *ptr; 6285dfecf96Smrg if (islower(character)) 6295dfecf96Smrg character = toupper(character); 6305dfecf96Smrg if (character >= '0' && character <= '9') { 6315dfecf96Smrg if (character - '0' >= radix) 6325dfecf96Smrg junk = 1; 6335dfecf96Smrg else { 6345dfecf96Smrg check = integer; 6355dfecf96Smrg integer = integer * radix + character - '0'; 6365dfecf96Smrg } 6375dfecf96Smrg } 6385dfecf96Smrg else if (character >= 'A' && character <= 'Z') { 6395dfecf96Smrg if (character - 'A' + 10 >= radix) 6405dfecf96Smrg junk = 1; 6415dfecf96Smrg else { 6425dfecf96Smrg check = integer; 6435dfecf96Smrg integer = integer * radix + character - 'A' + 10; 6445dfecf96Smrg } 6455dfecf96Smrg } 6465dfecf96Smrg else { 6475dfecf96Smrg if (isspace(character)) 6485dfecf96Smrg break; 6495dfecf96Smrg junk = 1; 6505dfecf96Smrg } 6515dfecf96Smrg 6525dfecf96Smrg if (junk) 6535dfecf96Smrg break; 6545dfecf96Smrg 6555dfecf96Smrg if (!overflow && check > integer) 6565dfecf96Smrg overflow = 1; 6575dfecf96Smrg /* keep looping just to count read bytes */ 6585dfecf96Smrg } 6595dfecf96Smrg 6605dfecf96Smrg if (!junk) 6615dfecf96Smrg /* Skip white spaces */ 6625dfecf96Smrg for (; i < end && *ptr && isspace(*ptr); ptr++, i++) 6635dfecf96Smrg ; 6645dfecf96Smrg 6655dfecf96Smrg if ((junk || ptr == string) && 6665dfecf96Smrg (junk_allowed == UNSPEC || junk_allowed == NIL)) 6675dfecf96Smrg LispDestroy("%s: %s has a bad integer representation", 6685dfecf96Smrg STRFUN(builtin), STROBJ(ostring)); 6695dfecf96Smrg else if (ptr == string) 6705dfecf96Smrg result = NIL; 6715dfecf96Smrg else if (overflow) { 6725dfecf96Smrg mpi *bigi = LispMalloc(sizeof(mpi)); 6735dfecf96Smrg char *str; 6745dfecf96Smrg 6755dfecf96Smrg length = end - start + sign; 6765dfecf96Smrg str = LispMalloc(length + 1); 6775dfecf96Smrg 6785dfecf96Smrg strncpy(str, string - sign, length + sign); 6795dfecf96Smrg str[length + sign] = '\0'; 6805dfecf96Smrg mpi_init(bigi); 6815dfecf96Smrg mpi_setstr(bigi, str, radix); 6825dfecf96Smrg LispFree(str); 6835dfecf96Smrg result = BIGNUM(bigi); 6845dfecf96Smrg } 6855dfecf96Smrg else 6865dfecf96Smrg result = INTEGER(sign ? -integer : integer); 6875dfecf96Smrg 6885dfecf96Smrg GC_PROTECT(result); 6895dfecf96Smrg RETURN(0) = FIXNUM(i); 6905dfecf96Smrg RETURN_COUNT = 1; 6915dfecf96Smrg GC_LEAVE(); 6925dfecf96Smrg 6935dfecf96Smrg return (result); 6945dfecf96Smrg} 6955dfecf96Smrg 6965dfecf96SmrgLispObj * 6975dfecf96SmrgLisp_String(LispBuiltin *builtin) 6985dfecf96Smrg/* 6995dfecf96Smrg string object 7005dfecf96Smrg */ 7015dfecf96Smrg{ 7025dfecf96Smrg LispObj *object; 7035dfecf96Smrg 7045dfecf96Smrg object = ARGUMENT(0); 7055dfecf96Smrg 7065dfecf96Smrg return (LispStringCoerce(builtin, object)); 7075dfecf96Smrg} 7085dfecf96Smrg 7095dfecf96SmrgLispObj * 7105dfecf96SmrgLisp_Stringp(LispBuiltin *builtin) 7115dfecf96Smrg/* 7125dfecf96Smrg stringp object 7135dfecf96Smrg */ 7145dfecf96Smrg{ 7155dfecf96Smrg LispObj *object; 7165dfecf96Smrg 7175dfecf96Smrg object = ARGUMENT(0); 7185dfecf96Smrg 7195dfecf96Smrg return (STRINGP(object) ? T : NIL); 7205dfecf96Smrg} 7215dfecf96Smrg 7225dfecf96Smrg/* XXX preserve-whitespace is being ignored */ 7235dfecf96SmrgLispObj * 7245dfecf96SmrgLisp_ReadFromString(LispBuiltin *builtin) 7255dfecf96Smrg/* 7265dfecf96Smrg read-from-string string &optional eof-error-p eof-value &key start end preserve-whitespace 7275dfecf96Smrg */ 7285dfecf96Smrg{ 7295dfecf96Smrg GC_ENTER(); 7305dfecf96Smrg char *string; 7315dfecf96Smrg LispObj *stream, *result; 7325dfecf96Smrg long length, start, end, bytes_read; 7335dfecf96Smrg 7345dfecf96Smrg LispObj *ostring, *eof_error_p, *eof_value, *ostart, *oend; 7355dfecf96Smrg 7365dfecf96Smrg oend = ARGUMENT(4); 7375dfecf96Smrg ostart = ARGUMENT(3); 7385dfecf96Smrg eof_value = ARGUMENT(2); 7395dfecf96Smrg eof_error_p = ARGUMENT(1); 7405dfecf96Smrg ostring = ARGUMENT(0); 7415dfecf96Smrg 7425dfecf96Smrg CHECK_STRING(ostring); 7435dfecf96Smrg string = THESTR(ostring); 7445dfecf96Smrg LispCheckSequenceStartEnd(builtin, ostring, ostart, oend, 7455dfecf96Smrg &start, &end, &length); 7465dfecf96Smrg 7475dfecf96Smrg if (start > 0 || end < length) 7485dfecf96Smrg length = end - start; 7495dfecf96Smrg stream = LSTRINGSTREAM(string + start, STREAM_READ, length); 7505dfecf96Smrg 7515dfecf96Smrg if (eof_value == UNSPEC) 7525dfecf96Smrg eof_value = NIL; 7535dfecf96Smrg 7545dfecf96Smrg LispPushInput(stream); 7555dfecf96Smrg result = LispRead(); 7565dfecf96Smrg /* stream->data.stream.source.string->input is 7575dfecf96Smrg * the offset of the last byte read in string */ 7585dfecf96Smrg bytes_read = stream->data.stream.source.string->input; 7595dfecf96Smrg LispPopInput(stream); 7605dfecf96Smrg 7615dfecf96Smrg if (result == NULL) { 7625dfecf96Smrg if (eof_error_p == NIL) 7635dfecf96Smrg result = eof_value; 7645dfecf96Smrg else 7655dfecf96Smrg LispDestroy("%s: unexpected end of input", STRFUN(builtin)); 7665dfecf96Smrg } 7675dfecf96Smrg 7685dfecf96Smrg GC_PROTECT(result); 7695dfecf96Smrg RETURN(0) = FIXNUM(start + bytes_read); 7705dfecf96Smrg RETURN_COUNT = 1; 7715dfecf96Smrg GC_LEAVE(); 7725dfecf96Smrg 7735dfecf96Smrg return (result); 7745dfecf96Smrg} 7755dfecf96Smrg 7765dfecf96Smrgstatic LispObj * 7775dfecf96SmrgLispStringTrim(LispBuiltin *builtin, int left, int right, int inplace) 7785dfecf96Smrg/* 7795dfecf96Smrg string-{,left-,right-}trim character-bag string 7805dfecf96Smrg*/ 7815dfecf96Smrg{ 7825dfecf96Smrg unsigned char *string; 7835dfecf96Smrg long start, end, length; 7845dfecf96Smrg 7855dfecf96Smrg LispObj *ochars, *ostring; 7865dfecf96Smrg 7875dfecf96Smrg ostring = ARGUMENT(1); 7885dfecf96Smrg ochars = ARGUMENT(0); 7895dfecf96Smrg 7905dfecf96Smrg if (!POINTERP(ochars) || !(XSTRINGP(ochars) || XCONSP(ochars))) { 7915dfecf96Smrg if (ARRAYP(ochars) && ochars->data.array.rank == 1) 7925dfecf96Smrg ochars = ochars->data.array.list; 7935dfecf96Smrg else 7945dfecf96Smrg LispDestroy("%s: %s is not a sequence", 7955dfecf96Smrg STRFUN(builtin), STROBJ(ochars)); 7965dfecf96Smrg } 7975dfecf96Smrg CHECK_STRING(ostring); 7985dfecf96Smrg 7995dfecf96Smrg string = (unsigned char*)THESTR(ostring); 8005dfecf96Smrg length = STRLEN(ostring); 8015dfecf96Smrg 8025dfecf96Smrg start = 0; 8035dfecf96Smrg end = length; 8045dfecf96Smrg 8055dfecf96Smrg if (XSTRINGP(ochars)) { 8065dfecf96Smrg unsigned char *chars = (unsigned char*)THESTR(ochars); 8075dfecf96Smrg long i, clength = STRLEN(ochars); 8085dfecf96Smrg 8095dfecf96Smrg if (left) { 8105dfecf96Smrg for (; start < end; start++) { 8115dfecf96Smrg for (i = 0; i < clength; i++) 8125dfecf96Smrg if (string[start] == chars[i]) 8135dfecf96Smrg break; 8145dfecf96Smrg if (i >= clength) 8155dfecf96Smrg break; 8165dfecf96Smrg } 8175dfecf96Smrg } 8185dfecf96Smrg if (right) { 8195dfecf96Smrg for (--end; end >= 0; end--) { 8205dfecf96Smrg for (i = 0; i < clength; i++) 8215dfecf96Smrg if (string[end] == chars[i]) 8225dfecf96Smrg break; 8235dfecf96Smrg if (i >= clength) 8245dfecf96Smrg break; 8255dfecf96Smrg } 8265dfecf96Smrg ++end; 8275dfecf96Smrg } 8285dfecf96Smrg } 8295dfecf96Smrg else { 8305dfecf96Smrg LispObj *ochar, *list; 8315dfecf96Smrg 8325dfecf96Smrg if (left) { 8335dfecf96Smrg for (; start < end; start++) { 8345dfecf96Smrg for (list = ochars; CONSP(list); list = CDR(list)) { 8355dfecf96Smrg ochar = CAR(list); 8365dfecf96Smrg if (SCHARP(ochar) && string[start] == SCHAR_VALUE(ochar)) 8375dfecf96Smrg break; 8385dfecf96Smrg } 8395dfecf96Smrg if (!CONSP(list)) 8405dfecf96Smrg break; 8415dfecf96Smrg } 8425dfecf96Smrg } 8435dfecf96Smrg if (right) { 8445dfecf96Smrg for (--end; end >= 0; end--) { 8455dfecf96Smrg for (list = ochars; CONSP(list); list = CDR(list)) { 8465dfecf96Smrg ochar = CAR(list); 8475dfecf96Smrg if (SCHARP(ochar) && string[end] == SCHAR_VALUE(ochar)) 8485dfecf96Smrg break; 8495dfecf96Smrg } 8505dfecf96Smrg if (!CONSP(list)) 8515dfecf96Smrg break; 8525dfecf96Smrg } 8535dfecf96Smrg ++end; 8545dfecf96Smrg } 8555dfecf96Smrg } 8565dfecf96Smrg 8575dfecf96Smrg if (start == 0 && end == length) 8585dfecf96Smrg return (ostring); 8595dfecf96Smrg 8605dfecf96Smrg length = end - start; 8615dfecf96Smrg 8625dfecf96Smrg if (inplace) { 8635dfecf96Smrg CHECK_STRING_WRITABLE(ostring); 8645dfecf96Smrg memmove(string, string + start, length); 8655dfecf96Smrg string[length] = '\0'; 8665dfecf96Smrg STRLEN(ostring) = length; 8675dfecf96Smrg } 8685dfecf96Smrg else { 8695dfecf96Smrg string = LispMalloc(length + 1); 8705dfecf96Smrg memcpy(string, THESTR(ostring) + start, length); 8715dfecf96Smrg string[length] = '\0'; 8725dfecf96Smrg ostring = LSTRING2((char*)string, length); 8735dfecf96Smrg } 8745dfecf96Smrg 8755dfecf96Smrg return (ostring); 8765dfecf96Smrg} 8775dfecf96Smrg 8785dfecf96SmrgLispObj * 8795dfecf96SmrgLisp_StringTrim(LispBuiltin *builtin) 8805dfecf96Smrg/* 8815dfecf96Smrg string-trim character-bag string 8825dfecf96Smrg */ 8835dfecf96Smrg{ 8845dfecf96Smrg return (LispStringTrim(builtin, 1, 1, 0)); 8855dfecf96Smrg} 8865dfecf96Smrg 8875dfecf96SmrgLispObj * 8885dfecf96SmrgLisp_NstringTrim(LispBuiltin *builtin) 8895dfecf96Smrg/* 8905dfecf96Smrg ext::nstring-trim character-bag string 8915dfecf96Smrg */ 8925dfecf96Smrg{ 8935dfecf96Smrg return (LispStringTrim(builtin, 1, 1, 1)); 8945dfecf96Smrg} 8955dfecf96Smrg 8965dfecf96SmrgLispObj * 8975dfecf96SmrgLisp_StringLeftTrim(LispBuiltin *builtin) 8985dfecf96Smrg/* 8995dfecf96Smrg string-left-trim character-bag string 9005dfecf96Smrg */ 9015dfecf96Smrg{ 9025dfecf96Smrg return (LispStringTrim(builtin, 1, 0, 0)); 9035dfecf96Smrg} 9045dfecf96Smrg 9055dfecf96SmrgLispObj * 9065dfecf96SmrgLisp_NstringLeftTrim(LispBuiltin *builtin) 9075dfecf96Smrg/* 9085dfecf96Smrg ext::nstring-left-trim character-bag string 9095dfecf96Smrg */ 9105dfecf96Smrg{ 9115dfecf96Smrg return (LispStringTrim(builtin, 1, 0, 1)); 9125dfecf96Smrg} 9135dfecf96Smrg 9145dfecf96SmrgLispObj * 9155dfecf96SmrgLisp_StringRightTrim(LispBuiltin *builtin) 9165dfecf96Smrg/* 9175dfecf96Smrg string-right-trim character-bag string 9185dfecf96Smrg */ 9195dfecf96Smrg{ 9205dfecf96Smrg return (LispStringTrim(builtin, 0, 1, 0)); 9215dfecf96Smrg} 9225dfecf96Smrg 9235dfecf96SmrgLispObj * 9245dfecf96SmrgLisp_NstringRightTrim(LispBuiltin *builtin) 9255dfecf96Smrg/* 9265dfecf96Smrg ext::nstring-right-trim character-bag string 9275dfecf96Smrg */ 9285dfecf96Smrg{ 9295dfecf96Smrg return (LispStringTrim(builtin, 0, 1, 1)); 9305dfecf96Smrg} 9315dfecf96Smrg 9325dfecf96Smrgstatic LispObj * 9335dfecf96SmrgLispStringCompare(LispBuiltin *builtin, int function, int ignore_case) 9345dfecf96Smrg{ 9355dfecf96Smrg int cmp1, cmp2; 9365dfecf96Smrg LispObj *fixnum; 9375dfecf96Smrg unsigned char *string1, *string2; 9385dfecf96Smrg long start1, end1, start2, end2, offset, length; 9395dfecf96Smrg 9405dfecf96Smrg LispGetStringArgs(builtin, (char**)&string1, (char**)&string2, 9415dfecf96Smrg &start1, &end1, &start2, &end2); 9425dfecf96Smrg 9435dfecf96Smrg string1 += start1; 9445dfecf96Smrg string2 += start2; 9455dfecf96Smrg 9465dfecf96Smrg if (function == CHAR_EQUAL) { 9475dfecf96Smrg length = end1 - start1; 9485dfecf96Smrg 9495dfecf96Smrg if (length != (end2 - start2)) 9505dfecf96Smrg return (NIL); 9515dfecf96Smrg 9525dfecf96Smrg if (!ignore_case) 9535dfecf96Smrg return (memcmp(string1, string2, length) ? NIL : T); 9545dfecf96Smrg 9555dfecf96Smrg for (; length; length--, string1++, string2++) 9565dfecf96Smrg if (toupper(*string1) != toupper(*string2)) 9575dfecf96Smrg return (NIL); 9585dfecf96Smrg return (T); 9595dfecf96Smrg } 9605dfecf96Smrg 9615dfecf96Smrg end1 -= start1; 9625dfecf96Smrg end2 -= start2; 9635dfecf96Smrg length = MIN(end1, end2); 9645dfecf96Smrg for (offset = 0; 9655dfecf96Smrg offset < length; 9665dfecf96Smrg string1++, string2++, offset++, start1++, start2++) { 9675dfecf96Smrg cmp1 = *string1; 9685dfecf96Smrg cmp2 = *string2; 9695dfecf96Smrg if (ignore_case) { 9705dfecf96Smrg cmp1 = toupper(cmp1); 9715dfecf96Smrg cmp2 = toupper(cmp2); 9725dfecf96Smrg } 9735dfecf96Smrg if (cmp1 != cmp2) { 9745dfecf96Smrg fixnum = FIXNUM(start1); 9755dfecf96Smrg switch (function) { 9765dfecf96Smrg case CHAR_LESS: 9775dfecf96Smrg return ((cmp1 < cmp2) ? fixnum : NIL); 9785dfecf96Smrg case CHAR_LESS_EQUAL: 9795dfecf96Smrg return ((cmp1 <= cmp2) ? fixnum : NIL); 9805dfecf96Smrg case CHAR_NOT_EQUAL: 9815dfecf96Smrg return (fixnum); 9825dfecf96Smrg case CHAR_GREATER_EQUAL: 9835dfecf96Smrg return ((cmp1 >= cmp2) ? fixnum : NIL); 9845dfecf96Smrg case CHAR_GREATER: 9855dfecf96Smrg return ((cmp1 > cmp2) ? fixnum : NIL); 9865dfecf96Smrg } 9875dfecf96Smrg } 9885dfecf96Smrg } 9895dfecf96Smrg 9905dfecf96Smrg fixnum = FIXNUM(start1); 9915dfecf96Smrg switch (function) { 9925dfecf96Smrg case CHAR_LESS: 9935dfecf96Smrg return (start1 >= end1 && start2 < end2 ? fixnum : NIL); 9945dfecf96Smrg case CHAR_LESS_EQUAL: 9955dfecf96Smrg return (start1 >= end1 ? fixnum : NIL); 9965dfecf96Smrg case CHAR_NOT_EQUAL: 9975dfecf96Smrg return (start1 >= end1 && start2 >= end2 ? NIL : fixnum); 9985dfecf96Smrg case CHAR_GREATER_EQUAL: 9995dfecf96Smrg return (start2 >= end2 ? fixnum : NIL); 10005dfecf96Smrg case CHAR_GREATER: 10015dfecf96Smrg return (start2 >= end2 && start1 < end1 ? fixnum : NIL); 10025dfecf96Smrg } 10035dfecf96Smrg 10045dfecf96Smrg return (NIL); 10055dfecf96Smrg} 10065dfecf96Smrg 10075dfecf96SmrgLispObj * 10085dfecf96SmrgLisp_StringEqual_(LispBuiltin *builtin) 10095dfecf96Smrg/* 10105dfecf96Smrg string= string1 string2 &key start1 end1 start2 end2 10115dfecf96Smrg */ 10125dfecf96Smrg{ 10135dfecf96Smrg return (LispStringCompare(builtin, CHAR_EQUAL, 0)); 10145dfecf96Smrg} 10155dfecf96Smrg 10165dfecf96SmrgLispObj * 10175dfecf96SmrgLisp_StringLess(LispBuiltin *builtin) 10185dfecf96Smrg/* 10195dfecf96Smrg string< string1 string2 &key start1 end1 start2 end2 10205dfecf96Smrg */ 10215dfecf96Smrg{ 10225dfecf96Smrg return (LispStringCompare(builtin, CHAR_LESS, 0)); 10235dfecf96Smrg} 10245dfecf96Smrg 10255dfecf96SmrgLispObj * 10265dfecf96SmrgLisp_StringGreater(LispBuiltin *builtin) 10275dfecf96Smrg/* 10285dfecf96Smrg string> string1 string2 &key start1 end1 start2 end2 10295dfecf96Smrg */ 10305dfecf96Smrg{ 10315dfecf96Smrg return (LispStringCompare(builtin, CHAR_GREATER, 0)); 10325dfecf96Smrg} 10335dfecf96Smrg 10345dfecf96SmrgLispObj * 10355dfecf96SmrgLisp_StringLessEqual(LispBuiltin *builtin) 10365dfecf96Smrg/* 10375dfecf96Smrg string<= string1 string2 &key start1 end1 start2 end2 10385dfecf96Smrg */ 10395dfecf96Smrg{ 10405dfecf96Smrg return (LispStringCompare(builtin, CHAR_LESS_EQUAL, 0)); 10415dfecf96Smrg} 10425dfecf96Smrg 10435dfecf96SmrgLispObj * 10445dfecf96SmrgLisp_StringGreaterEqual(LispBuiltin *builtin) 10455dfecf96Smrg/* 10465dfecf96Smrg string>= string1 string2 &key start1 end1 start2 end2 10475dfecf96Smrg */ 10485dfecf96Smrg{ 10495dfecf96Smrg return (LispStringCompare(builtin, CHAR_GREATER_EQUAL, 0)); 10505dfecf96Smrg} 10515dfecf96Smrg 10525dfecf96SmrgLispObj * 10535dfecf96SmrgLisp_StringNotEqual_(LispBuiltin *builtin) 10545dfecf96Smrg/* 10555dfecf96Smrg string/= string1 string2 &key start1 end1 start2 end2 10565dfecf96Smrg */ 10575dfecf96Smrg{ 10585dfecf96Smrg return (LispStringCompare(builtin, CHAR_NOT_EQUAL, 0)); 10595dfecf96Smrg} 10605dfecf96Smrg 10615dfecf96SmrgLispObj * 10625dfecf96SmrgLisp_StringEqual(LispBuiltin *builtin) 10635dfecf96Smrg/* 10645dfecf96Smrg string-equal string1 string2 &key start1 end1 start2 end2 10655dfecf96Smrg */ 10665dfecf96Smrg{ 10675dfecf96Smrg return (LispStringCompare(builtin, CHAR_EQUAL, 1)); 10685dfecf96Smrg} 10695dfecf96Smrg 10705dfecf96SmrgLispObj * 10715dfecf96SmrgLisp_StringLessp(LispBuiltin *builtin) 10725dfecf96Smrg/* 10735dfecf96Smrg string-lessp string1 string2 &key start1 end1 start2 end2 10745dfecf96Smrg */ 10755dfecf96Smrg{ 10765dfecf96Smrg return (LispStringCompare(builtin, CHAR_LESS, 1)); 10775dfecf96Smrg} 10785dfecf96Smrg 10795dfecf96SmrgLispObj * 10805dfecf96SmrgLisp_StringGreaterp(LispBuiltin *builtin) 10815dfecf96Smrg/* 10825dfecf96Smrg string-greaterp string1 string2 &key start1 end1 start2 end2 10835dfecf96Smrg */ 10845dfecf96Smrg{ 10855dfecf96Smrg return (LispStringCompare(builtin, CHAR_GREATER, 1)); 10865dfecf96Smrg} 10875dfecf96Smrg 10885dfecf96SmrgLispObj * 10895dfecf96SmrgLisp_StringNotGreaterp(LispBuiltin *builtin) 10905dfecf96Smrg/* 10915dfecf96Smrg string-not-greaterp string1 string2 &key start1 end1 start2 end2 10925dfecf96Smrg */ 10935dfecf96Smrg{ 10945dfecf96Smrg return (LispStringCompare(builtin, CHAR_LESS_EQUAL, 1)); 10955dfecf96Smrg} 10965dfecf96Smrg 10975dfecf96SmrgLispObj * 10985dfecf96SmrgLisp_StringNotLessp(LispBuiltin *builtin) 10995dfecf96Smrg/* 11005dfecf96Smrg string-not-lessp string1 string2 &key start1 end1 start2 end2 11015dfecf96Smrg */ 11025dfecf96Smrg{ 11035dfecf96Smrg return (LispStringCompare(builtin, CHAR_GREATER_EQUAL, 1)); 11045dfecf96Smrg} 11055dfecf96Smrg 11065dfecf96SmrgLispObj * 11075dfecf96SmrgLisp_StringNotEqual(LispBuiltin *builtin) 11085dfecf96Smrg/* 11095dfecf96Smrg string-not-equal string1 string2 &key start1 end1 start2 end2 11105dfecf96Smrg */ 11115dfecf96Smrg{ 11125dfecf96Smrg return (LispStringCompare(builtin, CHAR_NOT_EQUAL, 1)); 11135dfecf96Smrg} 11145dfecf96Smrg 11155dfecf96SmrgLispObj * 11165dfecf96SmrgLispStringUpcase(LispBuiltin *builtin, int inplace) 11175dfecf96Smrg/* 11185dfecf96Smrg string-upcase string &key start end 11195dfecf96Smrg nstring-upcase string &key start end 11205dfecf96Smrg */ 11215dfecf96Smrg{ 11225dfecf96Smrg LispObj *result; 11235dfecf96Smrg char *string, *newstring; 11245dfecf96Smrg long start, end, length, offset; 11255dfecf96Smrg 11265dfecf96Smrg LispObj *ostring, *ostart, *oend; 11275dfecf96Smrg 11285dfecf96Smrg oend = ARGUMENT(2); 11295dfecf96Smrg ostart = ARGUMENT(1); 11305dfecf96Smrg ostring = ARGUMENT(0); 11315dfecf96Smrg CHECK_STRING(ostring); 11325dfecf96Smrg LispCheckSequenceStartEnd(builtin, ostring, ostart, oend, 11335dfecf96Smrg &start, &end, &offset); 11345dfecf96Smrg result = ostring; 11355dfecf96Smrg string = THESTR(ostring); 11365dfecf96Smrg length = STRLEN(ostring); 11375dfecf96Smrg 11385dfecf96Smrg /* first check if something need to be done */ 11395dfecf96Smrg for (offset = start; offset < end; offset++) 11405dfecf96Smrg if (string[offset] != toupper(string[offset])) 11415dfecf96Smrg break; 11425dfecf96Smrg 11435dfecf96Smrg if (offset >= end) 11445dfecf96Smrg return (result); 11455dfecf96Smrg 11465dfecf96Smrg if (inplace) { 11475dfecf96Smrg CHECK_STRING_WRITABLE(ostring); 11485dfecf96Smrg newstring = string; 11495dfecf96Smrg } 11505dfecf96Smrg else { 11515dfecf96Smrg /* upcase a copy of argument */ 11525dfecf96Smrg newstring = LispMalloc(length + 1); 11535dfecf96Smrg if (offset) 11545dfecf96Smrg memcpy(newstring, string, offset); 11555dfecf96Smrg if (length > end) 11565dfecf96Smrg memcpy(newstring + end, string + end, length - end); 11575dfecf96Smrg newstring[length] = '\0'; 11585dfecf96Smrg } 11595dfecf96Smrg 11605dfecf96Smrg for (; offset < end; offset++) 11615dfecf96Smrg newstring[offset] = toupper(string[offset]); 11625dfecf96Smrg 11635dfecf96Smrg if (!inplace) 11645dfecf96Smrg result = LSTRING2(newstring, length); 11655dfecf96Smrg 11665dfecf96Smrg return (result); 11675dfecf96Smrg} 11685dfecf96Smrg 11695dfecf96SmrgLispObj * 11705dfecf96SmrgLisp_StringUpcase(LispBuiltin *builtin) 11715dfecf96Smrg/* 11725dfecf96Smrg string-upcase string &key start end 11735dfecf96Smrg */ 11745dfecf96Smrg{ 11755dfecf96Smrg return (LispStringUpcase(builtin, 0)); 11765dfecf96Smrg} 11775dfecf96Smrg 11785dfecf96SmrgLispObj * 11795dfecf96SmrgLisp_NstringUpcase(LispBuiltin *builtin) 11805dfecf96Smrg/* 11815dfecf96Smrg nstring-upcase string &key start end 11825dfecf96Smrg */ 11835dfecf96Smrg{ 11845dfecf96Smrg return (LispStringUpcase(builtin, 1)); 11855dfecf96Smrg} 11865dfecf96Smrg 11875dfecf96SmrgLispObj * 11885dfecf96SmrgLispStringDowncase(LispBuiltin *builtin, int inplace) 11895dfecf96Smrg/* 11905dfecf96Smrg string-downcase string &key start end 11915dfecf96Smrg nstring-downcase string &key start end 11925dfecf96Smrg */ 11935dfecf96Smrg{ 11945dfecf96Smrg LispObj *result; 11955dfecf96Smrg char *string, *newstring; 11965dfecf96Smrg long start, end, length, offset; 11975dfecf96Smrg 11985dfecf96Smrg LispObj *ostring, *ostart, *oend; 11995dfecf96Smrg 12005dfecf96Smrg oend = ARGUMENT(2); 12015dfecf96Smrg ostart = ARGUMENT(1); 12025dfecf96Smrg ostring = ARGUMENT(0); 12035dfecf96Smrg CHECK_STRING(ostring); 12045dfecf96Smrg LispCheckSequenceStartEnd(builtin, ostring, ostart, oend, 12055dfecf96Smrg &start, &end, &offset); 12065dfecf96Smrg result = ostring; 12075dfecf96Smrg string = THESTR(ostring); 12085dfecf96Smrg length = STRLEN(ostring); 12095dfecf96Smrg 12105dfecf96Smrg /* first check if something need to be done */ 12115dfecf96Smrg for (offset = start; offset < end; offset++) 12125dfecf96Smrg if (string[offset] != tolower(string[offset])) 12135dfecf96Smrg break; 12145dfecf96Smrg 12155dfecf96Smrg if (offset >= end) 12165dfecf96Smrg return (result); 12175dfecf96Smrg 12185dfecf96Smrg if (inplace) { 12195dfecf96Smrg CHECK_STRING_WRITABLE(ostring); 12205dfecf96Smrg newstring = string; 12215dfecf96Smrg } 12225dfecf96Smrg else { 12235dfecf96Smrg /* downcase a copy of argument */ 12245dfecf96Smrg newstring = LispMalloc(length + 1); 12255dfecf96Smrg if (offset) 12265dfecf96Smrg memcpy(newstring, string, offset); 12275dfecf96Smrg if (length > end) 12285dfecf96Smrg memcpy(newstring + end, string + end, length - end); 12295dfecf96Smrg newstring[length] = '\0'; 12305dfecf96Smrg } 12315dfecf96Smrg for (; offset < end; offset++) 12325dfecf96Smrg newstring[offset] = tolower(string[offset]); 12335dfecf96Smrg 12345dfecf96Smrg if (!inplace) 12355dfecf96Smrg result = LSTRING2(newstring, length); 12365dfecf96Smrg 12375dfecf96Smrg return (result); 12385dfecf96Smrg} 12395dfecf96Smrg 12405dfecf96SmrgLispObj * 12415dfecf96SmrgLisp_StringDowncase(LispBuiltin *builtin) 12425dfecf96Smrg/* 12435dfecf96Smrg string-downcase string &key start end 12445dfecf96Smrg */ 12455dfecf96Smrg{ 12465dfecf96Smrg return (LispStringDowncase(builtin, 0)); 12475dfecf96Smrg} 12485dfecf96Smrg 12495dfecf96SmrgLispObj * 12505dfecf96SmrgLisp_NstringDowncase(LispBuiltin *builtin) 12515dfecf96Smrg/* 12525dfecf96Smrg nstring-downcase string &key start end 12535dfecf96Smrg */ 12545dfecf96Smrg{ 12555dfecf96Smrg return (LispStringDowncase(builtin, 1)); 12565dfecf96Smrg} 12575dfecf96Smrg 12585dfecf96SmrgLispObj * 12595dfecf96SmrgLispStringCapitalize(LispBuiltin *builtin, int inplace) 12605dfecf96Smrg/* 12615dfecf96Smrg string-capitalize string &key start end 12625dfecf96Smrg nstring-capitalize string &key start end 12635dfecf96Smrg */ 12645dfecf96Smrg{ 12655dfecf96Smrg LispObj *result; 12665dfecf96Smrg char *string, *newstring; 12675dfecf96Smrg long start, end, length, offset, upcase; 12685dfecf96Smrg 12695dfecf96Smrg LispObj *ostring, *ostart, *oend; 12705dfecf96Smrg 12715dfecf96Smrg oend = ARGUMENT(2); 12725dfecf96Smrg ostart = ARGUMENT(1); 12735dfecf96Smrg ostring = ARGUMENT(0); 12745dfecf96Smrg CHECK_STRING(ostring); 12755dfecf96Smrg LispCheckSequenceStartEnd(builtin, ostring, ostart, oend, 12765dfecf96Smrg &start, &end, &offset); 12775dfecf96Smrg result = ostring; 12785dfecf96Smrg string = THESTR(ostring); 12795dfecf96Smrg length = STRLEN(ostring); 12805dfecf96Smrg 12815dfecf96Smrg /* first check if something need to be done */ 12825dfecf96Smrg for (upcase = 1, offset = start; offset < end; offset++) { 12835dfecf96Smrg if (upcase) { 12845dfecf96Smrg if (!isalnum(string[offset])) 12855dfecf96Smrg continue; 12865dfecf96Smrg if (string[offset] != toupper(string[offset])) 12875dfecf96Smrg break; 12885dfecf96Smrg upcase = 0; 12895dfecf96Smrg } 12905dfecf96Smrg else { 12915dfecf96Smrg if (isalnum(string[offset])) { 12925dfecf96Smrg if (string[offset] != tolower(string[offset])) 12935dfecf96Smrg break; 12945dfecf96Smrg } 12955dfecf96Smrg else 12965dfecf96Smrg upcase = 1; 12975dfecf96Smrg } 12985dfecf96Smrg } 12995dfecf96Smrg 13005dfecf96Smrg if (offset >= end) 13015dfecf96Smrg return (result); 13025dfecf96Smrg 13035dfecf96Smrg if (inplace) { 13045dfecf96Smrg CHECK_STRING_WRITABLE(ostring); 13055dfecf96Smrg newstring = string; 13065dfecf96Smrg } 13075dfecf96Smrg else { 13085dfecf96Smrg /* capitalize a copy of argument */ 13095dfecf96Smrg newstring = LispMalloc(length + 1); 13105dfecf96Smrg memcpy(newstring, string, length); 13115dfecf96Smrg newstring[length] = '\0'; 13125dfecf96Smrg } 13135dfecf96Smrg for (; offset < end; offset++) { 13145dfecf96Smrg if (upcase) { 13155dfecf96Smrg if (!isalnum(string[offset])) 13165dfecf96Smrg continue; 13175dfecf96Smrg newstring[offset] = toupper(string[offset]); 13185dfecf96Smrg upcase = 0; 13195dfecf96Smrg } 13205dfecf96Smrg else { 13215dfecf96Smrg if (isalnum(newstring[offset])) 13225dfecf96Smrg newstring[offset] = tolower(string[offset]); 13235dfecf96Smrg else 13245dfecf96Smrg upcase = 1; 13255dfecf96Smrg } 13265dfecf96Smrg } 13275dfecf96Smrg 13285dfecf96Smrg if (!inplace) 13295dfecf96Smrg result = LSTRING2(newstring, length); 13305dfecf96Smrg 13315dfecf96Smrg return (result); 13325dfecf96Smrg} 13335dfecf96Smrg 13345dfecf96SmrgLispObj * 13355dfecf96SmrgLisp_StringCapitalize(LispBuiltin *builtin) 13365dfecf96Smrg/* 13375dfecf96Smrg string-capitalize string &key start end 13385dfecf96Smrg */ 13395dfecf96Smrg{ 13405dfecf96Smrg return (LispStringCapitalize(builtin, 0)); 13415dfecf96Smrg} 13425dfecf96Smrg 13435dfecf96SmrgLispObj * 13445dfecf96SmrgLisp_NstringCapitalize(LispBuiltin *builtin) 13455dfecf96Smrg/* 13465dfecf96Smrg nstring-capitalize string &key start end 13475dfecf96Smrg */ 13485dfecf96Smrg{ 13495dfecf96Smrg return (LispStringCapitalize(builtin, 1)); 13505dfecf96Smrg} 13515dfecf96Smrg 13525dfecf96SmrgLispObj * 13535dfecf96SmrgLisp_StringConcat(LispBuiltin *builtin) 13545dfecf96Smrg/* 13555dfecf96Smrg string-concat &rest strings 13565dfecf96Smrg */ 13575dfecf96Smrg{ 13585dfecf96Smrg char *buffer; 13595dfecf96Smrg long size, length; 13605dfecf96Smrg LispObj *object, *string; 13615dfecf96Smrg 13625dfecf96Smrg LispObj *strings; 13635dfecf96Smrg 13645dfecf96Smrg strings = ARGUMENT(0); 13655dfecf96Smrg 13665dfecf96Smrg if (strings == NIL) 13675dfecf96Smrg return (STRING("")); 13685dfecf96Smrg 13695dfecf96Smrg for (length = 1, object = strings; CONSP(object); object = CDR(object)) { 13705dfecf96Smrg string = CAR(object); 13715dfecf96Smrg CHECK_STRING(string); 13725dfecf96Smrg length += STRLEN(string); 13735dfecf96Smrg } 13745dfecf96Smrg 13755dfecf96Smrg buffer = LispMalloc(length); 13765dfecf96Smrg 13775dfecf96Smrg for (length = 0, object = strings; CONSP(object); object = CDR(object)) { 13785dfecf96Smrg string = CAR(object); 13795dfecf96Smrg size = STRLEN(string); 13805dfecf96Smrg memcpy(buffer + length, THESTR(string), size); 13815dfecf96Smrg length += size; 13825dfecf96Smrg } 13835dfecf96Smrg buffer[length] = '\0'; 13845dfecf96Smrg object = LSTRING2(buffer, length); 13855dfecf96Smrg 13865dfecf96Smrg return (object); 13875dfecf96Smrg} 1388