- fix bug when using full paths to config files. Thanks Ted Roth
[fw/openocd] / src / helper / configuration.c
1 /***************************************************************************
2  *   Copyright (C) 2004, 2005 by Dominic Rath                              *
3  *   Dominic.Rath@gmx.de                                                   *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "types.h"
25 #include "command.h"
26 #include "configuration.h"
27 #include "log.h"
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <getopt.h>
32 #include <string.h>
33
34 static size_t num_config_files;
35 static char** config_file_names;
36
37 static size_t num_script_dirs;
38 static char** script_search_dirs;
39
40 static int help_flag;
41
42 static struct option long_options[] =
43 {
44         {"help",                        no_argument,    &help_flag, 1},
45
46         {"debug",                       optional_argument,      0, 'd'},
47         {"file",                        required_argument,      0, 'f'},
48         {"search",                      required_argument,      0, 's'},
49         {"log_output",          required_argument,      0, 'l'},
50         
51         {0, 0, 0, 0}
52 };
53
54 int configuration_output_handler(struct command_context_s *context, char* line)
55 {
56         INFO(line);
57         
58         return ERROR_OK;
59 }
60
61 void add_script_search_dir (const char *dir)
62 {
63         num_script_dirs++;
64         script_search_dirs = (char **)realloc(script_search_dirs, (num_script_dirs+1) * sizeof (char *));
65
66         script_search_dirs[num_script_dirs-1] = strdup(dir);
67         script_search_dirs[num_script_dirs] = NULL;
68 }
69
70 void add_config_file_name (const char *cfg)
71 {
72         num_config_files++;
73         config_file_names = (char **)realloc(config_file_names, (num_config_files+1) * sizeof (char *));
74
75         config_file_names[num_config_files-1] = strdup(cfg);
76         config_file_names[num_config_files] = NULL;
77 }
78
79 int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[])
80 {
81         int c;
82         char command_buffer[128];
83
84         while (1)
85         {       
86                 /* getopt_long stores the option index here. */
87                 int option_index = 0;
88                 
89                 c = getopt_long(argc, argv, "hd::l:f:s:", long_options, &option_index);
90                 
91                 /* Detect the end of the options. */
92                 if (c == -1)
93                         break;
94                 
95                 switch (c)
96                 {
97                         case 0:
98                                 break;
99                         case 'h':       /* --help | -h */
100                                 help_flag = 1;
101                                 break;
102                         case 'f':       /* --file | -f */
103                                 add_config_file_name(optarg);
104                                 break;
105                         case 's':       /* --search | -s */
106                                 add_script_search_dir(optarg);
107                                 break;
108                         case 'd':       /* --debug | -d */
109                                 if (optarg)
110                                         snprintf(command_buffer, 128, "debug_level %s", optarg);
111                                 else
112                                         snprintf(command_buffer, 128, "debug_level 3");
113                                 command_run_line(cmd_ctx, command_buffer);
114                                 break;
115                         case 'l':       /* --log_output | -l */
116                                 if (optarg)
117                                 {
118                                         snprintf(command_buffer, 128, "log_output %s", optarg);
119                                         command_run_line(cmd_ctx, command_buffer);
120                                 }       
121                                 break;
122                 }
123         }
124
125         if (help_flag)
126         {
127                 printf("Open On-Chip Debugger\n(c) 2005 by Dominic Rath\n\n");
128                 printf("--help       | -h\tdisplay this help\n");
129                 printf("--file       | -f\tuse configuration file <name>\n");
130                 printf("--search     | -s\tdir to search for config files and scripts.\n");
131                 printf("--debug      | -d\tset debug level <0-3>\n");
132                 printf("--log_output | -l\tredirect log output to file <name>\n");
133                 exit(-1);
134         }       
135
136         /* Add dir for openocd supplied scripts last so that user can over
137            ride those scripts if desired. */
138         add_script_search_dir(PKGDATADIR);
139
140         return ERROR_OK;
141 }
142
143 FILE *open_file_from_path (command_context_t *cmd_ctx, char *file, char *mode)
144 {
145         FILE *fp = NULL;
146         char **search_dirs = script_search_dirs;
147         char *dir;
148         char full_path[1024];
149
150         /* Check absolute and relative to current working dir first.
151          * This keeps full_path reporting belowing working. */
152         snprintf(full_path, 1024, "%s", file);
153         fp = fopen(full_path, mode);
154
155         while (!fp)
156         {
157                 dir = *search_dirs++;
158
159                 if (!dir)
160                         break;
161
162                 snprintf(full_path, 1024, "%s/%s", dir, file);
163                 fp = fopen(full_path, mode);
164         }
165
166         if (fp)
167                 command_print(cmd_ctx, "opened %s", full_path);
168
169         return fp;
170 }
171
172 int parse_config_file(struct command_context_s *cmd_ctx)
173 {
174         char **cfg;
175         FILE *config_file;
176
177         if (!config_file_names)
178                 add_config_file_name ("openocd.cfg");
179
180         cfg = config_file_names;
181
182         while (*cfg)
183         {
184                 config_file = open_file_from_path(cmd_ctx, *cfg, "r");
185                 if (!config_file)
186                 {
187                         ERROR("couldn't open config file");
188                         return ERROR_NO_CONFIG_FILE;
189                 }
190
191                 command_run_file(cmd_ctx, config_file, COMMAND_CONFIG);
192
193                 fclose(config_file);
194
195                 cfg++;
196         }
197
198         return ERROR_OK;
199 }