2 Copyright © 2011, The AROS Development Team. All rights reserved.
9 /******************************************************************************
17 STRING/A,C=CHAR/K,W=WORD/K,S=SEPARATOR/K
25 Extracts some characters or words from a string.
29 CUT <string> [CHAR <range> | WORD <range> [SEPARATOR <string>] ]
33 Standard DOS return codes.
37 Both CHAR (character) and WORD arguments allow to define a begin and an end
38 position in the original string. Words are strings separated by a SEPARATOR (a
39 space character (" ") is the default), which can also be a string.
41 Positions range is specified using numbers with the form "P1-P2", where "P1"
42 is the position of the first character (resp. word) to extract in the original
43 string, "-" is the hyphen-minus character, and "P2" is the position of the last
44 character (resp. word) to extract.
46 If only one position is supplied, then only one character (resp. word) is
47 extracted, unless the hyphen-minus character is supplied too: P- extracts a
48 string begining at the character (resp. word) at position P in the original
49 string until the end, and -P extracts a string starting at the beginning of the
50 original string, and ending with the character (resp. word) at position P in
56 > Cut "A dummy sentence" CHAR 7
58 extract one character.
61 > Cut "A dummy sentence" CHAR 6-12
63 extract from character 6 to 12.
66 > Cut "A dummy sentence" CHAR -7
68 extract from character 1 to 7 without specifying the beginning position.
71 > Cut "A dummy sentence" CHAR 12-
73 extract from character 12 of the string until the end.
76 > Cut "A dummy sentence" WORD 2 SEPARATOR "en"
78 extract the second word (using an user-defined separator).
81 ******************************************************************************/
83 #include <proto/exec.h>
84 #include <proto/dos.h>
87 #include <aros/debug.h>
89 #include <aros/shcommands.h>
91 #define min(x,y) (((x) < (y)) ? (x) : (y))
92 #define max(x,y) (((x) > (y)) ? (x) : (y))
101 static struct Bounds
*getBoundaries(STRPTR String
, APTR DOSBase
, struct ExecBase
*SysBase
);
103 AROS_SH4H(Cut
,50.1, "extract some characters or words from a string\n",
104 AROS_SHAH(STRPTR
, ,STRING
,/A
,NULL
,"Quoted string from which to extract CHARacters or WORDs"),
105 AROS_SHAH(STRPTR
,C
=,CHAR
,/K
,NULL
,"Extract one or a range of characters, form is P1-P2"),
106 AROS_SHAH(STRPTR
,W
=,WORD
,/K
,NULL
,"Extract one or a range of words separated by SEPARATOR"),
107 AROS_SHAH(STRPTR
,S
=,SEPARATOR
,/K
," " ,"Specify a string of any length to be used to split\n"
108 "\t\tthe original STRING in WORDs (default: space character)"
110 "\n\nExample: extract from character 6 to 12:\n"
111 "> Cut \"A dummy sentence\" CHAR 6-12\n"
116 int rc
= RETURN_FAIL
;
117 LONG ioerr
, stringLen
, sepLen
, wordCnt
= 0;
118 struct Bounds
*charBounds
, *wordBounds
;
119 STRPTR stringBuf
= SHArg(STRING
), sepBuf
;
121 if (!SHArg(CHAR
) && !SHArg(WORD
))
122 SetIoErr(ERROR_BAD_TEMPLATE
);
124 stringLen
= strlen((char *)SHArg(STRING
));
125 sepLen
= strlen((char *)SHArg(SEPARATOR
));
129 if ((wordBounds
= getBoundaries(SHArg(WORD
), DOSBase
, SysBase
)) != NULL
)
131 if (0 != wordBounds
->Start
)
133 wordCnt
= wordBounds
->Start
- 1;
134 while (wordCnt
&& (sepBuf
= (STRPTR
)strstr((char *)stringBuf
, (char *)SHArg(SEPARATOR
))))
136 stringBuf
= sepBuf
+ sepLen
;
144 wordCnt
= wordBounds
->End
- (wordBounds
->Start
? wordBounds
->Start
: 1) + 1;
146 /* Make sure to reach the end of the string in any case */
147 wordCnt
= strlen((char *)stringBuf
);
151 sepBuf
= (STRPTR
)strstr((char *)stringBuf
, (char *)SHArg(SEPARATOR
));
152 if (sepBuf
&& (sepBuf
== stringBuf
))
156 FPutC(Output(), *stringBuf
++);
169 if ((charBounds
= getBoundaries(SHArg(CHAR
), DOSBase
, SysBase
)) != NULL
)
171 if (0 != charBounds
->Start
)
172 stringBuf
+= charBounds
->Start
- 1;
174 while((stringBuf
- SHArg(STRING
)) < ((0 != charBounds
->End
) ? min(stringLen
, charBounds
->End
) : stringLen
))
176 FPutC(Output(), *stringBuf
++);
185 FPutC(Output(), '\n');
189 PrintFault(ioerr
, (CONST_STRPTR
)"Cut");
190 if (ioerr
== ERROR_BAD_TEMPLATE
)
200 static struct Bounds
*getBoundaries(STRPTR String
, APTR DOSBase
, struct ExecBase
*SysBase
)
203 struct Bounds
*bounds
;
205 if ((buffer
= String
) == NULL
)
207 SetIoErr(ERROR_BAD_TEMPLATE
);
211 D(bug("[Cut] getBoundaries() buffer = '%s'\n", buffer
));
213 if ((bounds
= AllocVec(sizeof(struct Bounds
), MEMF_ANY
| MEMF_CLEAR
)) != NULL
)
217 buffer
+= StrToLong(buffer
, &bounds
->Start
);
220 /* It is mandatory that boundaries are separated by '-'! */
221 if ((*buffer
) && (*buffer
++ == '-'))
225 StrToLong(buffer
, &bounds
->End
);
229 bounds
->End
= bounds
->Start
;
231 D(bug("[Cut] getBoundaries() bounds->Start = %ld, bounds->End = %ld\n",
232 bounds
->Start
, bounds
->End
));