OSDN Git Service

[ 2822900 ] more characters in each lines. (MURANAKA Masaki)
[pf3gnuchains/urjtag.git] / urjtag / src / global / parse.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2002, 2003 ETC s.r.o.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19  * 02111-1307, USA.
20  *
21  * Written by Marcel Telka <marcel@telka.sk>, 2002, 2003.
22  * Modified by Ajith Kumar P.C <ajithpc@kila.com>, 20/09/2006.
23  * Modified by Ville Voipio <vv@iki.fi>, 7-May-2008
24  *
25  */
26
27 #include <sysdep.h>
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <errno.h>
34
35 #include <urjtag/log.h>
36 #include <urjtag/error.h>
37 #include <urjtag/chain.h>
38 #include <urjtag/parse.h>
39 #include <urjtag/cmd.h>
40 #include <urjtag/jtag.h>
41 #include <urjtag/bsdl.h>
42
43 #define MAXINPUTLINE 300        /* Maximum input line length */
44
45
46
47 int
48 urj_parse_line (urj_chain_t *chain, char *line)
49 {
50     int l, i, r, tcnt;
51     char **a;
52     char *c, *d;
53     char *sline;
54
55     if (line == NULL)
56     {
57         urj_error_set (URJ_ERROR_INVALID, "NULL line");
58         return URJ_STATUS_FAIL;
59     }
60     l = strlen (line);
61     if (l == 0)
62         return URJ_STATUS_OK;
63
64     /* allocate as many chars as in the input line; this will be enough in all cases */
65     sline = malloc (l + 1);
66     if (sline == NULL)
67     {
68         urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zd) fails",
69                        (size_t) (l + 1));
70         return URJ_STATUS_FAIL;
71     }
72
73     /* count and copy the tokens */
74     c = line;
75     d = sline;
76     tcnt = 0;
77     while (1)
78     {
79         /* eat up leading spaces */
80         while (isspace (*c))
81             c++;
82
83         /* if the command ends here (either by NUL or comment) */
84         if (*c == '\0' || *c == '#')
85             break;
86
87         /* copy the meat (non-space, non-NUL) */
88         while (!isspace (*c) && *c != '\0')
89         {
90             *d++ = *c++;
91         }
92         /* mark the end to the destination string */
93         *d++ = '\0';
94         tcnt++;
95     }
96
97     if (tcnt == 0)
98     {
99         free (sline);
100         return URJ_STATUS_OK;
101     }
102
103     /* allocate the token pointer table */
104     a = malloc ((tcnt + 1) * sizeof (char *));
105     if (a == NULL)
106     {
107         urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zd) fails",
108                        (size_t) ((tcnt + 1) * sizeof (char *)));
109         return URJ_STATUS_FAIL;
110     }
111
112     /* find the starting points for the tokens */
113     d = sline;
114     for (i = 0; i < tcnt; i++)
115     {
116         a[i] = d;
117         while (*d++ != '\0')
118             ;
119     }
120     a[tcnt] = NULL;
121
122     r = urj_cmd_run (chain, a);
123     urj_log (URJ_LOG_LEVEL_DEBUG, "Return in urj_parse_line r=%d\n", r);
124     free (a);
125     free (sline);
126
127     return r;
128 }
129
130
131 int
132 urj_parse_stream (urj_log_level_t ll, urj_chain_t *chain, FILE *f)
133 {
134     char inputline[MAXINPUTLINE + 1];
135     int go = 1, i, c, lnr, clip, found_comment;
136
137     /* read the stream line-by-line until EOF or "quit" */
138     lnr = 0;
139     do
140     {
141         i = 0;
142         clip = 0;
143         found_comment = 0;
144
145         /* read stream until '\n' or EOF, copy at most MAXINPUTLINE-1 chars */
146         while (1)
147         {
148             c = fgetc (f);
149             if (c == EOF || c == '\n')
150                 break;
151             if (c == '#')
152                 found_comment = 1;
153             if (i < sizeof (inputline) - 1)
154                 inputline[i++] = c;
155             else
156                 clip = 1;
157         }
158         inputline[i] = '\0';
159         lnr++;
160         if (clip && !found_comment)
161             urj_warning ("line %d exceeds %zd characters, clipped\n", lnr,
162                          sizeof (inputline) - 1);
163         go = urj_parse_line (chain, inputline);
164         if (go == URJ_STATUS_FAIL)
165         {
166             urj_log (ll, "Error: %s; command '%s'\n", urj_error_describe(), inputline);
167             urj_error_reset ();
168         }
169         urj_tap_chain_flush (chain);
170     }
171     while (go != URJ_STATUS_MUST_QUIT && c != EOF);
172
173     return go;
174 }
175
176 int
177 urj_parse_file (urj_log_level_t ll, urj_chain_t *chain, const char *filename)
178 {
179     FILE *f;
180     int go;
181
182     f = fopen (filename, "r");
183     if (!f)
184     {
185         urj_error_IO_set ("Cannot open file '%s' to parse", filename);
186         return URJ_STATUS_FAIL;
187     }
188
189     go = urj_parse_stream (ll, chain, f);
190
191     fclose (f);
192     urj_log (URJ_LOG_LEVEL_DEBUG, "File Closed go=%d\n", go);
193
194     return go;
195 }
196
197 int
198 urj_parse_include (urj_chain_t *chain, const char *filename, int ignore_path)
199 {
200     char *path = NULL;
201     int r = URJ_STATUS_OK;
202
203     if (! ignore_path)
204     {
205         /* If "filename" begins with a slash, or dots followed by a slash,
206          * assume that user wants to ignore the search path after all */
207         const char *slashdots = filename;
208
209 #ifdef __MINGW32__
210         if (isalpha (*slashdots) && slashdots[1] == ':')
211             slashdots += 2;
212 #endif
213         while (*slashdots == '.')
214             slashdots++;
215         ignore_path = (*slashdots == '/' || *slashdots == '\\');
216     }
217
218     if (! ignore_path)
219     {
220         const char *jtag_data_dir = urj_get_data_dir ();
221         size_t len;
222
223         path = malloc (len = strlen (jtag_data_dir) + strlen (filename) + 2);
224         if (path == NULL)
225         {
226             urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zd) fails", len);
227             return URJ_STATUS_FAIL;
228         }
229         snprintf (path, len, "%s/%s", jtag_data_dir, filename);
230
231         filename = path;
232     }
233
234 #ifdef ENABLE_BSDL
235     /* perform a test read to check for BSDL syntax */
236     if (urj_bsdl_read_file (chain, filename, URJ_BSDL_MODE_INCLUDE1, NULL) >= 0)
237     {
238         // @@@@ RFHH ToDo: let urj_bsdl_read_file also return URJ_STATUS_...
239         /* it seems to be a proper BSDL file, so re-read and execute */
240         if (urj_bsdl_read_file (chain, filename, URJ_BSDL_MODE_INCLUDE2,
241                                 NULL) < 0)
242             // retain errno
243             r = URJ_STATUS_FAIL;
244     }
245     else
246 #endif
247     {
248         r = urj_parse_file (URJ_LOG_LEVEL_NORMAL, chain, filename);
249     }
250
251     free (path);
252
253     return r;
254 }
255