OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [go/] [gofrontend/] [import.cc] - Blame information for rev 714

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 714 jeremybenn
// import.cc -- Go frontend import declarations.
2
 
3
// Copyright 2009 The Go Authors. All rights reserved.
4
// Use of this source code is governed by a BSD-style
5
// license that can be found in the LICENSE file.
6
 
7
#include "go-system.h"
8
 
9
#include "filenames.h"
10
#include "simple-object.h"
11
 
12
#include "go-c.h"
13
#include "gogo.h"
14
#include "lex.h"
15
#include "types.h"
16
#include "export.h"
17
#include "import.h"
18
 
19
#ifndef O_BINARY
20
#define O_BINARY 0
21
#endif
22
 
23
// The list of paths we search for import files.
24
 
25
static std::vector<std::string> search_path;
26
 
27
// Add a directory to the search path.  This is called from the option
28
// handling language hook.
29
 
30
GO_EXTERN_C
31
void
32
go_add_search_path(const char* path)
33
{
34
  search_path.push_back(std::string(path));
35
}
36
 
37
// Find import data.  This searches the file system for FILENAME and
38
// returns a pointer to a Stream object to read the data that it
39
// exports.  If the file is not found, it returns NULL.
40
 
41
// When FILENAME is not an absolute path and does not start with ./ or
42
// ../, we use the search path provided by -I and -L options.
43
 
44
// When FILENAME does not exist, we try modifying FILENAME to find the
45
// file.  We use the first of these which exists:
46
//   * We append ".gox".
47
//   * We turn the base of FILENAME into libFILENAME.so.
48
//   * We turn the base of FILENAME into libFILENAME.a.
49
//   * We append ".o".
50
 
51
// When using a search path, we apply each of these transformations at
52
// each entry on the search path before moving on to the next entry.
53
// If the file exists, but does not contain any Go export data, we
54
// stop; we do not keep looking for another file with the same name
55
// later in the search path.
56
 
57
Import::Stream*
58
Import::open_package(const std::string& filename, Location location)
59
{
60
  bool is_local;
61
  if (IS_ABSOLUTE_PATH(filename))
62
    is_local = true;
63
  else if (filename[0] == '.' && IS_DIR_SEPARATOR(filename[1]))
64
    is_local = true;
65
  else if (filename[0] == '.'
66
           && filename[1] == '.'
67
           && IS_DIR_SEPARATOR(filename[2]))
68
    is_local = true;
69
  else
70
    is_local = false;
71
  if (!is_local)
72
    {
73
      for (std::vector<std::string>::const_iterator p = search_path.begin();
74
           p != search_path.end();
75
           ++p)
76
        {
77
          std::string indir = *p;
78
          if (!indir.empty() && indir[indir.size() - 1] != '/')
79
            indir += '/';
80
          indir += filename;
81
          Stream* s = Import::try_package_in_directory(indir, location);
82
          if (s != NULL)
83
            return s;
84
        }
85
    }
86
 
87
  Stream* s = Import::try_package_in_directory(filename, location);
88
  if (s != NULL)
89
    return s;
90
 
91
  return NULL;
92
}
93
 
94
// Try to find the export data for FILENAME.
95
 
96
Import::Stream*
97
Import::try_package_in_directory(const std::string& filename,
98
                                 Location location)
99
{
100
  std::string found_filename = filename;
101
  int fd = open(found_filename.c_str(), O_RDONLY | O_BINARY);
102
 
103
  if (fd >= 0)
104
    {
105
      struct stat s;
106
      if (fstat(fd, &s) >= 0 && S_ISDIR(s.st_mode))
107
        {
108
          close(fd);
109
          fd = -1;
110
          errno = EISDIR;
111
        }
112
    }
113
 
114
  if (fd < 0)
115
    {
116
      if (errno != ENOENT && errno != EISDIR)
117
        warning_at(location, 0, "%s: %m", filename.c_str());
118
 
119
      fd = Import::try_suffixes(&found_filename);
120
      if (fd < 0)
121
        return NULL;
122
    }
123
 
124
  // The export data may not be in this file.
125
  Stream* s = Import::find_export_data(found_filename, fd, location);
126
  if (s != NULL)
127
    return s;
128
 
129
  close(fd);
130
 
131
  error_at(location, "%s exists but does not contain any Go export data",
132
           found_filename.c_str());
133
 
134
  return NULL;
135
}
136
 
