// -*- C++ -*- // Boost general library 'format' --------------------------- // See http://www.boost.org for updates, documentation, and revision history. // (C) Samuel Krempp 2001 // krempp@crans.ens-cachan.fr // Permission to copy, use, modify, sell and // distribute this software is granted provided this copyright notice appears // in all copies. This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // ideas taken from Rudiger Loos's format class // and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing) // ------------------------------------------------------------------------------ // parsing.hpp : implementation of the parsing member functions // ( parse, parse_printf_directive) // ------------------------------------------------------------------------------ #ifndef BOOST_FORMAT_PARSING_HPP #define BOOST_FORMAT_PARSING_HPP #include
aboutsummaryrefslogtreecommitdiff
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

;;;
;;; Check whether important binaries are available.
;;;

(use-modules (guix store)
             (guix grafts)
             (guix packages)
             (guix derivations)
             (guix ui)
             (gnu packages commencement)
             (ice-9 match)
             (srfi srfi-1)
             (srfi srfi-26))

(define (final-inputs store system)
  "Return the list of outputs directories of the final inputs for SYSTEM."
  (append-map (match-lambda
                ((or (name package) (name package _))
                 (let ((drv (package-derivation store package system)))
                   ;; Libc's 'debug' output refers to gcc-cross-boot0, but it's
                   ;; hard to avoid, so we tolerate it.  This should be the
                   ;; only exception.  Likewise, 'bash:include' depends on
                   ;; bootstrap-binaries via its 'Makefile.inc' (FIXME).
                   (filter-map (match-lambda
                                 (("debug" . directory)
                                  (if (string=? "glibc" (package-name package))
                                      #f
                                      directory))
                                 (("include" . directory)
                                  (if (string=? "bash" (package-name package))
                                      #f
                                      directory))
                                 ((_ . directory) directory))
                               (derivation->output-paths drv)))))
              %final-inputs))

(define (assert-valid-substitute substitute)
  "Make sure SUBSTITUTE does not refer to any bootstrap inputs, and bail out
if it does."
  (let ((references (substitutable-references substitute)))
    (when (any (cut string-contains <> "boot") references)
      (leave (G_ "'~a' refers to bootstrap inputs: ~s~%")
             (substitutable-path substitute) references))))

