Belt and braces iteration



  • Imagine a configuration file like so:

    setting_a => 42
    setting_b => 10.100.4.5
    setting_c => 1338
    setting_d => Z
    

    I don't have the code to hand, but it looked a lot like the following (as best as I can remember):

    open (SOMEFILE, "<", "somefile");
    @lines = <SOMEFILE>;
    close (SOMEFILE);
     
    $i = 0;
    foreach (@lines) {
    $line = $lines[$i]; # Seriously
     
    $line =~ s/ |>|\r|\n|\#.*|;.*//gi;
     
    if ($line =~ /^setting_a/) {
    $SettingA = $line; $SettingA =~ s/.*=//gi;
    }
     
    if ($line =~ /^setting_b/) {
    $SettingB = $line; $SettingB =~ s/.*=//gi;
    }
     
    if ($line =~ /^setting_c/) {
    $SettingC = $line; $SettingC =~ s/.*=//gi;
    }
     
    # Snip a page or two of these ... apparently somebody has never seen
    # a hash before ... or was smoking hash ...
     
    $i++;
    }

    Of each " => ", the " " and "> " are removed at the top, and the "=" is removed later on — not action at a distance, but … just … why? The chap helpfully factored out a bunch of string replacements, but didn't think to factor out splitting the line into key and value. In reality, the if statements did slightly more (also not factored) and were denser and harder to follow (LOTS OF STUFF IN CAPITALS FOR NO REASON), but I forget the specifics now.

    Also, he's found Perl's foreach, yet he's using it solely to terminate what is otherwise a while loop.

    I don't know what Perl version this was written for, and it may not have had switch statements (given/when) but some elsifs would have at least restored faith that the guy had some idea what he was doing. Then again, the only reason I was called to look at this code was after a crash caused by a miserable lack of error handling ('Cannot call method "login" on an undefined value' after a connection timeout).

    This codebase is always good for a laugh. It's not good for a lot else …

    Bonus points:

    • Futureproofed against uppercase and lowercase equals signs
    • Spaces in values will be clobbered
    • # and ; in values (e.g. in URLs) will be mistaken for intra-line comments — if you're going to invent your own config format you may as well break it in as many creative ways as possible
    • Escaped # in regex for fun and kittens


  • TRWTF is using your own parsing of a settings file. Nobody hear of YAML?



  • @morbiuswilters said:

    TRWTF is using your own parsing of a settings file. Nobody hear of YAML?

    Or JSON. Literally every language under the sun can parse JSON into a native format, most with native libraries even. Objective-C has NSJSONSerialization. PHP has json_decode/json_encode. Javascript has JSON.parse... the list goes on.



  • @gu3st said:

    @morbiuswilters said:
    TRWTF is using your own parsing of a settings file. Nobody hear of YAML?

    Or JSON. Literally every language under the sun can parse JSON into a native format, most with native libraries even. Objective-C has NSJSONSerialization. PHP has json_decode/json_encode. Javascript has JSON.parse... the list goes on.

    JSON is technically a subset of YAML.



  • @morbiuswilters said:

    @gu3st said:
    @morbiuswilters said:
    TRWTF is using your own parsing of a settings file. Nobody hear of YAML?

    Or JSON. Literally every language under the sun can parse JSON into a native format, most with native libraries even. Objective-C has NSJSONSerialization. PHP has json_decode/json_encode. Javascript has JSON.parse... the list goes on.

    JSON is technically a subset of YAML.

    I'm guessing you mean because it can do nesting? However, YAML is bracketless and whitespace sensitive. By your assertion, every data format is a potential subset of YAML. Heck, HTML is a subset of YAML because I can use Jade to pre-process it.



  • @Soviut said:

    I'm guessing you mean because it can do nesting? However, YAML is bracketless and whitespace sensitive. By your assertion, every data format is a potential subset of YAML. Heck, HTML is a subset of YAML because I can use Jade to pre-process it.


    A modern YAML parser can parse JSON. In fact, that's often how I parse JSON from a shell script when I don't have Node handy.



  • For posterity, this is what the code should roughly look like (assuming we know how to use a hash):

    my %settings;
    
    open my $somefile, "<", "somefile" or die "Can't open settings file: $!";
    while (<$somefile>) {
    	chomp;
    	next if /^[#;]/;
    
    	my ($setting, $value) = split(/\s*=>\s*/, $_, 2);
    	$settings{ $setting } = $value;
    }
    close $somefile;
    

    File handles are nowadays supposed to be lexical ($fh) instead of typeglobs (FH). That feature was introduced fourteen years ago, in Perl 5.6. Well, I 'm not sure it should be called a feature -- more likely, a major bugfix to the language. But anyway, typeglobs were global and they weren't really of much use. Lexical file handles automagically close when they go out of scope, so there's a definite bonus there.

    The other fun thing was that the coder was slurping the file as whole before operating on it. I guess configuration files don't tend to be large enough for that to be a problem, though.



  • I think it may have been a lexical file handle.

    If you want to be picky, the error should be: "Can't open settings file $somefile: $!" — all too often, I know that some file somewhere can't be read, but I have no idea where it is …



  • The /real/ WTF is writing your own config parser.

    C:\>perl -MConfig::Any -MData::Printer -E"p(Config::Any->load_files({ files => ['config.conf'], use_ext =>1}));"
    \ [
      [0] {
         config.conf {
           setting_a 42,
           setting_b "10.100.4.5",
           setting_c 1338,
           setting_d "Z"
         }
       }
    ]


  • @oesor said:

    The /real/ WTF is writing your own config parser.

    But surely TRWTF is writing your own config parser.



  • @morbiuswilters said:

    @oesor said:
    The /real/ WTF is writing your own config parser.

    But surely TRWTF is writing your own config parser.

    The first rule about writing your own config parser is not to talk about writing your own config parser.



  • @gu3st said:

    @morbiuswilters said:
    @oesor said:
    The /real/ WTF is writing your own config parser.

    But surely TRWTF is writing your own config parser.

    The first rule about writing your own config parser is not to talk about writing your own config parser.

    I would have known that, but Rule #2 contained "=>" in it which caused my home-grown rule parser to burst into flames.



  • @morbiuswilters said:

    Filed under: Parsing config files a regex: TRWTF

    Even worse: Using a regex to check the length of a password.

            <tr>
                <td class="label"><label for="ctl00_ContentPlaceHolder1_txtPassword" id="ctl00_ContentPlaceHolder1_Label3">Password:</label></td>
                <td>
                    <span id="ctl00_ContentPlaceHolder1_txtPassword_wrapper" class="riSingle RadInput RadInput_MetroTouch" style="width:160px;"><input id="ctl00_ContentPlaceHolder1_txtPassword" name="ctl00$ContentPlaceHolder1$txtPassword" size="20" class="riTextBox riEnabled" onkeyup="checkPasswordMatch()" type="password" /><input id="ctl00_ContentPlaceHolder1_txtPassword_ClientState" name="ctl00_ContentPlaceHolder1_txtPassword_ClientState" type="hidden" /></span>
                    <span id="ctl00_ContentPlaceHolder1_RequiredFieldValidator3" style="color:Red;display:none;">required</span>
                    <span id="ctl00_ContentPlaceHolder1_RegularExpressionValidator1" style="color:Red;display:none;">too short!</span>
                </td>
                <td>
                          <b>Password</b> – enter a new password to access your account and pet license record. Passwords must be at least 8 characters long.
                </td>
            </tr>
    

    At least it claims to be using a regular expression. Is it? Let's find that checkPasswordMatch() function. Hmm. I can't find that defined either in-line or in any of the script files it pulls in, but this looks promising...

    ctl00_ContentPlaceHolder1_RegularExpressionValidator1.controltovalidate = "ctl00_ContentPlaceHolder1_txtPassword";
    ctl00_ContentPlaceHolder1_RegularExpressionValidator1.errormessage = "too short!";
    ctl00_ContentPlaceHolder1_RegularExpressionValidator1.display = "Dynamic";
    ctl00_ContentPlaceHolder1_RegularExpressionValidator1.evaluationfunction = "RegularExpressionValidatorEvaluateIsValid";
    ctl00_ContentPlaceHolder1_RegularExpressionValidator1.validationexpression = "[a-zA-Z0-9@#$%^&+=]{8,}";
    

    Well, it allows upper-case, lower-case, numbers and special characters, and doesn't impose a maximum length – better than I expected. However, the list of allowed special characters is a bit limited, and there is no indication anywhere (except digging through the source) of what characters are allowed and what are not. Worse, if you use a disallowed special character in the first eight characters, it doesn't tell you that you have an illegal character; it tells you your password is too short. "12345678" is a valid password, but "@5kda;Ps43;'H$Y@H*V^lSF#/I(2m83''l[ixj:q}bbPRWA+!f" is "too short" because the regex only recognizes the first 5 characters. Dafuq?



  • @HardwareGeek said:

    "@5kda;Ps43;'H$Y@H*V^lSF#/I(2m83''l[ixj:q}bbPRWA+!f"

    Hey, that's my luggage combination!



  • @morbiuswilters said:

    @HardwareGeek said:
    "@5kda;Ps43;'H$Y@H*V^lSF#/I(2m83''l[ixj:q}bbPRWA+!f"

    Hey, that's my luggage combination!


    Spaceballs the config parser!



  • @DrakeSmith said:

    @morbiuswilters said:
    @HardwareGeek said:
    "@5kda;Ps43;'H$Y@H*V^lSF#/I(2m83''l[ixj:q}bbPRWA+!f"

    Hey, that's my luggage combination!


    Spaceballs the config parser!
    Next up, Spaceballs the Programming Language, where all keywords and system calls are arbitrarily taken from the movie.


    dink Main()

    {

        MegaphoneAtYourFace("Hello, Druidia!");

        barf 0;

    }



  • @mott555 said:

    @DrakeSmith said:

    @morbiuswilters said:
    @HardwareGeek said:
    "@5kda;Ps43;'H$Y@H*V^lSF#/I(2m83''l[ixj:q}bbPRWA+!f"

    Hey, that's my luggage combination!


    Spaceballs the config parser!
    Next up, Spaceballs the Programming Language, where all keywords and system calls are arbitrarily taken from the movie.


    dink Main()

    {

        MegaphoneAtYourFace("Hello, Druidia!");

        barf 0;

    }

    And '-O3' will be replace with '--ludicrous_speed' when compiling



  • @morbiuswilters said:

    "Hey, that's my luggage combination!"

    Hey, that's my luggage combination!



  • (WTF edited out)



  • @Ben L. said:

    @morbiuswilters said:
    "Hey, that's my luggage combination!"

    Hey, that's my luggage combination!

    +1



  • @mott555 said:

    @DrakeSmith said:

    @morbiuswilters said:
    @HardwareGeek said:
    "@5kda;Ps43;'H$Y@H*V^lSF#/I(2m83''l[ixj:q}bbPRWA+!f"

    Hey, that's my luggage combination!


    Spaceballs the config parser!
    Next up, Spaceballs the Programming Language, where all keywords and system calls are arbitrarily taken from the movie.


    dink Main()

    {

        MegaphoneAtYourFace("Hello, Druidia!");

        barf 0;

    }

     

    goto TheGolfCourse && WorkOn.Your("Putz");

     



  • @da Doctah said:

    @mott555 said:

    @DrakeSmith said:

    @morbiuswilters said:
    @HardwareGeek said:
    "@5kda;Ps43;'H$Y@H*V^lSF#/I(2m83''l[ixj:q}bbPRWA+!f"

    Hey, that's my luggage combination!


    Spaceballs the config parser!
    Next up, Spaceballs the Programming Language, where all keywords and system calls are arbitrarily taken from the movie.


    dink Main()

    {

        MegaphoneAtYourFace("Hello, Druidia!");

        barf 0;

    }

     

    goto TheGolfCourse && WorkOn.Your("Putz");

     


    if (ShesGonePlaid)

    {

       OverShot.Set(week);

    }



  • @DrakeSmith said:

    @da Doctah said:

     

    @mott555 said:

    @DrakeSmith said:

    @morbiuswilters said:
    @HardwareGeek said:
    "@5kda;Ps43;'H$Y@H*V^lSF#/I(2m83''l[ixj:q}bbPRWA+!f"

    Hey, that's my luggage combination!


    Spaceballs the config parser!
    Next up, Spaceballs the Programming Language, where all keywords and system calls are arbitrarily taken from the movie.


    dink Main()

    {

        MegaphoneAtYourFace("Hello, Druidia!");

        barf 0;

    }

     

    goto TheGolfCourse && WorkOn.Your("Putz");

     


    if (ShesGonePlaid)

    {

       OverShot.Set(week);

    }

    if (Now() == RadarWatchingTime)

        MrCoffee.Start();



  • @mott555 said:

    @DrakeSmith said:
    @da Doctah said:

     

    @mott555 said:

    @DrakeSmith said:

    @morbiuswilters said:
    @HardwareGeek said:
    "@5kda;Ps43;'H$Y@H*V^lSF#/I(2m83''l[ixj:q}bbPRWA+!f"

    Hey, that's my luggage combination!


    Spaceballs the config parser!
    Next up, Spaceballs the Programming Language, where all keywords and system calls are arbitrarily taken from the movie.


    dink Main()

    {

        MegaphoneAtYourFace("Hello, Druidia!");

        barf 0;

    }

     

    goto TheGolfCourse && WorkOn.Your("Putz");

     


    if (ShesGonePlaid)

    {

       OverShot.Set(week);

    }

    if (Now() == RadarWatchingTime)

        MrCoffee.Start();

    Dear Lord, what hath I wrought?


  • Considered Harmful

    public void ToggleState() { state = ( state == MegaMaidState.Suck ) ? MegaMaidState.Blow : MegaMaidState.Suck; }

  • Discourse touched me in a no-no place

    SchwartzFactory factory = CrackerjackBox.find();



  • @morbiuswilters said:

    Dear Lord, what hath I wrought?

    You should know better by now ;-)



  • @morbiuswilters said:

    @mott555 said:
    @DrakeSmith said:
    @da Doctah said:

     

    @mott555 said:

    @DrakeSmith said:

    @morbiuswilters said:
    @HardwareGeek said:
    "@5kda;Ps43;'H$Y@H*V^lSF#/I(2m83''l[ixj:q}bbPRWA+!f"

    Hey, that's my luggage combination!


    Spaceballs the config parser!
    Next up, Spaceballs the Programming Language, where all keywords and system calls are arbitrarily taken from the movie.


    dink Main()

    {

        MegaphoneAtYourFace("Hello, Druidia!");

        barf 0;

    }

     

    goto TheGolfCourse && WorkOn.Your("Putz");

     


    if (ShesGonePlaid)

    {

       OverShot.Set(week);

    }

    if (Now() == RadarWatchingTime)

        MrCoffee.Start();

    Dear Lord, what hath I wrought?


    if (Morbs.Father().Brother().Nephew().Cousin().FormerRoomate == Me)

        Morbs = AbsolutelyNothing;



  • @joe.edwards said:

    public void ToggleState() { state = ( state == MegaMaidState.Suck ) ? MegaMaidState.Blow : MegaMaidState.Suck; }

     

    ...for a second there, I thought you were going to rename true and false to suck and blow.

     



  • @mott555 said:

    if (Morbs.Father().Brother().Nephew().Cousin().FormerRoomate == Me)

        Morbs = AbsolutelyNothing;

    Filed under: [Edit Tags], I know that code is technically wrong but I'm too lazy to deal with collection iteration for a joke
    It's not that difficult, at least for the one collection that matters, and totally worth it:

    for (Man possibleFather : Morbs.Father()) {
        if (possibleFather.Brother().Nephew().Cousin().FormerRoomate == Me)
            Morbs = AbsolutelyNothing;

    }



  • @gu3st said:

    Literally every language under the sun can parse JSON into a native format...

     Lets see an implementation for PAL-8 



  • @TheCPUWizard said:

    @gu3st said:

    Literally every language under the sun can parse JSON into a native format...

     Lets see an implementation for PAL-8 


    List of languages I would like gu3st to confirm his hypothesis on:



  • @Ben L. said:

    @TheCPUWizard said:

    @gu3st said:

    Literally every language under the sun can parse JSON into a native format...

     Lets see an implementation for PAL-8 


    List of languages I would like gu3st to confirm his hypothesis on:

    None of those languages can be found under the sun. They all reside in a special place in Hell set aside for stupid programming languages and the sexless nerds who create them.


  • @bstorer said:

    @Ben L. said:
    @TheCPUWizard said:

    @gu3st said:

    Literally every language under the sun can parse JSON into a native format...

     Lets see an implementation for PAL-8 


    List of languages I would like gu3st to confirm his hypothesis on:

    None of those languages can be found under the sun. They all reside in a special place in Hell set aside for stupid programming languages and the sexless nerds who create them.

    To be fair, I'm pretty sure the only language to come out from under the Sun was Java.



  • @Buttembly Coder said:

    @bstorer said:
    @Ben L. said:
    @TheCPUWizard said:

    @gu3st said:

    Literally every language under the sun can parse JSON into a native format...

     Lets see an implementation for PAL-8 


    List of languages I would like gu3st to confirm his hypothesis on:

    None of those languages can be found under the sun. They all reside in a special place in Hell set aside for stupid programming languages and the sexless nerds who create them.

    To be fair, I'm pretty sure the only language to come out from under the Sun was Java.

    Ah, you forget Fortress.


  • @bstorer said:

    @Buttembly Coder said:
    @bstorer said:
    @Ben L. said:
    @TheCPUWizard said:

    @gu3st said:

    Literally every language under the sun can parse JSON into a native format...

     Lets see an implementation for PAL-8 


    List of languages I would like gu3st to confirm his hypothesis on:

    None of those languages can be found under the sun. They all reside in a special place in Hell set aside for stupid programming languages and the sexless nerds who create them.

    To be fair, I'm pretty sure the only language to come out from under the Sun was Java.

    Ah, you forget Fortress.


  • @Ben L. said:

    @bstorer said:
    @Buttembly Coder said:
    @bstorer said:
    @Ben L. said:
    @TheCPUWizard said:

    @gu3st said:

    Literally every language under the sun can parse JSON into a native format...

     Lets see an implementation for PAL-8 


    List of languages I would like gu3st to confirm his hypothesis on:

    None of those languages can be found under the sun. They all reside in a special place in Hell set aside for stupid programming languages and the sexless nerds who create them.

    To be fair, I'm pretty sure the only language to come out from under the Sun was Java.

    Ah, you forget Fortress.

    Assuming there is some Turing-complete thing in Dwarf Fortress, go ahead and implement a JSON parser in it.



  • @Buttembly Coder said:

    @Ben L. said:
    @bstorer said:
    @Buttembly Coder said:
    @bstorer said:
    @Ben L. said:
    @TheCPUWizard said:

    @gu3st said:

    Literally every language under the sun can parse JSON into a native format...

     Lets see an implementation for PAL-8 


    List of languages I would like gu3st to confirm his hypothesis on:

    None of those languages can be found under the sun. They all reside in a special place in Hell set aside for stupid programming languages and the sexless nerds who create them.

    To be fair, I'm pretty sure the only language to come out from under the Sun was Java.

    Ah, you forget Fortress.

    Assuming there is some Turing-complete thing in Dwarf Fortress, go ahead and implement a JSON parser in it.

    Evidently, someone built a turing machine in it.



  • I never went to computer school, so am I right when claiming that any system with a switch or inverter or whatever can eventually become a computer or turing-complete?


  • Discourse touched me in a no-no place

    @dhromed said:

    I never went to computer school, so am I right when claiming that any system with a switch or inverter or whatever can eventually become a computer or turing-complete?
    It's a NAND, NOR or XOR that's sufficient for building any other standard logic element, and those have indeed been used to build whole computers. An inverter isn't enough though, unless you abuse it terribly (which is what real hardware people actually do to make those NANDs and NORs).

    They don't make computers exactly that way any more; there are cheaper ways (well, in terms of power and circuit density, but those translate into better wafer usage and so become either actually cheaper or actually more profitable, depending on price point).



  • @dkf said:

    @dhromed said:
    I never went to computer school, so am I right when claiming that any system with a switch or inverter or whatever can eventually become a computer or turing-complete?
    It's a NAND, NOR or XOR that's sufficient for building any other standard logic element, and those have indeed been used to build whole computers. An inverter isn't enough though, unless you abuse it terribly (which is what real hardware people actually do to make those NANDs and NORs).

    They don't make computers exactly that way any more; there are cheaper ways (well, in terms of power and circuit density, but those translate into better wafer usage and so become either actually cheaper or actually more profitable, depending on price point).

    Wait, XOR works? How do you get true? With NOR or NAND it's simply (input OP input) OP (input OP input).



  • @Ben L. said:

    Wait, XOR works? How do you get true? With NOR or NAND it's simply (input OP input) OP (input OP input).
    input XOR 0
    Edit: Or do you mean constant true? Just true. At least in real hardware, constants true and false are always available without using any gates.



  • Some what relevant, or at least entertaining: Domino Logic.



  • @HardwareGeek said:

    @Ben L. said:
    Wait, XOR works? How do you get true? With NOR or NAND it's simply (input OP input) OP (input OP input).
    input XOR 0
    Edit: Or do you mean constant true? Just true. At least in real hardware, constants true and false are always available without using any gates.
    How do you make a NAND out of XORs?



  • @mikeTheLiar said:

    Some what relevant, or at least entertaining: Domino Logic.
    Just needs a way to auto-reset the dominoes on a clock somehow, and an adapter to plug it into a 1970's motherboard and we could build a fully-functional Domino-based 8086 in an unused baseball stadium.


  • Discourse touched me in a no-no place

    @flabdablet said:

    How do you make a NAND out of XORs?
    Sorry. Brain-fart there. You can't, as it's too symmetric. My bad. (In my meagre defence, I've been distracted by an ongoing fight with a horrible Wordpress installation the past few days. It's definitely TRWTF in ever so many ways, but I'm too tired and fed up with the whole thing to want to try to list them all beyond grumbling about it's insane notions of what belongs in a URL and what doesn't.)


Log in to reply