137
// Given import "*PFILENAME", where *PFILENAME does not exist, try
138
// various suffixes.  If we find one, set *PFILENAME to the one we
139
// found.  Return the open file descriptor.
140
 
141
int
142
Import::try_suffixes(std::string* pfilename)
143
{
144
  std::string filename = *pfilename + ".gox";
145
  int fd = open(filename.c_str(), O_RDONLY | O_BINARY);
146
  if (fd >= 0)
147
    {
148
      *pfilename = filename;
149
      return fd;
150
    }
151
 
152
  const char* basename = lbasename(pfilename->c_str());
153
  size_t basename_pos = basename - pfilename->c_str();
154
  filename = pfilename->substr(0, basename_pos) + "lib" + basename + ".so";
155
  fd = open(filename.c_str(), O_RDONLY | O_BINARY);
156
  if (fd >= 0)
157
    {
158
      *pfilename = filename;
159
      return fd;
160
    }
161
 
162
  filename = pfilename->substr(0, basename_pos) + "lib" + basename + ".a";
163
  fd = open(filename.c_str(), O_RDONLY | O_BINARY);
164
  if (fd >= 0)
165
    {
166
      *pfilename = filename;
167
      return fd;
168
    }
169
 
170
  filename = *pfilename + ".o";
171
  fd = open(filename.c_str(), O_RDONLY | O_BINARY);
172
  if (fd >= 0)
173
    {
174
      *pfilename = filename;
175
      return fd;
176
    }
177
 
178
  return -1;
179
}
180
 
181
// Look for export data in the file descriptor FD.
182
 
183
Import::Stream*
184
Import::find_export_data(const std::string& filename, int fd,
185
                         Location location)
186
{
187
  // See if we can read this as an object file.
188
  Import::Stream* stream = Import::find_object_export_data(filename, fd, 0,
189
                                                           location);
190
  if (stream != NULL)
191
    return stream;
192
 
193
  const int len = MAX(Export::v1_magic_len, Import::archive_magic_len);
194
 
195
  if (lseek(fd, 0, SEEK_SET) < 0)
196
    {
197
      error_at(location, "lseek %s failed: %m", filename.c_str());
198
      return NULL;
199
    }
200
 
201
  char buf[len];
202
  ssize_t c = read(fd, buf, len);
203
  if (c < len)
204
    return NULL;
205
 
206
  // Check for a file containing nothing but Go export data.
207
  if (memcmp(buf, Export::v1_magic, Export::v1_magic_len) == 0)
208
    return new Stream_from_file(fd);
209
 
210
  // See if we can read this as an archive.
211
  if (Import::is_archive_magic(buf))
212
    return Import::find_archive_export_data(filename, fd, location);
213
 
214
  return NULL;
215
}
216
 
217
// Look for export data in a simple_object.
218
 
219
Import::Stream*
220
Import::find_object_export_data(const std::string& filename,
221
                                int fd,
222
                                off_t offset,
223
                                Location location)
224
{
225
  char *buf;
226
  size_t len;
227
  int err;
228
  const char *errmsg = go_read_export_data(fd, offset, &buf, &len, &err);
229
  if (errmsg != NULL)
230
    {
231
      if (err == 0)
232
        error_at(location, "%s: %s", filename.c_str(), errmsg);
233
      else
234
        error_at(location, "%s: %s: %s", filename.c_str(), errmsg,
235
                 xstrerror(err));
236
      return NULL;
237
    }
238
 
239
  if (buf == NULL)
240
    return NULL;
241
 
242
  return new Stream_from_buffer(buf, len);
243
}
244
 
245
// Class Import.
246
 
247
// Construct an Import object.  We make the builtin_types_ vector
248
// large enough to hold all the builtin types.
249
 
250
Import::Import(Stream* stream, Location location)
251
  : gogo_(NULL), stream_(stream), location_(location), package_(NULL),