(define (test-final-inputs store system)
  "Check whether the final inputs for SYSTEM are clean---i.e., they don't
refer to the bootstrap tools."
  (format #t "checking final inputs for '~a'...~%" system)
  (let* ((inputs    (final-inputs store system))
         (available (substitutable-path-info store inputs)))
    (for-each (lambda (dir)
                (unless (find (lambda (substitute)
                                (string=? (substitutable-path substitute)
                                          dir))
                              available)
                  (leave (G_ "~a (system: ~a) has no substitute~%")
                         dir system)))
              inputs)

    (for-each assert-valid-substitute available)))

;; Entry point.
(with-store store
  (parameterize ((%graft? #f))
    (set-build-options store #:use-substitutes? #t)

    (for-each (cut test-final-inputs store <>)
              %cuirass-supported-systems)))
; case '-': fpar->ref_state_.flags_ |= std::ios::left; break; case '=': fpar->pad_scheme_ |= format_item_t::centered; break; case ' ': fpar->pad_scheme_ |= format_item_t::spacepad; break; case '+': fpar->ref_state_.flags_ |= std::ios::showpos; break; case '0': fpar->pad_scheme_ |= format_item_t::zeropad; // need to know alignment before really setting flags, // so just add 'zeropad' flag for now, it will be processed later. break; case '#': fpar->ref_state_.flags_ |= std::ios::showpoint | std::ios::showbase; break; default: goto parse_width; } ++i1; } // loop on flag. if( i1>=buf.size()) { maybe_throw_exception(exceptions); return true; } parse_width: // handle width spec skip_asterisk(buf, &i1, os); // skips 'asterisk fields' : *, or *N$ i0 = i1; // save position before digits while (i1ref_state_.width_ = str2int( buf,i0, os, std::streamsize(0) ); } parse_precision: if( i1>=buf.size()) { maybe_throw_exception(exceptions); return true; } // handle precision spec if (buf[i1]=='.') { ++i1; skip_asterisk(buf, &i1, os); i0 = i1; // save position before digits while (i1ref_state_.precision_ = 0; else fpar->ref_state_.precision_ = str2int(buf,i0, os, std::streamsize(0) ); } // handle formatting-type flags : while( i1=buf.size()) { maybe_throw_exception(exceptions); return true; } if( in_brackets && buf[i1]=='|' ) { ++i1; return true; } switch (buf[i1]) { case 'X': fpar->ref_state_.flags_ |= std::ios::uppercase; case 'p': // pointer => set hex. case 'x': fpar->ref_state_.flags_ &= ~std::ios::basefield; fpar->ref_state_.flags_ |= std::ios::hex; break; case 'o': fpar->ref_state_.flags_ &= ~std::ios::basefield; fpar->ref_state_.flags_ |= std::ios::oct; break; case 'E': fpar->ref_state_.flags_ |= std::ios::uppercase; case 'e': fpar->ref_state_.flags_ &= ~std::ios::floatfield; fpar->ref_state_.flags_ |= std::ios::scientific; fpar->ref_state_.flags_ &= ~std::ios::basefield; fpar->ref_state_.flags_ |= std::ios::dec; break; case 'f': fpar->ref_state_.flags_ &= ~std::ios::floatfield; fpar->ref_state_.flags_ |= std::ios::fixed; case 'u': case 'd': case 'i': fpar->ref_state_.flags_ &= ~std::ios::basefield; fpar->ref_state_.flags_ |= std::ios::dec; break; case 'T': ++i1; if( i1 >= buf.size()) maybe_throw_exception(exceptions); else fpar->ref_state_.fill_ = buf[i1]; fpar->pad_scheme_ |= format_item_t::tabulation; fpar->argN_ = format_item_t::argN_tabulation; break; case 't': fpar->ref_state_.fill_ = ' '; fpar->pad_scheme_ |= format_item_t::tabulation; fpar->argN_ = format_item_t::argN_tabulation; break; case 'G': fpar->ref_state_.flags_ |= std::ios::uppercase; break; case 'g': // 'g' conversion is default for floats. fpar->ref_state_.flags_ &= ~std::ios::basefield; fpar->ref_state_.flags_ |= std::ios::dec; // CLEAR all floatield flags, so stream will CHOOSE fpar->ref_state_.flags_ &= ~std::ios::floatfield; break; case 'C': case 'c': fpar->truncate_ = 1; break; case 'S': case 's': fpar->truncate_ = fpar->ref_state_.precision_; fpar->ref_state_.precision_ = -1; break; case 'n' : fpar->argN_ = format_item_t::argN_ignored; break; default: maybe_throw_exception(exceptions); } ++i1; if( in_brackets ) { if( i1= buf.size() ) { if(exceptions() & io::bad_format_string_bit) boost::throw_exception(io::bad_format_string()); // must not end in "bla bla %" else break; // stop there, ignore last '%' } if(buf[i1+1] == buf[i1] ) { i1+=2; continue; } // escaped "%%" / "##" ++i1; // in case of %N% directives, dont count it double (wastes allocations..) : while(i1 < buf.size() && io::detail::wrap_isdigit(buf[i1],oss_)) ++i1; if( i1 < buf.size() && buf[i1] == arg_mark ) ++ i1; ++num_items; } items_.assign( num_items, format_item_t() ); // B: Now the real parsing of the format string : num_items=0; i1 = 0; string_t::size_type i0 = i1; bool special_things=false; int cur_it=0; while( (i1=buf.find(arg_mark,i1)) != string::npos ) { string_t & piece = (cur_it==0) ? prefix_ : items_[cur_it-1].appendix_; if( buf[i1+1] == buf[i1] ) // escaped mark, '%%' { piece += buf.substr(i0, i1-i0) + buf[i1]; i1+=2; i0=i1; continue; } BOOST_ASSERT( static_cast(cur_it) < items_.size() || cur_it==0); if(i1!=i0) piece += buf.substr(i0, i1-i0); ++i1; bool parse_ok; parse_ok = io::detail::parse_printf_directive(buf, &i1, &items_[cur_it], oss_, exceptions()); if( ! parse_ok ) continue; // the directive will be printed verbatim i0=i1; items_[cur_it].compute_states(); // process complex options, like zeropad, into stream params. int argN=items_[cur_it].argN_; if(argN == format_item_t::argN_ignored) continue; if(argN ==format_item_t::argN_no_posit) ordered_args=false; else if(argN == format_item_t::argN_tabulation) special_things=true; else if(argN > max_argN) max_argN = argN; ++num_items; ++cur_it; } // loop on %'s BOOST_ASSERT(cur_it == num_items); // store the final piece of string string_t & piece = (cur_it==0) ? prefix_ : items_[cur_it-1].appendix_; piece += buf.substr(i0); if( !ordered_args) { if(max_argN >= 0 ) // dont mix positional with non-positionnal directives { if(exceptions() & io::bad_format_string_bit) boost::throw_exception(io::bad_format_string()); // else do nothing. => positionnal arguments are processed as non-positionnal } // set things like it would have been with positional directives : int non_ordered_items = 0; for(int i=0; i< num_items; ++i) if(items_[i].argN_ == format_item_t::argN_no_posit) { items_[i].argN_ = non_ordered_items; ++non_ordered_items; } max_argN = non_ordered_items-1; } // C: set some member data : items_.resize(num_items); if(special_things) style_ |= special_needs; num_args_ = max_argN + 1; if(ordered_args) style_ |= ordered; else style_ &= ~ordered; } } // namespace boost #endif // BOOST_FORMAT_PARSING_HPP