try to make sure compiler/include/mmakefile is always refreshed correctly.
[AROS.git] / rom / dos / readitem.c
blobf599aa19fa4e48af582147ca90006d5b1d4386c5
1 /*
2 Copyright © 1995-2014, 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.
49 NOTES
50 This function handles conversion of '**', '*"', etc. inside quotes.
52 This function has well known bugs, and should be avoided
53 in new applications.
55 EXAMPLE
57 BUGS
58 1. Forgets to unread a separator character (equal sign, whitespace or
59 tabulation).
60 2. Tries to unread an end-of-line, which actually causes unreading the
61 last read character of CSource if supplied. Even if it's not a
62 separator, but belongs to the last read item.
63 3. IoErr() is never modified by this function.
65 As AOS programs that use ReadItem() depend on this broken behaviour,
66 it will not be fixed.
68 4. If maxchars == 0, buffer[0] is set to NUL anyway.
70 SEE ALSO
72 INTERNALS
74 *****************************************************************************/
76 AROS_LIBFUNC_INIT
79 * WARNING!!!
80 * As mentioned above, this code has some intentional (but not obvious) bugs.
81 * They must not be fixed.
82 * If you change something here, be sure that the code passes unit tests
83 * in test/dos/readitem. Those unit tests are verified to pass on AmigaOS 3.1.
86 /* Macro to get a character from the input source */
87 #define GET(c) \
88 if(input!=NULL) \
89 { \
90 if(input->CS_CurChr>=input->CS_Length) \
91 c=EOF; \
92 else \
93 c=input->CS_Buffer[input->CS_CurChr++]; \
94 }else \
95 { \
96 c=FGetC(Input()); \
99 /* Macro to push the character back */
100 #define UNGET() {if(input!=NULL) input->CS_CurChr--; else UnGetC(Input(),-1);}
102 STRPTR b=buffer;
103 LONG c;
105 /* No buffer? */
106 if (buffer == NULL)
107 return ITEM_NOTHING;
109 if (!maxchars) {
110 *b = 0;
111 return ITEM_NOTHING;
114 /* Skip leading whitespace characters */
117 GET(c);
118 } while (c==' '||c=='\t');
120 if(!c||c=='\n'||c==EOF||c==';')
122 *b=0;
123 if (c != EOF)
124 UNGET();
125 return ITEM_NOTHING;
126 }else if(c=='=')
128 /* Found '='. Return it. */
129 *b=0;
130 return ITEM_EQUAL;
131 }else if(c=='\"')
132 /* Quoted item found. Convert Contents. */
133 for(;;)
135 if(!maxchars)
137 b[-1]=0;
138 return ITEM_NOTHING;
140 maxchars--;
141 GET(c);
142 /* Convert ** to *, *" to ", *n to \n and *e to 0x1b. */
143 if(c=='*')
145 GET(c);
146 /* Check for premature end of line. */
147 if(!c||c=='\n'||c==EOF)
149 UNGET();
150 *b=0;
151 return ITEM_ERROR;
152 }else if(c=='n'||c=='N')
153 c='\n';
154 else if(c=='e'||c=='E')
155 c=0x1b;
156 }else if(!c||c=='\n'||c==EOF)
158 UNGET();
159 *b=0;
160 return ITEM_ERROR;
161 }else if(c=='\"')
163 /* " ends the item. */
164 *b=0;
165 return ITEM_QUOTED;
167 *b++=c;
169 else
171 /* Unquoted item. Store first character. */
172 if(!maxchars)
174 b[-1]=0;
175 return ITEM_ERROR;
177 maxchars--;
178 *b++=c;
179 /* Read up to the next terminator. */
180 for(;;)
182 if(!maxchars)
184 b[-1]=0;
185 return ITEM_ERROR;
187 maxchars--;
188 GET(c);
189 /* Check for terminator */
190 if(!c||c==' '||c=='\t'||c=='\n'||c=='='||c==EOF)
192 /* To be compatible with AOS, we need
193 * to *not* UNGET() here if we see a space
194 * or equals sign.
196 * Yes, it's broken, but so are any programs
197 * that actually used ReadItem(), and relied
198 * on this behaviour.
200 if (c != '=' && c != ' ' && c != '\t')
201 UNGET();
202 *b=0;
203 return ITEM_UNQUOTED;
205 *b++=c;
208 AROS_LIBFUNC_EXIT
209 } /* ReadItem */