252
    add_to_globals_(false),
253
    builtin_types_((- SMALLEST_BUILTIN_CODE) + 1),
254
    types_()
255
{
256
}
257
 
258
// Import the data in the associated stream.
259
 
260
Package*
261
Import::import(Gogo* gogo, const std::string& local_name,
262
               bool is_local_name_exported)
263
{
264
  // Hold on to the Gogo structure.  Otherwise we need to pass it
265
  // through all the import functions, because we need it when reading
266
  // a type.
267
  this->gogo_ = gogo;
268
 
269
  // A stream of export data can include data from more than one input
270
  // file.  Here we loop over each input file.
271
  Stream* stream = this->stream_;
272
  while (!stream->at_eof() && !stream->saw_error())
273
    {
274
      // The vector of types is package specific.
275
      this->types_.clear();
276
 
277
      stream->require_bytes(this->location_, Export::v1_magic,
278
                            Export::v1_magic_len);
279
 
280
      this->require_c_string("package ");
281
      std::string package_name = this->read_identifier();
282
      this->require_c_string(";\n");
283
 
284
      this->require_c_string("prefix ");
285
      std::string unique_prefix = this->read_identifier();
286
      this->require_c_string(";\n");
287
 
288
      this->package_ = gogo->add_imported_package(package_name, local_name,
289
                                                  is_local_name_exported,
290
                                                  unique_prefix,
291
                                                  this->location_,
292
                                                  &this->add_to_globals_);
293
      if (this->package_ == NULL)
294
        {
295
          stream->set_saw_error();
296
          return NULL;
297
        }
298
 
299
      this->require_c_string("priority ");
300
      std::string priority_string = this->read_identifier();
301
      int prio;
302
      if (!this->string_to_int(priority_string, false, &prio))
303
        return NULL;
304
      this->package_->set_priority(prio);
305
      this->require_c_string(";\n");
306
 
307
      while (stream->match_c_string("import"))
308
        this->read_one_import();
309
 
310
      if (stream->match_c_string("init"))
311
        this->read_import_init_fns(gogo);
312
 
313
      // Loop over all the input data for this package.
314
      while (!stream->saw_error())
315
        {
316
          if (stream->match_c_string("const "))
317
            this->import_const();
318
          else if (stream->match_c_string("type "))
319
            this->import_type();
320
          else if (stream->match_c_string("var "))
321
            this->import_var();
322
          else if (stream->match_c_string("func "))
323
            this->import_func(this->package_);
324
          else if (stream->match_c_string("checksum "))
325
            break;
326
          else
327
            {
328
              error_at(this->location_,
329
                       ("error in import data at %d: "
330
                        "expected %<const%>, %<type%>, %<var%>, "
331
                        "%<func%>, or %<checksum%>"),
332
                       stream->pos());
333
              stream->set_saw_error();
334
              return NULL;
335
            }
336
        }
337
 
338
      // We currently ignore the checksum.  In the future we could
339
      // store the checksum somewhere in the generated object and then
340
      // verify that the checksum matches at link time or at dynamic
341
      // load time.
342
      this->require_c_string("checksum ");
343
      stream->advance(Export::v1_checksum_len * 2);
344
      this->require_c_string(";\n");
345
    }
346
 
347
  return this->package_;
348
}
349
 
350
// Read an import line.  We don't actually care about these.
351
 
352
void
353
Import::read_one_import()
354
{
355
  this->require_c_string("import ");
356
  Stream* stream = this->stream_;
357
  while (stream->peek_char() != ';')
358
    stream->advance(1);
359
  this->require_c_string(";\n");
360
}
361
 
362
// Read the list of import control functions.
363
 
364
void
365
Import::read_import_init_fns(Gogo* gogo)
366
{
367
  this->require_c_string("init");
368
  while (!this->match_c_string(";"))
369
    {
370
      this->require_c_string(" ");
371
      std::string package_name = this->read_identifier();
372
      this->require_c_string(" ");
373
      std::string init_name = this->read_identifier();
374
      this->require_c_string(" ");
375
      std::string prio_string = this->read_identifier();
376
      int prio;
377
      if (!this->string_to_int(prio_string, false, &prio))
378
        return;
379
      gogo->add_import_init_fn(package_name, init_name, prio);
380
    }
381
  this->require_c_string(";\n");
382
}
383
 
