@@ -222,20 +222,6 @@ class MasterLoader::MasterLoaderImpl {
222
222
// / handled in \c loadIncremental().
223
223
MasterToken handleInitialToken ();
224
224
225
- // / \brief Helper method for \c doGenerate().
226
- // /
227
- // / This is a helper method for \c doGenerate() that processes the
228
- // / LHS or RHS for a single iteration in the range that is requested
229
- // / by the $GENERATE directive and returns a generated string (that
230
- // / is used to build a name (LHS) or RDATA (RHS) for an RR). See the
231
- // / commented implementation for details.
232
- std::string generateForIter (const std::string& str, const int it);
233
-
234
- // / \brief Process the $GENERATE directive.
235
- // /
236
- // / See the commented implementation for details.
237
- void doGenerate ();
238
-
239
225
// / \brief Process the $ORIGIN directive.
240
226
void doOrigin (bool is_optional) {
241
227
// Parse and create the new origin. It is relative to the previous
@@ -458,9 +444,6 @@ class MasterLoader::MasterLoaderImpl {
458
444
} else if (iequals (directive, " ORIGIN" )) {
459
445
doOrigin (false );
460
446
eatUntilEOL (true );
461
- } else if (iequals (directive, " GENERATE" )) {
462
- doGenerate ();
463
- eatUntilEOL (true );
464
447
} else if (iequals (directive, " TTL" )) {
465
448
setDefaultTTL (RRTTL (getString ()), false );
466
449
eatUntilEOL (true );
@@ -551,318 +534,6 @@ class MasterLoader::MasterLoaderImpl {
551
534
size_t rr_count_; // number of RRs successfully loaded
552
535
};
553
536
554
- namespace { // begin unnamed namespace
555
-
556
- // / \brief Generate a dotted nibble sequence.
557
- // /
558
- // / This method generates a dotted nibble sequence and returns it as a
559
- // / string. The nibbles are appended from the least significant digit
560
- // / (in hex representation of \c num) to the most significant digit with
561
- // / dots ('.') to separate the digits. If \c width is non-zero and the
562
- // / dotted nibble sequence has not filled the requested width, the rest
563
- // / of the width is filled with a dotted nibble sequence of 0 nibbles.
564
- // /
565
- // / Some sample representations:
566
- // /
567
- // / num = 0x1234, width = 0
568
- // / "4.3.2.1"
569
- // /
570
- // / num = 0x1234, width = 1
571
- // / "4.3.2.1"
572
- // /
573
- // / num = 0x1234, width = 8
574
- // / "4.3.2.1"
575
- // /
576
- // / num = 0x1234, width = 9
577
- // / "4.3.2.1."
578
- // /
579
- // / num = 0x1234, width = 10
580
- // / "4.3.2.1.0"
581
- // /
582
- // / num = 0x1234, width = 11
583
- // / "4.3.2.1.0."
584
- // /
585
- // / num = 0xabcd, width = 0, uppercase = true
586
- // / "D.C.B.A"
587
- // /
588
- // / num = 0, width = 0
589
- // / "0"
590
- // /
591
- // / num = 0, width = 1
592
- // / "0"
593
- // /
594
- // / num = 0, width = 2
595
- // / "0."
596
- // /
597
- // / num = 0, width = 3
598
- // / "0.0"
599
- // /
600
- // / \param num The number for which the dotted nibble sequence should be
601
- // / generated.
602
- // / \param width The width of the generated string. This is only
603
- // / meaningful when it is larger than the dotted nibble sequence
604
- // / representation of \c num.
605
- // / \param uppercase Whether to use uppercase characters in nibble
606
- // / sequence.
607
- // / \return A string containing the dotted nibble sequence.
608
- std::string
609
- genNibbles (int num, unsigned int width, bool uppercase) {
610
- static const char *hex = " 0123456789abcdef0123456789ABCDEF" ;
611
- std::string rstr;
612
-
613
- do {
614
- char ch = hex[(num & 0x0f ) + (uppercase ? 16 : 0 )];
615
- num >>= 4 ;
616
- rstr.push_back (ch);
617
-
618
- if (width > 0 ) {
619
- --width;
620
- }
621
-
622
- // If width is non zero then we need to add a label separator.
623
- // If value is non zero then we need to add another label and
624
- // that requires a label separator.
625
- if (width > 0 || num != 0 ) {
626
- rstr.push_back (' .' );
627
-
628
- if (width > 0 ) {
629
- --width;
630
- }
631
- }
632
- } while ((num != 0 ) || (width > 0 ));
633
-
634
- return (rstr);
635
- }
636
-
637
- } // end unnamed namespace
638
-
639
- std::string
640
- MasterLoader::MasterLoaderImpl::generateForIter (const std::string& str,
641
- const int num) {
642
- std::string rstr;
643
-
644
- for (auto it = str.begin (); it != str.end ();) {
645
- switch (*it) {
646
- case ' $' :
647
- // This is the case when the '$' character is encountered in
648
- // the LHS or RHS. A computed value is added in its place in
649
- // the generated string.
650
- ++it;
651
- if ((it != str.end ()) && (*it == ' $' )) {
652
- rstr.push_back (' $' );
653
- ++it;
654
- continue ;
655
- }
656
-
657
- // The str.end() check is required.
658
- if ((it == str.end ()) || (*it != ' {' )) {
659
- // There is no modifier (between {}), so just copy the
660
- // passed number into the generated string.
661
- rstr += boost::str (boost::format (" %d" ) % num);
662
- } else {
663
- // There is a modifier (between {}). Parse it and handle
664
- // the various cases below.
665
- const char * scan_str =
666
- str.c_str () + std::distance (str.begin (), it);
667
- int offset = 0 ;
668
- unsigned int width;
669
- char base[2 ] = {' d' , 0 }; // char plus null byte
670
- // cppcheck-suppress invalidscanf_libc
671
- const int n = sscanf (scan_str, " {%d,%u,%1[doxXnN]}" ,
672
- &offset, &width, base);
673
- switch (n) {
674
- case 1 :
675
- // Only 1 item was matched (the offset). Copy (num +
676
- // offset) into the generated string.
677
- rstr += boost::str (boost::format (" %d" ) % (num + offset));
678
- break ;
679
-
680
- case 2 : {
681
- // 2 items were matched (the offset and width). Copy
682
- // (num + offset) and format it according to the width
683
- // into the generated string.
684
- const std::string fmt =
685
- boost::str (boost::format (" %%0%ud" ) % width);
686
- rstr += boost::str (boost::format (fmt) % (num + offset));
687
- break ;
688
- }
689
-
690
- case 3 :
691
- // 3 items were matched (offset, width and base).
692
- if ((base[0 ] == ' n' ) || (base[0 ] == ' N' )) {
693
- // The base is requesting nibbles. Format it
694
- // specially (see genNibbles() documentation).
695
- rstr += genNibbles (num + offset, width, (base[0 ] == ' N' ));
696
- } else {
697
- // The base is not requesting nibbles. Copy (num +
698
- // offset) and format it according to the width
699
- // and base into the generated string.
700
- const std::string fmt =
701
- boost::str (boost::format (" %%0%u%c" ) % width % base[0 ]);
702
- rstr += boost::str (boost::format (fmt) % (num + offset));
703
- }
704
- break ;
705
-
706
- default :
707
- // Any other case in the modifiers is an error.
708
- reportError (lexer_.getSourceName (), lexer_.getSourceLine (),
709
- " Invalid $GENERATE format modifiers" );
710
- return (" " );
711
- }
712
-
713
- // Find the closing brace. Careful that 'it' can be equal
714
- // to str.end() here.
715
- while ((it != str.end ()) && (*it != ' }' )) {
716
- ++it;
717
- }
718
- // Skip past the closing brace (if there is one).
719
- if (it != str.end ()) {
720
- ++it;
721
- }
722
- }
723
- break ;
724
-
725
- case ' \\ ' :
726
- // This is the case when the '\' character is encountered in
727
- // the LHS or RHS. The '\' and the following character are
728
- // copied as-is into the generated string. This is usually
729
- // used for escaping the $ character.
730
- rstr.push_back (*it);
731
- ++it;
732
- if (it == str.end ()) {
733
- continue ;
734
- }
735
- rstr.push_back (*it);
736
- ++it;
737
- break ;
738
-
739
- default :
740
- // This is the default case that handles all other
741
- // characters. They are copied as-is into the generated
742
- // string.
743
- rstr.push_back (*it);
744
- ++it;
745
- break ;
746
- }
747
- }
748
-
749
- return (rstr);
750
- }
751
-
752
- void
753
- MasterLoader::MasterLoaderImpl::doGenerate () {
754
- // Parse the range token
755
- const MasterToken& range_token = lexer_.getNextToken (MasterToken::STRING);
756
- if (range_token.getType () != MasterToken::STRING) {
757
- reportError (lexer_.getSourceName (), lexer_.getSourceLine (),
758
- " Invalid $GENERATE syntax" );
759
- return ;
760
- }
761
- const std::string range = range_token.getString ();
762
-
763
- // Parse the LHS token
764
- const MasterToken& lhs_token = lexer_.getNextToken (MasterToken::STRING);
765
- if (lhs_token.getType () != MasterToken::STRING) {
766
- reportError (lexer_.getSourceName (), lexer_.getSourceLine (),
767
- " Invalid $GENERATE syntax" );
768
- return ;
769
- }
770
- const std::string lhs = lhs_token.getString ();
771
-
772
- // Parse the TTL, RR class and RR type tokens. Note that TTL and RR
773
- // class may come in any order, or may be missing (either or
774
- // both). If TTL is missing, we expect that it was either specified
775
- // explicitly using $TTL, or is implicitly known from a previous RR,
776
- // or that this is the SOA RR from which the MINIMUM field is
777
- // used. It's unlikely that $GENERATE will be used with an SOA RR,
778
- // but it's possible. The parsing happens within the parseRRParams()
779
- // helper method which is called below.
780
- const MasterToken& param_token = lexer_.getNextToken (MasterToken::STRING);
781
- if (param_token.getType () != MasterToken::STRING) {
782
- reportError (lexer_.getSourceName (), lexer_.getSourceLine (),
783
- " Invalid $GENERATE syntax" );
784
- return ;
785
- }
786
-
787
- bool explicit_ttl = false ;
788
- const RRType rrtype = parseRRParams (explicit_ttl, param_token);
789
-
790
- // Parse the RHS token. It can be a quoted string.
791
- const MasterToken& rhs_token = lexer_.getNextToken (MasterToken::QSTRING);
792
- if ((rhs_token.getType () != MasterToken::QSTRING) &&
793
- (rhs_token.getType () != MasterToken::STRING))
794
- {
795
- reportError (lexer_.getSourceName (), lexer_.getSourceLine (),
796
- " Invalid $GENERATE syntax" );
797
- return ;
798
- }
799
- const std::string rhs = rhs_token.getString ();
800
-
801
- // Range can be one of two forms: start-stop or start-stop/step. If
802
- // the first form is used, then step is set to 1. All of start, stop
803
- // and step must be positive.
804
- unsigned int start;
805
- unsigned int stop;
806
- unsigned int step;
807
- // cppcheck-suppress invalidscanf_libc
808
- const int n = sscanf (range.c_str (), " %u-%u/%u" , &start, &stop, &step);
809
- if ((n < 2 ) || (stop < start)) {
810
- reportError (lexer_.getSourceName (), lexer_.getSourceLine (),
811
- " $GENERATE: invalid range: " + range);
812
- return ;
813
- }
814
-
815
- if (n == 2 ) {
816
- step = 1 ;
817
- }
818
-
819
- // Generate and add the records.
820
- for (unsigned int i = start; i <= stop; i += step) {
821
- // Get generated strings for LHS and RHS. LHS goes to form the
822
- // name, RHS goes to form the RDATA of the RR.
823
- const std::string generated_name = generateForIter (lhs, i);
824
- const std::string generated_rdata = generateForIter (rhs, i);
825
- if (generated_name.empty () || generated_rdata.empty ()) {
826
- // The error should have been sent to the callbacks already
827
- // by generateForIter().
828
- reportError (lexer_.getSourceName (), lexer_.getSourceLine (),
829
- " $GENERATE error" );
830
- return ;
831
- }
832
-
833
- // generateForIter() can return a string with a trailing '.' in
834
- // case of a nibble representation. So we cannot use the
835
- // relative Name constructor. We use concatenate() which is
836
- // expensive, but keeps the generated LHS-based Name within the
837
- // active origin.
838
- last_name_.reset
839
- (new Name (Name (generated_name).concatenate (active_origin_)));
840
- previous_name_ = true ;
841
-
842
- const rdata::RdataPtr rdata =
843
- rdata::createRdata (rrtype, zone_class_, generated_rdata);
844
- // In case we get null, it means there was error creating the
845
- // Rdata. The errors should have been reported by callbacks_
846
- // already. We need to decide if we want to continue or not.
847
- if (rdata) {
848
- add_callback_ (*last_name_, zone_class_, rrtype,
849
- getCurrentTTL (explicit_ttl, rrtype, rdata),
850
- rdata);
851
- // Good, we added another one
852
- ++rr_count_;
853
- } else {
854
- seen_error_ = true ;
855
- if (!many_errors_) {
856
- ok_ = false ;
857
- complete_ = true ;
858
- // We don't have the exact error here, but it was
859
- // reported by the error callback.
860
- isc_throw (MasterLoaderError, " Invalid RR data" );
861
- }
862
- }
863
- }
864
- }
865
-
866
537
MasterToken
867
538
MasterLoader::MasterLoaderImpl::handleInitialToken () {
868
539
const MasterToken& initial_token =
0 commit comments