linux/scripts/dtc/srcpos.c
<<
>>
Prefs
   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#define _GNU_SOURCE
  21
  22#include <stdio.h>
  23
  24#include "dtc.h"
  25#include "srcpos.h"
  26
  27
  28static char *dirname(const char *path)
  29{
  30        const char *slash = strrchr(path, '/');
  31
  32        if (slash) {
  33                int len = slash - path;
  34                char *dir = xmalloc(len + 1);
  35
  36                memcpy(dir, path, len);
  37                dir[len] = '\0';
  38                return dir;
  39        }
  40        return NULL;
  41}
  42
  43FILE *depfile; /* = NULL */
  44struct srcfile_state *current_srcfile; /* = NULL */
  45
  46/* Detect infinite include recursion. */
  47#define MAX_SRCFILE_DEPTH     (100)
  48static int srcfile_depth; /* = 0 */
  49
  50FILE *srcfile_relative_open(const char *fname, char **fullnamep)
  51{
  52        FILE *f;
  53        char *fullname;
  54
  55        if (streq(fname, "-")) {
  56                f = stdin;
  57                fullname = xstrdup("<stdin>");
  58        } else {
  59                if (!current_srcfile || !current_srcfile->dir
  60                    || (fname[0] == '/'))
  61                        fullname = xstrdup(fname);
  62                else
  63                        fullname = join_path(current_srcfile->dir, fname);
  64
  65                f = fopen(fullname, "r");
  66                if (!f)
  67                        die("Couldn't open \"%s\": %s\n", fname,
  68                            strerror(errno));
  69        }
  70
  71        if (depfile)
  72                fprintf(depfile, " %s", fullname);
  73
  74        if (fullnamep)
  75                *fullnamep = fullname;
  76        else
  77                free(fullname);
  78
  79        return f;
  80}
  81
  82void srcfile_push(const char *fname)
  83{
  84        struct srcfile_state *srcfile;
  85
  86        if (srcfile_depth++ >= MAX_SRCFILE_DEPTH)
  87                die("Includes nested too deeply");
  88
  89        srcfile = xmalloc(sizeof(*srcfile));
  90
  91        srcfile->f = srcfile_relative_open(fname, &srcfile->name);
  92        srcfile->dir = dirname(srcfile->name);
  93        srcfile->prev = current_srcfile;
  94
  95        srcfile->lineno = 1;
  96        srcfile->colno = 1;
  97
  98        current_srcfile = srcfile;
  99}
 100
 101int srcfile_pop(void)
 102{
 103        struct srcfile_state *srcfile = current_srcfile;
 104
 105        assert(srcfile);
 106
 107        current_srcfile = srcfile->prev;
 108
 109        if (fclose(srcfile->f))
 110                die("Error closing \"%s\": %s\n", srcfile->name,
 111                    strerror(errno));
 112
 113        /* FIXME: We allow the srcfile_state structure to leak,
 114         * because it could still be referenced from a location
 115         * variable being carried through the parser somewhere.  To
 116         * fix this we could either allocate all the files from a
 117         * table, or use a pool allocator. */
 118
 119        return current_srcfile ? 1 : 0;
 120}
 121
 122/*
 123 * The empty source position.
 124 */
 125
 126struct srcpos srcpos_empty = {
 127        .first_line = 0,
 128        .first_column = 0,
 129        .last_line = 0,
 130        .last_column = 0,
 131        .file = NULL,
 132};
 133
 134#define TAB_SIZE      8
 135
 136void srcpos_update(struct srcpos *pos, const char *text, int len)
 137{
 138        int i;
 139
 140        pos->file = current_srcfile;
 141
 142        pos->first_line = current_srcfile->lineno;
 143        pos->first_column = current_srcfile->colno;
 144
 145        for (i = 0; i < len; i++)
 146                if (text[i] == '\n') {
 147                        current_srcfile->lineno++;
 148                        current_srcfile->colno = 1;
 149                } else if (text[i] == '\t') {
 150                        current_srcfile->colno =
 151                                ALIGN(current_srcfile->colno, TAB_SIZE);
 152                } else {
 153                        current_srcfile->colno++;
 154                }
 155
 156        pos->last_line = current_srcfile->lineno;
 157        pos->last_column = current_srcfile->colno;
 158}
 159
 160struct srcpos *
 161srcpos_copy(struct srcpos *pos)
 162{
 163        struct srcpos *pos_new;
 164
 165        pos_new = xmalloc(sizeof(struct srcpos));
 166        memcpy(pos_new, pos, sizeof(struct srcpos));
 167
 168        return pos_new;
 169}
 170
 171
 172
 173void
 174srcpos_dump(struct srcpos *pos)
 175{
 176        printf("file        : \"%s\"\n",
 177               pos->file ? (char *) pos->file : "<no file>");
 178        printf("first_line  : %d\n", pos->first_line);
 179        printf("first_column: %d\n", pos->first_column);
 180        printf("last_line   : %d\n", pos->last_line);
 181        printf("last_column : %d\n", pos->last_column);
 182        printf("file        : %s\n", pos->file->name);
 183}
 184
 185
 186char *
 187srcpos_string(struct srcpos *pos)
 188{
 189        const char *fname = "<no-file>";
 190        char *pos_str;
 191        int rc;
 192
 193        if (pos)
 194                fname = pos->file->name;
 195
 196
 197        if (pos->first_line != pos->last_line)
 198                rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
 199                              pos->first_line, pos->first_column,
 200                              pos->last_line, pos->last_column);
 201        else if (pos->first_column != pos->last_column)
 202                rc = asprintf(&pos_str, "%s:%d.%d-%d", fname,
 203                              pos->first_line, pos->first_column,
 204                              pos->last_column);
 205        else
 206                rc = asprintf(&pos_str, "%s:%d.%d", fname,
 207                              pos->first_line, pos->first_column);
 208
 209        if (rc == -1)
 210                die("Couldn't allocate in srcpos string");
 211
 212        return pos_str;
 213}
 214
 215void
 216srcpos_verror(struct srcpos *pos, char const *fmt, va_list va)
 217{
 218       const char *srcstr;
 219
 220       srcstr = srcpos_string(pos);
 221
 222       fprintf(stdout, "Error: %s ", srcstr);
 223       vfprintf(stdout, fmt, va);
 224       fprintf(stdout, "\n");
 225}
 226
 227void
 228srcpos_error(struct srcpos *pos, char const *fmt, ...)
 229{
 230        va_list va;
 231
 232        va_start(va, fmt);
 233        srcpos_verror(pos, fmt, va);
 234        va_end(va);
 235}
 236
 237
 238void
 239srcpos_warn(struct srcpos *pos, char const *fmt, ...)
 240{
 241        const char *srcstr;
 242        va_list va;
 243        va_start(va, fmt);
 244
 245        srcstr = srcpos_string(pos);
 246
 247        fprintf(stderr, "Warning: %s ", srcstr);
 248        vfprintf(stderr, fmt, va);
 249        fprintf(stderr, "\n");
 250
 251        va_end(va);
 252}
 253
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.