384
// Import a constant.
385
 
386
void
387
Import::import_const()
388
{
389
  std::string name;
390
  Type* type;
391
  Expression* expr;
392
  Named_constant::import_const(this, &name, &type, &expr);
393
  Typed_identifier tid(name, type, this->location_);
394
  Named_object* no = this->package_->add_constant(tid, expr);
395
  if (this->add_to_globals_)
396
    this->gogo_->add_named_object(no);
397
}
398
 
399
// Import a type.
400
 
401
void
402
Import::import_type()
403
{
404
  Named_type* type;
405
  Named_type::import_named_type(this, &type);
406
 
407
  // The named type has been added to the package by the type import
408
  // process.  Here we need to make it visible to the parser, and it
409
  // to the global bindings if necessary.
410
  type->set_is_visible();
411
 
412
  if (this->add_to_globals_)
413
    this->gogo_->add_named_type(type);
414
}
415
 
416
// Import a variable.
417
 
418
void
419
Import::import_var()
420
{
421
  std::string name;
422
  Type* type;
423
  Variable::import_var(this, &name, &type);
424
  Variable* var = new Variable(type, NULL, true, false, false,
425
                               this->location_);
426
  Named_object* no;
427
  no = this->package_->add_variable(name, var);
428
  if (this->add_to_globals_)
429
    this->gogo_->add_named_object(no);
430
}
431
 
432
// Import a function into PACKAGE.  PACKAGE is normally
433
// THIS->PACKAGE_, but it will be different for a method associated
434
// with a type defined in a different package.
435
 
436
Named_object*
437
Import::import_func(Package* package)
438
{
439
  std::string name;
440
  Typed_identifier* receiver;
441
  Typed_identifier_list* parameters;
442
  Typed_identifier_list* results;
443
  bool is_varargs;
444
  Function::import_func(this, &name, &receiver, &parameters, &results,
445
                        &is_varargs);
446
  Function_type *fntype = Type::make_function_type(receiver, parameters,
447
                                                   results, this->location_);
448
  if (is_varargs)
449
    fntype->set_is_varargs();
450
 
451
  Location loc = this->location_;
452
  Named_object* no;
453
  if (fntype->is_method())
454
    {
455
      Type* rtype = receiver->type();
456
 
457
      // We may still be reading the definition of RTYPE, so we have
458
      // to be careful to avoid calling base or convert.  If RTYPE is
459
      // a named type or a forward declaration, then we know that it
460
      // is not a pointer, because we are reading a method on RTYPE
461
      // and named pointers can't have methods.
462
 
463
      if (rtype->classification() == Type::TYPE_POINTER)
464
        rtype = rtype->points_to();
465
 
466
      if (rtype->is_error_type())
467
        return NULL;
468
      else if (rtype->named_type() != NULL)
469
        no = rtype->named_type()->add_method_declaration(name, package, fntype,
470
                                                         loc);
471
      else if (rtype->forward_declaration_type() != NULL)
472
        no = rtype->forward_declaration_type()->add_method_declaration(name,
473
                                                                       package,
474
                                                                       fntype,
475
                                                                       loc);
476
      else
477
        go_unreachable();
478
    }
479
  else
480
    {
481
      no = package->add_function_declaration(name, fntype, loc);
482
      if (this->add_to_globals_)
483
        this->gogo_->add_named_object(no);
484
    }
485
  return no;
486
}
487
 
488
// Read a type in the import stream.  This records the type by the
489
// type index.  If the type is named, it registers the name, but marks
490
// it as invisible.
491
 
