Announcement

Collapse
No announcement yet.

Long CSV fields

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • #41
    What the hell is wrong with yelling or screaming. I actually encourage it when it can be of useful. Boy could I tell some stories.
    Look. Anybody that knows much about an email format would be just purely missing the boat to make an email part of a simple comma delimited file.
    p purvis

    Comment


    • #42
      Maybe you cannot "control" them.. but...
      We are in a pretty competitive market, so anything we try to "advise" our clients to do, they often reply, "Well, XYZ Company doesn't have a problem with our files, so I guess I'll just take our business there. Bye..."

      But, on the bright side... it gives me something to do.
      Last edited by Jim Robinson; 14 Jun 2017, 01:13 PM. Reason: Too much fun...
      ... .... . ... . . ... ... .... . .. ... .... .. ... .... .. .... ..

      n6jah @ yahoo.com

      Comment


      • #43
        We are in a pretty competitive market, so anything we try to "advise" our clients to do, they often reply, "Well, XYZ Company doesn't have a problem with our files, so I guess I'll just take our business there
        One of the hardest things to learn is how to say, "No, thank you."

        But I suggest everyone learn anyway.


        MCM
        Michael Mattias
        Tal Systems Inc.
        Racine WI USA
        mmattias@talsystems.com
        http://www.talsystems.com

        Comment


        • #44
          I recon Kerry will become one of the resident email experts.
          Just for starters. Many emails break standard rules of email. One is the emails basic date/time and subject.
          Now you figure they would have that and st least subject. I had to allow my email server to accept those kinds of emails. Yes, those are current email senders with info we need receive.
          Google use to not include email originating ipaddress and much stuff like that. Maybe it was a storage size thingy.

          p purvis

          Comment


          • #45
            Originally posted by Jim Robinson View Post
            We are in a pretty competitive market, so anything we try to "advise" our clients to do, they often reply, "Well, XYZ Company doesn't have a problem with our files, so I guess I'll just take our business there. Bye..."
            Well, with that attitude either those clients have a monopoly of sorts, or they sooner or later go out of business. My bet's on the later ...

            Comment


            • #46
              Knuth, programing is not business. Business is an entity that makes a living providing a product or service. If you happen to be the janitor and programmer, then you have to provide a fair price for your services or product based only on your financial needs. This changes when you have employees, but the bottom line is negotiation between the potential client and server.

              If your in business long enough you will find the proposal comes before any contract. A potential client that tells me that XYZ company doesn't have a problem, my 1st thoughts are he owes this company money or comparing prices. I've turned down many engineering jobs on initial verbal conversation. Software or programming was an aid to my business.

              I've dealt with many CSV files, and from the posts here I still don't know what Kerry's objective was, or basically what the client wanted.

              Comment


              • #47
                Originally posted by Nick Luick View Post
                I've dealt with many CSV files, and from the posts here I still don't know what Kerry's objective was, or basically what the client wanted.
                My objective was to read a CSV file which had a lot of issues - 3 easy fields and one complex field. The complex field had email information and some of the emails were themselves an amalgamation of emails. So the complex field had uncontrolled content and control characters. It was up to 40,000 bytes but could be more. The file was over 11000 records. The file was incorrectly read by Excel and could not be read with FreeFileViewer. I had to read it as binary and PARSE$ and REMAIN$ carefully to extract the data that I wanted. I thought that I may have hit some of the PB size limits but it turned out that this was not the case. I had to change the file format and code some fields using the 3 easy fields (they were not that easy!) and create an output CSV file in a different format.

                One of the amazing outcomes was that I did not give any real consideration to speed but the program only takes seconds to run - thanks PB.

                Another outcome is that I have standardized my binary file read process in a MACRO so I am good from now on. I have also tightened up my processes for recognizing and dealing sensibly with corrupt records (checking, ignoring, reporting, counting).

                The easy fields also had some issues that fell outside the user spec - but I just managed them.
                [I]I made a coding error once - but fortunately I fixed it before anyone noticed[/I]
                Kerry Farmer

                Comment


                • #48
                  and from the posts here I still don't know what Kerry's objective was..
                  Kerry Farmer's objective in Post#1 was to seek to learn if some PowerBASIC compiler limitation was responsible for some "bad read" situations. limits After he was told there were no such limitations, he began looking at what else could be causing his symptoms.

                  As you can see in Keryy's Post #47, he has addressed and cured those symptoms by changing the code used to read the file... code which made assumptions which just were not true.
                  Michael Mattias
                  Tal Systems Inc.
                  Racine WI USA
                  mmattias@talsystems.com
                  http://www.talsystems.com

                  Comment


                  • #49
                    Back again ! From Kerry's post #47, my premise in post #25 of outputting a cleaned up file was his solution. This cleaned file could be read and searched or sorted by various available readers. Kerry's software is now more of a utility. In his post #26 the desire was not to have a modified 2nd file.

                    I'm old school and get by using INSTR and MID$ in combination to accomplish parsing, albeit a little slower.

                    Comment


                    • #50
                      Hi Nick

                      Thanks for your continued interest

                      I had forgotten about INSTR!!!! So thanks for reminding me. I can see me using MID$(data,INSTR(blah), LEN(data)- INSTR(blah)) or something - is there plus or minus 1 in there?

                      Actually, you can call my program a utility if you like but some of the field conversions I had to do with the 'easy' fields are quite specific to this client. I had not mentioned them as they were quite straightforward but took a little bit of thought and testing.
                      [I]I made a coding error once - but fortunately I fixed it before anyone noticed[/I]
                      Kerry Farmer

                      Comment


                      • #51
                        I use INSTR a lot when manipulating strings. And +1"s and "-1's are dependent on what you are trying to do.
                        Generally a "+1" will only work if Blah is one character long. In other cases, you will need "+Len(Blah)", but "-1"s are often handy regardless of the length of Blah.

                        Your example function doesn't need the third parameter. MID$ defaults to "the rest of the string" if the 3rd parameter is omitted.
                        (and INSTR takes two parameters)

                        Mid$(strData,INSTR(strData,blah)) will extract everything including the starting Blah.
                        Note that Mid$ is simpler than Right$ in this case:
                        You would need - Right$(strData,LEN(strData) - INSTR(strData,Blah) + 1)

                        Mid$(data,INSTR(strData,blah) + Len(blah)) will extract everything after Blah
                        alternatively the more complex again -
                        Right$(strData,LEN(strData) - INSTR(strData,blah) - LEN(blah) + 1)


                        Also
                        Left$(strData,iINSTR(strData,blah) - 1) will extract everything before Blah.

                        (Hope I've got all of them right )
                        --
                        [URL="http://www.camcopng.com"]CAMCo - Applications Development & ICT Consultancy[/URL][URL="http://www.hostingpng.com"]
                        PNG Domain Hosting[/URL]

                        Comment


                        • #52
                          'm old school and get by using INSTR and MID$ in combination to accomplish parsing, albeit a little slower.
                          Hmm... someone around here is always saying, "First you make it work, then you can make it work better."

                          I think I'd listen to that guy.

                          MCM
                          PS: I have it on good authority he's 'old school,' too!
                          Michael Mattias
                          Tal Systems Inc.
                          Racine WI USA
                          mmattias@talsystems.com
                          http://www.talsystems.com

                          Comment


                          • #53
                            Kerry,

                            If you cannot control the usage of CRLF in the source files, here is a toy for you that will convert any combination of CRLF (13,10 or both) to a single CRLF pair. It also removes any blank lines that are only ascii 13,10. It should be fast enough.
                            Code:
                            ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                            
                                #include "\basic\include\win32api.inc"
                            
                            ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                            
                            FUNCTION PBmain as LONG
                            
                                test$ = load_file("win32api.inc")           ' load a standard CRLF delimited text file
                            
                                test$ = remove$(test$,chr$(10))             ' strip ascii 10s from it (13 works too)
                            
                                rslt$ = any2crlf(test$)                     ' convert text back to CRLF delimited text
                            
                                save_file("output.txt",rslt$)
                            
                                waitkey$
                            
                            End FUNCTION
                            
                            ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                            
                            FUNCTION any2crlf(src$) as STRING
                              ' -------------------------------------------------------
                              ' replace any combination of CRLF with a single CRLF pair
                              ' -------------------------------------------------------
                                #REGISTER NONE
                            
                                LOCAL psrc as DWORD
                                LOCAL pbuf as DWORD
                                LOCAL rlen as DWORD
                            
                                psrc = StrPtr(src$)
                                buf$ = space$(len(src$)*2)
                                pbuf = StrPtr(buf$)
                            
                              PREFIX "!"
                            
                                mov esi, psrc
                                mov edi, pbuf
                            
                                sub esi, 1
                              lbl0:
                                add esi, 1
                              backin:
                                movzx eax, BYTE PTR [esi]
                                test eax, eax
                                jz bye
                                cmp eax, 13
                                je nxt
                                cmp eax, 10
                                je nxt
                                mov BYTE PTR [edi], al
                                add edi, 1
                                jmp lbl0
                            
                              nxt:
                                add esi, 1
                                movzx eax, BYTE PTR [esi]
                                test eax, eax
                                jz bye
                                cmp eax, 13
                                je nxt
                                cmp eax, 10
                                je nxt
                                mov BYTE PTR [edi], 13
                                add edi, 1
                                mov BYTE PTR [edi], 10
                                add edi, 1
                                jmp backin
                            
                              bye:
                                mov BYTE PTR [edi], 13
                                add edi, 1
                                mov BYTE PTR [edi], 10
                                add edi, 1
                            
                                sub edi, pbuf
                                mov rlen, edi
                            
                              END PREFIX
                            
                                FUNCTION = left$(buf$,rlen)
                            
                            End FUNCTION
                            
                            ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                            
                                DECLARE FUNCTION open_file_A LIB "KERNEL32.DLL" ALIAS "CreateFileA" ( _
                                                 ByVal lpFileName AS DWORD, _
                                                 ByVal dwDesiredAccess AS DWORD, _
                                                 ByVal dwShareMode AS DWORD, _
                                                 ByVal lpSecurityAttributes AS DWORD, _
                                                 ByVal dwCreationDisposition AS DWORD, _
                                                 ByVal dwFlagsAndAttributes AS DWORD, _
                                                 BYVAL hTemplateFile AS DWORD) AS DWORD
                            
                                DECLARE FUNCTION get_file_size LIB "KERNEL32.DLL" ALIAS "GetFileSize" ( _
                                                 BYVAL hFile AS DWORD, lpFileSizeHigh AS LONG) AS LONG
                            
                                DECLARE FUNCTION file__read LIB "KERNEL32.DLL" ALIAS "ReadFile" ( _
                                                 BYVAL hFile AS DWORD,ByVal pbuff as DWORD, BYVAL nNumberOfBytesToRead AS DWORD, _
                                                 ByVal lpNumberOfBytesRead AS DWORD, ByVal lpOverlapped AS DWORD) AS LONG
                            
                                DECLARE FUNCTION closefh LIB "KERNEL32.DLL" ALIAS "CloseHandle" ( _
                                                 BYVAL hObject AS DWORD) AS LONG
                            
                            ' ------------------------------------
                            
                            FUNCTION load_file(fname$) as STRING
                            
                                LOCAL hFile as DWORD
                                LOCAL flen  as DWORD
                                LOCAL pdat  as DWORD         ' string pointer
                                LOCAL bred  as DWORD         ' bytes read variable
                            
                                hFile = open_file_A(StrPtr(fname$),&H80000000& or &H40000000&,0,0,3,&H00000080,0)
                                flen  = get_file_size(hFile,0)
                            
                                buffer$ = nul$(flen)
                                pdat = StrPtr(buffer$)
                            
                                file__read(hFile,pdat,flen,VarPtr(bred),0)
                            
                                closefh hFile
                            
                                FUNCTION = buffer$
                            
                            End FUNCTION
                            
                            ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                            
                                DECLARE FUNCTION fcreate_A LIB "KERNEL32.DLL" ALIAS "CreateFileA" ( _
                                                 ByVal lpFileName AS DWORD, _
                                                 ByVal dwDesiredAccess AS DWORD, _
                                                 ByVal dwShareMode AS DWORD, _
                                                 ByVal lpSecurityAttributes AS DWORD, _
                                                 ByVal dwCreationDisposition AS DWORD, _
                                                 ByVal dwFlagsAndAttributes AS DWORD, _
                                                 BYVAL hTemplateFile AS DWORD) AS DWORD
                            
                                DECLARE FUNCTION file__write LIB "KERNEL32.DLL" ALIAS "WriteFile" ( _
                                                 BYVAL hFile AS DWORD,ByVal lpBuffer AS DWORD, _
                                                 BYVAL nNumberOfBytesToWrite AS DWORD, _
                                                 ByVal NumberOfBytesWritten AS DWORD,ByVal lpOverlapped AS DWORD) AS DWORD
                            
                                DECLARE FUNCTION fh_close LIB "KERNEL32.DLL" ALIAS "CloseHandle" ( _
                                                 BYVAL hObject AS DWORD) AS LONG
                            
                            ' ------------------------------------------
                            
                            FUNCTION save_file(fname$,src$) as DWORD
                            
                                LOCAL hFile as DWORD
                                LOCAL pdat as DWORD         ' string pointer
                                LOCAl ldat as DWORD         ' data length
                                LOCAL bwrt as DWORD         ' bytes written variable
                            
                                hFile = fcreate_A(StrPtr(fname$),&H40000000&,0,0,2,&H00000080,0)
                            
                                pdat = StrPtr(src$)         ' get string address
                                ! mov eax, pdat
                                ! mov eax, [eax-4]          ' get string length
                                ! mov ldat, eax
                            
                                file__write(hFile,pdat,ldat,VarPtr(bwrt),0)
                            
                                fh_close hFile
                            
                                FUNCTION = bwrt
                            
                            End FUNCTION
                            
                            ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                            hutch at movsd dot com
                            The MASM Forum

                            www.masm32.com

                            Comment


                            • #54
                              Thanks Steve

                              I can follow much of that - I will spend some time understanding the rest. It all assumes that load_file reads in the whole file in some sort of controlled way, does it not? In fact, my question is 'does this load_file read in any conceivable file?
                              [I]I made a coding error once - but fortunately I fixed it before anyone noticed[/I]
                              Kerry Farmer

                              Comment


                              • #55
                                Kerry,

                                Its the "any2crlf" function that is the action, basic file IO is fine for loading the file. This is a toy for dealing with unreliable text format where it may not have standard CRLF line termination and it replaces strange or non standard combinations with a single CRLF pair so it can be processed with the normal basic functions. The two file IO functions work OK, I use them because it takes less typing and they are both fast enough.
                                hutch at movsd dot com
                                The MASM Forum

                                www.masm32.com

                                Comment


                                • #56
                                  Here is one more if you have to deal with files that have stray binary junk in them. You can either simply remove the high ascii characters OR replace each one with a space.

                                  Code:
                                  ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                  
                                      #include "\basic\include\win32api.inc"
                                  
                                  ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                  
                                   FUNCTION PBmain as LONG
                                  
                                      test$ = "1234"+chr$(205)+"5678"
                                      test$ = no_high_ascii(test$,0)
                                      StdOut "Len = "+format$(len(test$))
                                      StdOut test$+" without space replacement"
                                  
                                      test$ = "1234"+chr$(205)+"5678"
                                      test$ = no_high_ascii(test$,1)
                                      StdOut "Len = "+format$(len(test$))
                                      StdOut test$+" with space replacement"
                                  
                                      waitkey$
                                  
                                   End FUNCTION
                                  
                                  ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                  
                                   FUNCTION no_high_ascii(src$,BYVAL optn as DWORD) as STRING
                                    ' --------------------------------------
                                    ' src$ = string to strip high ascii from
                                    ' optn = optional treatment of location
                                    '        of any high ascii characters
                                    '        0 = write nothing in its place
                                    '    other = write space in its place
                                    ' --------------------------------------
                                  
                                      #REGISTER NONE
                                  
                                      LOCAL psrc as DWORD                 ' allocate a local for the string address
                                  
                                      psrc = StrPtr(src$)                 ' get the source address
                                  
                                    PREFIX "!"                            ' free yourself from the YUKKIE "!" notation
                                  
                                      mov esi, psrc                       ' load address into esi as source
                                      mov edi, psrc                       ' load same address into edi as destination
                                      sub esi, 1
                                      jmp lbl0                            ' jump into algo
                                  
                                    pre:
                                      cmp optn, 0                         ' if "optn" = 0
                                      je lbl0                             ' jump past and don't write anything in place of hi ascii
                                      mov BYTE PTR [edi], 32              ' else write a space
                                      add edi, 1                          ' then increment edi
                                    lbl0:
                                      add esi, 1
                                      movzx eax, BYTE PTR [esi]           ' zero extend byte to DWORD
                                      cmp eax, 127                        ' test if its 127 or greater
                                      jge pre                             ' jump back to "pre" if it is
                                      mov BYTE PTR [edi], al              ' write byte to destination
                                      add edi, 1                          ' increment edi
                                      test eax, eax                       ' test if last byte written is zero
                                      jnz lbl0                            ' loop back if its not
                                  
                                      sub edi, psrc                       ' sub src address from edi to get written length
                                      sub edi, 1
                                      mov psrc, edi                       ' reuse "psrc" by writing length to it
                                  
                                    END PREFIX
                                  
                                      FUNCTION = left$(src$,psrc)         ' trim string to written length
                                  
                                   End FUNCTION
                                  
                                  ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                                  hutch at movsd dot com
                                  The MASM Forum

                                  www.masm32.com

                                  Comment


                                  • #57
                                    Kerry...Welcome to my world
                                    With files full of weird characters that some languages interpret in an equally weird way
                                    or patterns that you don't fully recognise at the outset
                                    the most foolproof and adaptable approach I've found, however old-school, is to read the file as a stream of bytes
                                    through a cascading (tree-like) set of fish-traps in the code where the first byte caught arms subsequent traps and so on i.e.
                                    until either your pattern is found or failure occurs, resetting that whole section of the trap-line apart from the first trap,
                                    clearing whatever flag structures have been armed/set.

                                    I've tried other higher-level function approaches that appear to take less work until some further unforeseen complexity
                                    comes along and derails my logic.
                                    By contrast the above, more granular, approach often just needs a trap or two adding or modifying to cope
                                    i.e. it seems more resilient to change.
                                    It sounds like your already doing this by reading as binary so...Good luck.
                                    PS Hutch's solution looks spot on 'cos the only higher ascii character I have ever wanted to keep was a space of sorts (correctly identified by Stuart in a previous post if I remember right)
                                    Good luck
                                    Last edited by Dean Gwilliam; 18 Jun 2017, 04:42 PM.

                                    Comment


                                    • #58
                                      Dean

                                      Thank you for your remarks

                                      It made me think another thought.

                                      There are in fact 2 scenarios

                                      1 How do I read this specific file? I try and when I fail, I make a change and try again etc

                                      2 How do I read this type of file? I want to set up my 'read' so that it reads this file and all other similar files.

                                      [noting that no one can be sure what future files bring - so it is a plan, not a certainty]

                                      My requirement was for scenario 2
                                      [I]I made a coding error once - but fortunately I fixed it before anyone noticed[/I]
                                      Kerry Farmer

                                      Comment


                                      • #59
                                        My requirement was for scenario 2 [ "how do I read this type of file?]
                                        You start by clearly, completely and unambiguously defining the syntax rules for this type of file.

                                        Considering the thread subject says "CSV".. good luck. I've never seen a set of "clear, complete and unambiguous" syntax rules for a "comma-separated values" file.


                                        Michael Mattias
                                        Tal Systems Inc.
                                        Racine WI USA
                                        mmattias@talsystems.com
                                        http://www.talsystems.com

                                        Comment


                                        • #60
                                          Kerry,

                                          Michael is right here, about all I can suggest is that if you assume that a set number of fields are set for each line and the rest is something that you have to get a handle on to deal with the range of variation. Now if there are enough incompatible formats you have to deal with, designing something like a probe to get whatever file format is being used first would probably help but nothing beats the specs of what the file or files format is.
                                          hutch at movsd dot com
                                          The MASM Forum

                                          www.masm32.com

                                          Comment

                                          Working...
                                          X