Detabbed
[AROS.git] / rom / dos / readitem.c
blob248fab94c8862ec6297585d311095d1470283d55
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
8 #include <proto/exec.h>
9 #include <dos/rdargs.h>
10 #include <dos/dosasl.h>
11 #include <dos/dosextens.h>
12 #include "dos_intern.h"
14 /*****************************************************************************
16 NAME */
17 #include <proto/dos.h>
19 AROS_LH3(LONG, ReadItem,
21 /* SYNOPSIS */
22 AROS_LHA(STRPTR, buffer, D1),
23 AROS_LHA(LONG, maxchars, D2),
24 AROS_LHA(struct CSource *, input, D3),
26 /* LOCATION */
27 struct DosLibrary *, DOSBase, 135, Dos)
29 /* FUNCTION
30 Read an item from a given character source. Items are words
31 or quoted strings separated by whitespace or '=' just like on
32 the commandline. The separator is unread and the output string
33 is terminated by a NUL character.
35 INPUTS
36 buffer - Buffer to be filled.
37 maxchars - Size of the buffer. Must be at least 1 (for the NUL
38 terminator).
39 input - A ready to use CSource structure or NULL which means
40 "read from the input stream".
42 RESULT
43 One of ITEM_UNQUOTED - Normal word read.
44 ITEM_QUOTED - Quoted string read.
45 ITEM_NOTHING - End of line found. Nothing read.
46 ITEM_EQUAL - '=' read. Buffer is empty.
47 ITEM_ERROR - An error happened. IoErr() gives additional
48 information in that case.
50 NOTES
51 This function handles conversion of '**', '*"', etc inside quotes.
53 This function has well known bugs, and should be avoided
54 in new applications.
56 EXAMPLE
58 BUGS
59 1. Forgets to unread a separator character (equal sign, whitespace or
60 tabulation).
61 2. Tries to unread an end-of-line, which actually causes unreading the
62 last read character of CSource is supplied. Even if it's not a separator,
63 but belongs to last read item.
64 3. IoErr() is never modified by this function.
66 As AOS programs that use ReadItem() depend on this broken behaviour,
67 it will not be fixed.
69 4. If maxchars == 0, buff[0] is set to 0 anyway.
71 SEE ALSO
73 INTERNALS
75 *****************************************************************************/
77 AROS_LIBFUNC_INIT
80 * WARNING!!!
81 * As mentioned above, this code has some intentional (but not obvious) bugs.
82 * They must not be fixed.
83 * If you change something here, be sure that the code passes unit tests
84 * in test/dos/readitem. Those unit tests are verified to pass on AmigaOS 3.1.
87 /* Macro to get a character from the input source */
88 #define GET(c) \
89 if(input!=NULL) \
90 { \
91 if(input->CS_CurChr>=input->CS_Length) \
92 c=EOF; \
93 else \
94 c=input->CS_Buffer[input->CS_CurChr++]; \
95 }else \
96 { \
97 c=FGetC(Input()); \
100 /* Macro to push the character back */
101 #define UNGET() {if(input!=NULL) input->CS_CurChr--; else UnGetC(Input(),-1);}
103 STRPTR b=buffer;
104 LONG c;
106 /* No buffer? */
107 if (buffer == NULL)
108 return ITEM_NOTHING;
110 if (!maxchars) {
111 *b = 0;
112 return ITEM_NOTHING;
115 /* Skip leading whitespace characters */
118 GET(c);
119 } while (c==' '||c=='\t');
121 if(!c||c=='\n'||c==EOF||c==';')
123 *b=0;
124 if (c != EOF)
125 UNGET();
126 return ITEM_NOTHING;
127 }else if(c=='=')
129 /* Found '='. Return it. */
130 *b=0;
131 return ITEM_EQUAL;
132 }else if(c=='\"')
133 /* Quoted item found. Convert Contents. */
134 for(;;)
136 if(!maxchars)
138 b[-1]=0;
139 return ITEM_NOTHING;
141 maxchars--;
142 GET(c);
143 /* Convert ** to *, *" to ", *n to \n and *e to 0x1b. */
144 if(c=='*')
146 GET(c);
147 /* Check for premature end of line. */
148 if(!c||c=='\n'||c==EOF)
150 UNGET();
151 *b=0;
152 return ITEM_ERROR;
153 }else if(c=='n'||c=='N')
154 c='\n';
155 else if(c=='e'||c=='E')
156 c=0x1b;
157 }else if(!c||c=='\n'||c==EOF)
159 UNGET();
160 *b=0;
161 return ITEM_ERROR;
162 }else if(c=='\"')
164 /* " ends the item. */
165 *b=0;
166 return ITEM_QUOTED;
168 *b++=c;
170 else
172 /* Unquoted item. Store first character. */
173 if(!maxchars)
175 b[-1]=0;
176 return ITEM_ERROR;
178 maxchars--;
179 *b++=c;
180 /* Read up to the next terminator. */
181 for(;;)
183 if(!maxchars)
185 b[-1]=0;
186 return ITEM_ERROR;
188 maxchars--;
189 GET(c);
190 /* Check for terminator */
191 if(!c||c==' '||c=='\t'||c=='\n'||c=='='||c==EOF)
193 /* To be compatible with AOS, we need
194 * to *not* UNGET() here if we see a space
195 * or equals sign.
197 * Yes, it's broken, but so are any programs
198 * that actually used ReadItem(), and relied
199 * on this behaviour.
201 if (c != '=' && c != ' ' && c != '\t')
202 UNGET();
203 *b=0;
204 return ITEM_UNQUOTED;
206 *b++=c;
209 AROS_LIBFUNC_EXIT
210 } /* ReadItem */