492
Type*
493
Import::read_type()
494
{
495
  Stream* stream = this->stream_;
496
  this->require_c_string("<type ");
497
 
498
  std::string number;
499
  int c;
500
  while (true)
501
    {
502
      c = stream->get_char();
503
      if (c != '-' && (c < '0' || c > '9'))
504
        break;
505
      number += c;
506
    }
507
 
508
  int index;
509
  if (!this->string_to_int(number, true, &index))
510
    return Type::make_error_type();
511
 
512
  if (c == '>')
513
    {
514
      // This type was already defined.
515
      if (index < 0
516
          ? (static_cast<size_t>(- index) >= this->builtin_types_.size()
517
             || this->builtin_types_[- index] == NULL)
518
          : (static_cast<size_t>(index) >= this->types_.size()
519
             || this->types_[index] == NULL))
520
        {
521
          error_at(this->location_,
522
                   "error in import data at %d: bad type index %d",
523
                   stream->pos(), index);
524
          stream->set_saw_error();
525
          return Type::make_error_type();
526
        }
527
 
528
      return index < 0 ? this->builtin_types_[- index] : this->types_[index];
529
    }
530
 
531
  if (c != ' ')
532
    {
533
      if (!stream->saw_error())
534
        error_at(this->location_,
535
                 "error in import data at %d: expect %< %> or %<>%>'",
536
                 stream->pos());
537
      stream->set_saw_error();
538
      stream->advance(1);
539
      return Type::make_error_type();
540
    }
541
 
542
  if (index <= 0
543
      || (static_cast<size_t>(index) < this->types_.size()
544
          && this->types_[index] != NULL))
545
    {
546
      error_at(this->location_,
547
               "error in import data at %d: type index already defined",
548
               stream->pos());
549
      stream->set_saw_error();
550
      return Type::make_error_type();
551
    }
552
 
553
  if (static_cast<size_t>(index) >= this->types_.size())
554
    {
555
      int newsize = std::max(static_cast<size_t>(index) + 1,
556
                             this->types_.size() * 2);
557
      this->types_.resize(newsize, NULL);
558
    }
559
 
560
  if (stream->peek_char() != '"')
561
    {
562
      Type* type = Type::import_type(this);
563
      this->require_c_string(">");
564
      this->types_[index] = type;
565
      return type;
566
    }
567
 
568
  // This type has a name.
569
 
570
  stream->advance(1);
571
  std::string type_name;
572
  while ((c = stream->get_char()) != '"')
573
    type_name += c;
574
 
575
  // If this type is in the current package, the name will be
576
  // .PREFIX.PACKAGE.NAME or simply NAME with no dots.  Otherwise, a
577
  // non-hidden symbol will be PREFIX.PACKAGE.NAME and a hidden symbol
578
  // will be .PREFIX.PACKAGE.NAME.
579
  std::string package_name;
580
  std::string unique_prefix;
581
  if (type_name.find('.') != std::string::npos)
582
    {
583
      bool is_hidden = false;
584
      size_t start = 0;
585
      if (type_name[0] == '.')
586
        {
587
          ++start;
588
          is_hidden = true;
589
        }
590
      size_t dot1 = type_name.find('.', start);
591
      size_t dot2;
592
      if (dot1 == std::string::npos)
593
        dot2 = std::string::npos;
594
      else
595
        dot2 = type_name.find('.', dot1 + 1);
596
      if (dot1 == std::string::npos || dot2 == std::string::npos)
597
        {
598
          error_at(this->location_,
599
                   ("error at import data at %d: missing dot in type name"),
600
                   stream->pos());
601
          stream->set_saw_error();
602
        }
603
      else
604
        {
605
          unique_prefix = type_name.substr(start, dot1 - start);
606
          package_name = type_name.substr(dot1 + 1, dot2 - (dot1 + 1));
607
        }
608
      if (!is_hidden)
609
        type_name.erase(0, dot2 + 1);
610
    }
611
 
612
  this->require_c_string(" ");
613
 
614
  // Declare the type in the appropriate package.  If we haven't seen
615
  // it before, mark it as invisible.  We declare it before we read
616
  // the actual definition of the type, since the definition may refer
617
  // to the type itself.
618
  Package* package;
619
  if (package_name.empty())
620
    package = this->package_;
621
  else
622
    package = this->gogo_->register_package(package_name, unique_prefix,
623
                                            Linemap::unknown_location());
624
 
625
  Named_object* no = package->bindings()->lookup(type_name);
626
  if (no == NULL)
627
    no = package->add_type_declaration(type_name, this->location_);
628
  else if (!no->is_type_declaration() && !no->is_type())
629
    {
630
      error_at(this->location_, "imported %<%s.%s%> both type and non-type",
631
               Gogo::message_name(package->name()).c_str(),
632
               Gogo::message_name(type_name).c_str());
633
      stream->set_saw_error();
634
      return Type::make_error_type();
635
    }
636
  else
637
    go_assert(no->package() == package);
638
 
639
  if (this->types_[index] == NULL)
640
    {
641
      if (no->is_type_declaration())
642
        {
643
          // FIXME: It's silly to make a forward declaration every time.
644
          this->types_[index] = Type::make_forward_declaration(no);
645
        }
646
      else
647
        {
648
          go_assert(no->is_type());
649
          this->types_[index] = no->type_value();
650
        }
651
    }
652
 
653
  // If there is no type definition, then this is just a forward
654
  // declaration of a type defined in some other file.
655
  Type* type;
656
  if (this->match_c_string(">"))
657
    type = this->types_[index];
658
  else
659
    {
660
      type = this->read_type();
661
 
662
      if (no->is_type_declaration())
663
        {
664
          // We can define the type now.
665
 
666
          no = package->add_type(type_name, type, this->location_);
667
          Named_type* ntype = no->type_value();
668
 
669
          // This type has not yet been imported.
670
          ntype->clear_is_visible();
671
 
672
          type = ntype;
673
        }
674
      else if (no->is_type())
675
        {
676
          // We have seen this type before.  FIXME: it would be a good
677
          // idea to check that the two imported types are identical,
678
          // but we have not finalized the methods yet, which means
679
          // that we can not reliably compare interface types.
680
          type = no->type_value();
681
 
682
          // Don't change the visibility of the existing type.
683
        }
684
 
685
      this->types_[index] = type;
686
 
687
      // Read the type methods.
688
      if (this->match_c_string("\n"))
689
        {
690
          this->advance(1);
691
          while (this->match_c_string(" func"))
692
            {
693
              this->advance(1);
694
              this->import_func(package);
695
            }
696
        }
697
    }
698
 
699
  this->require_c_string(">");
700
 
701
  return type;
702
}
703
 
