Thread: Multi file source to single file source

  1. #1
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544

    Multi file source to single file source

    Has anyone got a script to turn a multi-file C source into a single file? Just asking, before I reinvent the wheel.

    - Remove duplicate #defines
    - Remove duplicate #includes
    - Remove comments

    Thanks.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Not sure what you mean by 'remove' duplicates?

    gcc -E prog.c
    This removes comments, expands includes and replaces #defines

    gcc -MM prog.c
    This outputs a list of header files which prog.c depends on.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    It's full of stars adrianxw's Avatar
    Join Date
    Aug 2001
    Posts
    4,829
    Don't see why anyone would want to do such a thing.
    Wave upon wave of demented avengers march cheerfully out of obscurity unto the dream.

  4. #4
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    I have a library, which of course, is split into multiple modules. For simplicity of use and distribution I want to make it available as a single source file.

    For example, if we have:

    Code:
    - File 1:
    
    #define UNICODE
    #include <windows.h>
    #include <stdio.h>
    
    void function(void) {
        /* Some comment */
        some code;
    }
    
    - File 2:
    
    #define UNICODE
    #include <windows.h>
    #include <something.h>
    
    void function2(int i) {
       while(i++) < 10000 printf("hello");
       /* another comment */
    }
    Then I want this as the result (all in one file):
    Code:
    #define UNICODE
    #include <windows.h>
    #include <stdio.h>
    #include <something.h>
    
    void function(void) {
        some code;
    }
    
    void function2(int i) {
       while(i++) < 10000 printf("hello");
    }
    Note: duplicate includes and defines gone, comments gone and all in one file.

    Salem:
    Thanks for the ideas but I don't wish to expand includes or resolve defines.

    I have made some progress on a rough script.

  5. #5
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    No worries, I got a script working. It's not exactly elegant or robust but it seems to do what I need.

    Code:
    Option Explicit
    Dim fso
    
    Call WScript.Quit( main() )
    
    
    ' Returns the entire contents of a text file
    '''
    Function ReadFile(sFilePath)
    
    	Const ForReading = 1, AsciiFormat = 0
    	Dim TextStream
    
    	Set TextStream = fso.OpenTextFile(sFilePath, ForReading, False, AsciiFormat)
    	ReadFile = TextStream.ReadAll()
    	TextStream.Close
    
    End Function
    
    ' Writes sContents to the specified file.
    '''
    Sub WriteFile(sFilePath, sContents)
    
    	Const ForWriting = 2, AsciiFormat = 0
    	Dim TextStream
    
    	Set TextStream = fso.OpenTextFile(sFilePath, ForWriting, True, AsciiFormat)
    	TextStream.Write sContents
    	TextStream.Close
    End Sub
    
    ' Relocates all #includes and #defines to the beginning
    ' of the source and removes duplicates.
    '''
    Function PreProcess(sOldSource)
    
    	Dim sNewSource, sTokens, sLine
    	Dim i, rgsLines, rgsArray
    	Dim dctTokens
    
    	Set dctTokens = CreateObject("Scripting.Dictionary")
    
    	rgsLines = Split(sOldSource, vbcrlf, -1, 0)
    
    	For i = LBound(rgsLines) To UBound(rgsLines)
    
    		sLine = Replace(rgsLines(i), " ", "")
    		sLine = Replace(rgsLines(i), vbTab, "")
    
    		If ( Left(sLine, Len("#include")) = "#include" Or _
    		     Left(sLine, Len("#define"))  = "#define" ) Then
    
    			if (Not dctTokens.Exists(rgsLines(i))) Then dctTokens.Add rgsLines(i), 0
    		Else
    			sNewSource = sNewSource & rgsLines(i) & vbcrlf
    		End If
    	Next
    
    	rgsArray = dctTokens.Keys
    
    	For i = LBound(rgsArray) To UBound(rgsArray)
    		sTokens = sTokens & rgsArray(i) & vbcrlf
    	Next
    
    	PreProcess = sTokens & sNewSource
    
    End Function
    
    ' Removes comments from the source
    '''
    Function RemoveComments(sOldSource)
    	Dim sNewSource, regEx
    
    	Set regEx = CreateObject("VBScript.RegExp")
    	regEx.Global = True
    	regEx.IgnoreCase = True
    
    	' Deal with /* */ comments that have a line to themselves.
    	regEx.Pattern = "\r\n[\t ]*/\*(.|[\r\n])*?\*/[\t ]*\r\n"
    	sNewSource = regEx.Replace(sOldSource, vbcrlf)
    
    	' Deal with /* */ comments that share the line.
    	regEx.Pattern = "/\*(.|[\r\n])*?\*/"
    	sNewSource = regEx.Replace(sNewSource, "")
    
    	' Deal with // comments that have a line to themselves.
    	regEx.Pattern = "\r\n[\t ]*//[^\r]*\r\n"
    	sNewSource = regEx.Replace(sNewSource, 	vbcrlf)
    
    	' Deal with // comments that share a line
    	regEx.Pattern = "//[^\r]*"
    	sNewSource = regEx.Replace(sNewSource, 	"")
    
    	' Remove double white lines
    	regEx.Pattern = "\r\n[\t \r\n]*\r\n"
    	sNewSource = regEx.Replace(sNewSource, vbcrlf & vbcrlf)
    
    	' Remove line ending white space
    	regEx.Pattern = "[\t ]*\r\n"
    	sNewSource = regEx.Replace(sNewSource, vbcrlf)
    
    	RemoveComments = sNewSource
    
    End Function
    
    
    Function main()
    
    	Const EXIT_SUCCESS = 0, EXIT_FAILURE = 1
    	Dim sArg, sSource, sOldSource, sNewSource
    
    	Set fso = CreateObject("Scripting.FileSystemObject")
    
    	For Each sArg In WScript.Arguments
    		sOldSource = sOldSource & vbCrLf & "@@@<<@@ ----- " & _
    		             fso.GetFileName(sArg) & " ----- @@>>@@@" & _
    		             vbCrLf & ReadFile(sArg)
    	Next
    
    	sNewSource = PreProcess(sOldSource)
    	sNewSource = RemoveComments(sNewSource)
    	sNewSource = Replace(sNewSource, "@@@<<@@", "/*")
    	sNewSource = Replace(sNewSource, "@@>>@@@", "*/")
    
    	Call WriteFile("output.c", sNewSource)
    
    	main = EXIT_SUCCESS
    End Function
    If anyone actually uses this:
    - You'll probably want to specify the filenames in an array so you can decide on order.
    - It is possible that the board has stuffed up some of the regular expressions.
    - There are many things it doesn't handle - such as multi line defines.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Formatting a text file...
    By dagorsul in forum C Programming
    Replies: 12
    Last Post: 05-02-2008, 03:53 AM
  2. Need Help Fixing My C Program. Deals with File I/O
    By Matus in forum C Programming
    Replies: 7
    Last Post: 04-29-2008, 07:51 PM
  3. gcc link external library
    By spank in forum C Programming
    Replies: 6
    Last Post: 08-08-2007, 03:44 PM
  4. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  5. archive format
    By Nor in forum A Brief History of Cprogramming.com
    Replies: 0
    Last Post: 08-05-2003, 07:01 PM