Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec...
[safe/jmp/linux-2.6] / arch / powerpc / boot / dtc-src / srcpos.c
1 /*
2  * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
17  *                                                                   USA
18  */
19
20 #include "dtc.h"
21 #include "srcpos.h"
22
23 /*
24  * Like yylineno, this is the current open file pos.
25  */
26
27 struct dtc_file *srcpos_file;
28
29 static int dtc_open_one(struct dtc_file *file,
30                         const char *search,
31                         const char *fname)
32 {
33         char *fullname;
34
35         if (search) {
36                 fullname = xmalloc(strlen(search) + strlen(fname) + 2);
37
38                 strcpy(fullname, search);
39                 strcat(fullname, "/");
40                 strcat(fullname, fname);
41         } else {
42                 fullname = strdup(fname);
43         }
44
45         file->file = fopen(fullname, "r");
46         if (!file->file) {
47                 free(fullname);
48                 return 0;
49         }
50
51         file->name = fullname;
52         return 1;
53 }
54
55
56 struct dtc_file *dtc_open_file(const char *fname,
57                                const struct search_path *search)
58 {
59         static const struct search_path default_search = { NULL, NULL, NULL };
60
61         struct dtc_file *file;
62         const char *slash;
63
64         file = xmalloc(sizeof(struct dtc_file));
65
66         slash = strrchr(fname, '/');
67         if (slash) {
68                 char *dir = xmalloc(slash - fname + 1);
69
70                 memcpy(dir, fname, slash - fname);
71                 dir[slash - fname] = 0;
72                 file->dir = dir;
73         } else {
74                 file->dir = NULL;
75         }
76
77         if (streq(fname, "-")) {
78                 file->name = "stdin";
79                 file->file = stdin;
80                 return file;
81         }
82
83         if (fname[0] == '/') {
84                 file->file = fopen(fname, "r");
85                 if (!file->file)
86                         goto fail;
87
88                 file->name = strdup(fname);
89                 return file;
90         }
91
92         if (!search)
93                 search = &default_search;
94
95         while (search) {
96                 if (dtc_open_one(file, search->dir, fname))
97                         return file;
98
99                 if (errno != ENOENT)
100                         goto fail;
101
102                 search = search->next;
103         }
104
105 fail:
106         die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
107 }
108
109 void dtc_close_file(struct dtc_file *file)
110 {
111         if (fclose(file->file))
112                 die("Error closing \"%s\": %s\n", file->name, strerror(errno));
113
114         free(file->dir);
115         free(file);
116 }