704
// Register the builtin types.
705
 
706
void
707
Import::register_builtin_types(Gogo* gogo)
708
{
709
  this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
710
  this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
711
  this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
712
  this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
713
  this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
714
  this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
715
  this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
716
  this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
717
  this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
718
  this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
719
  this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
720
  this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
721
  this->register_builtin_type(gogo, "int", BUILTIN_INT);
722
  this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
723
  this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
724
  this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
725
  this->register_builtin_type(gogo, "string", BUILTIN_STRING);
726
  this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
727
  this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
728
  this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
729
}
730
 
731
// Register a single builtin type.
732
 
733
void
734
Import::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
735
{
736
  Named_object* named_object = gogo->lookup_global(name);
737
  go_assert(named_object != NULL && named_object->is_type());
738
  int index = - static_cast<int>(code);
739
  go_assert(index > 0
740
             && static_cast<size_t>(index) < this->builtin_types_.size());
741
  this->builtin_types_[index] = named_object->type_value();
742
}
743
 
744
// Read an identifier from the stream.
745
 
746
std::string
747
Import::read_identifier()
748
{
749
  std::string ret;
750
  Stream* stream = this->stream_;
751
  int c;
752
  while (true)
753
    {
754
      c = stream->peek_char();
755
      if (c == -1 || c == ' ' || c == ';')
756
        break;
757
      ret += c;
758
      stream->advance(1);
759
    }
760
  return ret;
761
}
762
 
763
// Read a name from the stream.
764
 
765
std::string
766
Import::read_name()
767
{
768
  std::string ret = this->read_identifier();
769
  if (ret == "?")
770
    ret.clear();
771
  else if (!Lex::is_exported_name(ret))
772
    ret = ('.' + this->package_->unique_prefix()
773
           + '.' + this->package_->name()
774
           + '.' + ret);
775
  return ret;
776
}
777
 
778
// Turn a string into a integer with appropriate error handling.
779
 
