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