revert between 56095 -> 55830 in arch
[AROS.git] / workbench / c / shellcommands / Cut.c
blob28e51ec10577b82dcc59dc6c8b4ce34809345491
1 /*
2 Copyright © 2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: English
7 */
9 /******************************************************************************
11 NAME
13 Cut
15 TEMPLATE
17 STRING/A,C=CHAR/K,W=WORD/K,S=SEPARATOR/K
19 LOCATION
21 SYS:C
23 FUNCTION
25 Extracts some characters or words from a string.
27 FORMAT
29 CUT <string> [CHAR <range> | WORD <range> [SEPARATOR <string>] ]
31 RESULT
33 Standard DOS return codes.
35 NOTES
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
51 the original string.
53 EXAMPLES
55 Example 1:
56 > Cut "A dummy sentence" CHAR 7
58 extract one character.
60 Example 2:
61 > Cut "A dummy sentence" CHAR 6-12
62 my sent
63 extract from character 6 to 12.
65 Example 3:
66 > Cut "A dummy sentence" CHAR -7
67 A dummy
68 extract from character 1 to 7 without specifying the beginning position.
70 Example 4:
71 > Cut "A dummy sentence" CHAR 12-
72 tence
73 extract from character 12 of the string until the end.
75 Example 5:
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>
86 //#define DEBUG 1
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))
94 struct Bounds
96 LONG Start;
97 LONG End;
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"
112 "my sent\n") )
114 AROS_SHCOMMAND_INIT
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));
127 if (SHArg(WORD))
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;
137 wordCnt--;
141 if (0 == wordCnt)
143 if (wordBounds->End)
144 wordCnt = wordBounds->End - (wordBounds->Start ? wordBounds->Start : 1) + 1;
145 else
146 /* Make sure to reach the end of the string in any case */
147 wordCnt = strlen((char *)stringBuf);
149 while (*stringBuf)
151 sepBuf = (STRPTR)strstr((char *)stringBuf, (char *)SHArg(SEPARATOR));
152 if (sepBuf && (sepBuf == stringBuf))
153 wordCnt--;
155 if (0 < wordCnt)
156 FPutC(Output(), *stringBuf++);
157 else
158 break;
162 FreeVec(wordBounds);
163 rc = RETURN_OK;
167 if (SHArg(CHAR))
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++);
179 FreeVec(charBounds);
180 rc = RETURN_OK;
184 if (rc == RETURN_OK)
185 FPutC(Output(), '\n');
186 else
188 ioerr = IoErr();
189 PrintFault(ioerr, (CONST_STRPTR)"Cut");
190 if (ioerr == ERROR_BAD_TEMPLATE)
191 rc = RETURN_ERROR;
194 return rc;
196 AROS_SHCOMMAND_EXIT
200 static struct Bounds *getBoundaries(STRPTR String, APTR DOSBase, struct ExecBase *SysBase)
202 CONST_STRPTR buffer;
203 struct Bounds *bounds;
205 if ((buffer = String) == NULL)
207 SetIoErr(ERROR_BAD_TEMPLATE);
208 return NULL;
211 D(bug("[Cut] getBoundaries() buffer = '%s'\n", buffer));
213 if ((bounds = AllocVec(sizeof(struct Bounds), MEMF_ANY | MEMF_CLEAR)) != NULL)
215 if (*buffer != '-')
217 buffer += StrToLong(buffer, &bounds->Start);
220 /* It is mandatory that boundaries are separated by '-'! */
221 if ((*buffer) && (*buffer++ == '-'))
223 if (*buffer)
225 StrToLong(buffer, &bounds->End);
228 else
229 bounds->End = bounds->Start;
231 D(bug("[Cut] getBoundaries() bounds->Start = %ld, bounds->End = %ld\n",
232 bounds->Start, bounds->End));
235 return bounds;