780
bool
781
Import::string_to_int(const std::string &s, bool is_neg_ok, int* ret)
782
{
783
  char* end;
784
  long prio = strtol(s.c_str(), &end, 10);
785
  if (*end != '\0' || prio > 0x7fffffff || (prio < 0 && !is_neg_ok))
786
    {
787
      error_at(this->location_, "invalid integer in import data at %d",
788
               this->stream_->pos());
789
      this->stream_->set_saw_error();
790
      return false;
791
    }
792
  *ret = prio;
793
  return true;
794
}
795
 
796
// Class Import::Stream.
797
 
798
Import::Stream::Stream()
799
  : pos_(0), saw_error_(false)
800
{
801
}
802
 
803
Import::Stream::~Stream()
804
{
805
}
806
 
807
// Return the next character to come from the stream.
808
 
809
int
810
Import::Stream::peek_char()
811
{
812
  const char* read;
813
  if (!this->do_peek(1, &read))
814
    return -1;
815
  // Make sure we return an unsigned char, so that we don't get
816
  // confused by \xff.
817
  unsigned char ret = *read;
818
  return ret;
819
}
820
 
821
// Return true if the next LENGTH characters from the stream match
822
// BYTES
823
 
824
bool
825
Import::Stream::match_bytes(const char* bytes, size_t length)
826
{
827
  const char* read;
828
  if (!this->do_peek(length, &read))
829
    return false;
830
  return memcmp(bytes, read, length) == 0;
831
}
832
 
833
// Require that the next LENGTH bytes from the stream match BYTES.
834
 
835
void
836
Import::Stream::require_bytes(Location location, const char* bytes,
837
                              size_t length)
838
{
839
  const char* read;
840
  if (!this->do_peek(length, &read)
841
      || memcmp(bytes, read, length) != 0)
842
    {
843
      if (!this->saw_error_)
844
        error_at(location, "import error at %d: expected %<%.*s%>",
845
                 this->pos(), static_cast<int>(length), bytes);
846
      this->saw_error_ = true;
847
      return;
848
    }
849
  this->advance(length);
850
}
851
 
852
// Class Stream_from_file.
853
 
854
Stream_from_file::Stream_from_file(int fd)
855
  : fd_(fd), data_()
856
{
857
  if (lseek(fd, 0, SEEK_SET) != 0)
858
    {
859
      error("lseek failed: %m");
860
      this->set_saw_error();
861
    }
862
}
863
 
864
Stream_from_file::~Stream_from_file()
865
{
866
  close(this->fd_);
867
}
868
 
869
// Read next bytes.
870
 
871
bool
872
Stream_from_file::do_peek(size_t length, const char** bytes)
873
{
874
  if (this->data_.length() <= length)
875
    {
876
      *bytes = this->data_.data();
877
      return true;
878
    }
879
  // Don't bother to handle the general case, since we don't need it.
880
  go_assert(length < 64);
881
  char buf[64];
882
  ssize_t got = read(this->fd_, buf, length);
883
 
884
  if (got < 0)
885
    {
886
      if (!this->saw_error())
887
        error("read failed: %m");
888
      this->set_saw_error();
889
      return false;
890
    }
891
 
892
  if (lseek(this->fd_, - got, SEEK_CUR) != 0)
893
    {
894
      if (!this->saw_error())
895
        error("lseek failed: %m");
896
      this->set_saw_error();
897
      return false;
898
    }
899
 
900
  if (static_cast<size_t>(got) < length)
901
    return false;
902
 
903
  this->data_.assign(buf, got);
904
 
905
  *bytes = this->data_.data();
906
  return true;
907
}
908
 
909
// Advance.
910
 
911
void
912
Stream_from_file::do_advance(size_t skip)
913
{
914
  if (lseek(this->fd_, skip, SEEK_CUR) != 0)
915
    {
916
      if (!this->saw_error())
917
        error("lseek failed: %m");
918
      this->set_saw_error();
919
    }
920
  if (!this->data_.empty())
921
    {
922
      if (this->data_.length() < skip)
923
        this->data_.erase(0, skip);
924
      else
925
        this->data_.clear();
926
    }
927
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.