Volenteer wanted to compile C code

Discussion in 'Mac Programming' started by ReesAcheson, Dec 31, 2014.

  1. ReesAcheson macrumors newbie

    Joined:
    Dec 31, 2014
    #1
    I have a small utility that I use under Linux that I would like to make available on my wife's Mac (running 10.8.5, Moutain Lion). I am looking for someone to compile it for me. It is only 170 lines long and uses only stdio.h, stdlib.h & string.h and so should present no problems.

    I tried to install XCode to enable then installing a C compiler, but the installation crashed her computer and I had to reinstall the OS and the backup. I do not want to try it again - I'm still in the dog house from the last attempt.

    Any volenteers? If so, please recommend how to get the code to you. Email? Post it here? What?

    Thanks,
    Rees
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    Post the code here, using CODE tags.

    170 lines probably won't hit any post-size limits, and it lets potential volunteers see it first.
     
  3. ReesAcheson thread starter macrumors newbie

    Joined:
    Dec 31, 2014
    #3
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /* Program to read text from a file or from stdin, buffering text and searching for a string.
       When 2 CRs are found (a paragraph) if a match was found in it the buffer is 
       printed to stdout.  The buffer is cleared and reading contuned.
       The effect is to print the entire paragraph if it contains a match.
     */
    
    FILE	*intext;
    typedef char bufstr[0x7fff];	//32k buffer
    typedef char shortstr[63];
    typedef char filenamestr[255];
    
    bufstr buffer;
    int bufpos;
    
    shortstr	srchst, SRCHST; 
    char		Ch, LastCh;
    char		t;
    filenamestr	filename;
    int		Found, ReadFromStdIn, i, BufOverflow;
    int		SrchIndex;
    int 		ShowFn;  /*If ShowFn then display Fn before displaying lines  */
    
    
    void AddCh (char c) {
      if (bufpos < sizeof(buffer)-2) {
        buffer[bufpos] = c;
        bufpos ++;
        buffer[bufpos] = 0;
        }
      else {
          BufOverflow = 1;
        printf ("buffer full, program terminated\n");
      }
    }
    
    void ClearBuf () {
      bufpos = 0;
      buffer[bufpos] = 0;
    }
    
    void PrintBuf () {
      printf("%s", buffer);
      printf("\n");
    }
    
    
    void stupper(char *str) {			/* string uppercase, usage: stupper(srchst); */
    	int i;							/*this uppercases the original */
    	for (i = 0; str[i]; i++) 
    		str[ i ] = toupper( str[ i ] );
    }
    
    void stlower(char *str) {			/* string lowercase, usage: stlower(srchst); */
    	int i;							/*this lowercases the original */
    	for (i = 0; str[i]; i++) 
    		str[ i ] = tolower( str[ i ] );
    }
    
    
    
    void syntax(char *prog) {			/* this does work (call syntax(srchst) */
    	printf("Syntax: cat filename | %s [-f] [-h] srchst\n", prog);
    	printf("  filename is piped into %s.  Paragraphs that contain srchst\n", prog);
    	printf("  are printed.  srch is not case sensitive.\n");
    	printf("  Use double quotes around multi-word srearch phrases.\n");
    	printf("Or,");
    	printf("Syntax: %s srchst filename\n", prog);
    	printf("  -h  Help\n");
    	printf("  -f  Display filename of files that contain srchst\n");
    }
    
    
    /* ********************************************************* */
    
    
    
    int main ( int argc, char *argv[] ) {
    
      int i, stlen;
      BufOverflow = 0;
      ShowFn = 0;  	/*  Set this to 1 if filename is to be displayed, 0 otherwise */
    //  FnContains = 0;
      ReadFromStdIn = 1;
      filenamestr	argument;
      int args, ArgNum;
      ArgNum = 0;
      args=argc;	
    
      if (argc == 1) { 			 /*Should be > 1; argc[1] = argv[0] is programname */
        strncpy(filename, argv[0], sizeof(filename)-1);  //copy programname to srchst for syntax to use
        syntax(filename);
        return 1;			//Exit with error 1
      }
    
      for (i = 1; i < args; i++) {
        strncpy(argument, argv[i], sizeof(argument)-1);
        if (argument[0] == '-') {
    	    /* printf("we have a hyphen\n"); */
          switch (argument[1]) {
            case 'h': strncpy(filename, argv[0], sizeof(filename)-1); 
                      syntax(filename);	
                      return 1;
                      break;
            case 'f': ShowFn = 1; 	
                      break;
             default: printf("Unrecognized switch %c\n", argument[1]); 
                      break;
          }	//switch
        }		//if
        else {
          ArgNum ++;
          switch (ArgNum) {
            case 1: strncpy(srchst, argument, sizeof(srchst)-1); break;
            case 2: strncpy(filename, argument, sizeof(filename)-1);
                    ReadFromStdIn = 0; break;
           default: printf("Too many Arguments\n"); break;
          }	//switch
        }	//else
       } // for
    
      strcpy(SRCHST, srchst);
      stupper(SRCHST);			//The uppercase search string
      stlower(srchst);			//The lowercase one
    
      if (ReadFromStdIn == 0) { 
        intext=fopen(filename,"r");		/* open filename for reading */	
      }
      else {
        intext=fopen("/dev/stdin","r");	/* open stdin for reading */	  
      }
        /* printf("reading in file...\n");*/
      if(intext == NULL) 		   					/* did it open? */
        printf ("unable to open file");
      else {		//OK, let's do it
        Found = 0;
        LastCh = 0;
        Ch = 0;
        Found = 0;
        SrchIndex=0;
        do   {
          if (Ch != ' ')		/*Do not count a line of spaces as a line of text*/
            LastCh = Ch;
          Ch = fgetc(intext);
          if( feof(intext) )
            break ;
          if (Ch == '\n' && LastCh == '\n')  {   //if 2 CRs in a row
          /*    printf("New Paragraph\n"); */
            if (Found == 1)	//If anything found the the Paragraph, then print it
              PrintBuf();
            ClearBuf();
            Found = 0;
          }
          else  {		//not 2 CRs so add the ch to buffer
            AddCh(Ch);
            if (! Found) {	//If we already have a match, no need to look again
              if ( srchst[SrchIndex] == '?' || 		//Wild card?
                        Ch == srchst[SrchIndex] || 		//lowercase match?
                        Ch == SRCHST[SrchIndex])  { 		//uppercase match?
                 SrchIndex ++;				//check next character
                 if (srchst[SrchIndex] == 0)  {	/* if end of srchst, we have a match */
                   SrchIndex = 0;			//reset for next test
                   Found = 1;
                   //printf("bingo!"); 
                 }
              }
              else	//No match
                SrchIndex = 0;
              }
            }
        } while (! BufOverflow);	//do; an exit is provided with break at feof
      }			//else, do it
      if (Found == 1)	//If a match still pending then print it
        PrintBuf();
      ClearBuf();
      fclose(intext);
    }	//main
    
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    Compiled as x86_64 executable on 10.8.5 Mountain Lion. Attached as zip file.

    Source file was named "ach.c". Command line was:
    Code:
    make ach
    
    Output produced from compile:
    Code:
    cc     ach.c   -o ach
    ach.c:54:14: warning: implicit declaration of function 'toupper' is invalid in C99
          [-Wimplicit-function-declaration]
                    str[ i ] = toupper( str[ i ] );
                               ^
    ach.c:60:14: warning: implicit declaration of function 'tolower' is invalid in C99
          [-Wimplicit-function-declaration]
                    str[ i ] = tolower( str[ i ] );
                               ^
    2 warnings generated.
    
    I leave the testing to you.

    Happy New Year!
     

    Attached Files:

    • ach.zip
      File size:
      3 KB
      Views:
      22
  5. Senor Cuete macrumors regular

    Joined:
    Nov 9, 2011
    #5
    #include <ctype.h>

    You should #include the header file <ctype.h>. This will get rid of the compiler warnings. This shouldn't compile without it. Maybe you have something set different than I do but with my XCode, I couldn't compile this code without it.
     
  6. ReesAcheson thread starter macrumors newbie

    Joined:
    Dec 31, 2014
    #6
    Thank you so much. It works when fed a filename but not with stdin. Perhaps this has to do with Senor Cuete's point about missing #include <ctype.h>, although the warnings you posted don't seem to point to stdin not working.

    Could you please try it again with the <ctype.h> addition? If need be, I could use it as is, but I would rather pipe in the input text. Thank you very much for your efforts so far.

    Rees.
     
  7. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #7
    Will do.

    Could you post some sample input and expected output, so I have a decent test case? Again, use code tags around the data so it preserves all the spacing.
     
  8. ReesAcheson thread starter macrumors newbie

    Joined:
    Dec 31, 2014
    #8
    Code:
     echo "To announce that there must be no criticism of the President or that we are to stand by the President, right or wrong, is not only unpatriotic and servile, it is morally treasonable to the American Public.   President Theodore 
    Roosevelt" |greph moral
    If excecuted on the command line, the above should print the quote to the screen. Changing the search string at the end to something like "morak" should produce no output.

    By the way, Happy New Year!

    Rees
     
  9. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #9
    Here's the one with ctype.h included.

    Source changed to:
    Code:
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    ...no other changes...
    It was built the same way: at the command-line with 'make' and its default build rule.


    Tested on my 10.8.5 MacBook Pro, both the new and old versions had the same output for the given sample inputs. That is,
    Code:
    echo ..blahblah.. | ./greph morak
    did NOT produce any output text (the expected result).

    Here's all the tests I ran. The file 'grin' was made using the 'echo' command with output redirected to 'grin'.
    Code:
    mine:grephing me$  echo "To announce that there must be no criticism of the President or that we are to stand by the President, right or wrong, is not only unpatriotic and servile, it is morally treasonable to the American Public.   President Theodore Roosevelt" | ./greph moral
    To announce that there must be no criticism of the President or that we are to stand by the President, right or wrong, is not only unpatriotic and servile, it is morally treasonable to the American Public.   President Theodore Roosevelt
    
    mine:grephing me$ 
    mine:grephing me$  echo "To announce that there must be no criticism of the President or that we are to stand by the President, right or wrong, is not only unpatriotic and servile, it is morally treasonable to the American Public.   President Theodore Roosevelt" | ./greph morak
    mine:grephing me$ 
    
    mine:grephing me$ 
    mine:grephing me$ cat grin | ./greph moral
    To announce that there must be no criticism of the President or that we are to stand by the President, right or wrong, is not only unpatriotic and servile, it is morally treasonable to the American Public.   President Theodore Roosevelt
    
    mine:grephing me$ 
    mine:grephing me$ cat grin | ./greph morak
    mine:grephing me$ 
    mine:grephing me$ ./greph moral <grin
    To announce that there must be no criticism of the President or that we are to stand by the President, right or wrong, is not only unpatriotic and servile, it is morally treasonable to the American Public.   President Theodore Roosevelt
    
    mine:grephing me$ 
    mine:grephing me$ ./greph morak <grin
    mine:grephing me$ 
    mine:grephing me$ ./greph moral grin
    To announce that there must be no criticism of the President or that we are to stand by the President, right or wrong, is not only unpatriotic and servile, it is morally treasonable to the American Public.   President Theodore Roosevelt
    
    mine:grephing me$ 
    mine:grephing me$ ./greph morak grin
    mine:grephing me$ 
    

    For the following command, run on the old and new versions, the output is as shown.
    Old:
    Code:
    nm greph | grep lower
    0000000100001550 T _stlower
                     U _tolower
    
    New:
    Code:
    nm greph | grep lower
                     U ___tolower
    00000001000014e0 T _stlower
    0000000100001540 t _tolower
    
    The ctype.h file defines tolower() as a macro and/or inline func that eventually leads to __tolower(), the symbol marked as U above. In this context, a U symbol will mean a function residing in a library. Lower-case means the symbol is "static" (non-extern).


    If you want to examine any unexpected behavior, I think you'll need a simplified test-case focusing exclusively on the functions at issue, and specific input and output data.
     
  10. ReesAcheson thread starter macrumors newbie

    Joined:
    Dec 31, 2014
    #10
    chown33,

    The new version with the included ctype.h seems to produce the desired output for each of the various type of inputs you tested. And you tested all that I can think of.

    Your explanation of the nm object list:
    appears to indicate how ctype.h solves the problem, but I am sorry to say that I did not follow it all the way to how the difference of reading from a file or from piping or redirection effects it. I would like to know the anwer to that, but I initially asked for a volunteer, which I spelled correctly this time - I did not ask for your additional effort at debugging, which I very much thank you for. I am a bit uncomfortable asking for that explanation.

    Now, unless I missed it, I think you forgot to attach the executable. I assume it is now fixed, I have not been able to try it yet here,

    Rees
     
  11. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #11
    Somehow the attachment didn't upload, and with all the other stuff in the post, I failed to notice.

    Should be here this time.
     

    Attached Files:

  12. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #12
    I didn't compile with Xcode. I used 'make' and Terminal, as shown in the earlier post.

    I have the Xcode command line tools installed on this MBPro, but not Xcode itself.

    For reference, the C compiler that 'make' runs is this:
    Code:
    [B]cc --version[/B]
    Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
    Target: x86_64-apple-darwin12.5.0
    Thread model: posix
    
     
  13. ReesAcheson thread starter macrumors newbie

    Joined:
    Dec 31, 2014
    #13
    Got it. And it works just fine. Thank you. I've been trying to compile this for her for about two months. Thank you, thank you.

    Rees
     
  14. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #14
    I'm glad it's working, and glad to help.
     
  15. iSee macrumors 68040

    iSee

    Joined:
    Oct 25, 2004
    #15
    Social ad hoc distributed build system... cool
     
  16. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #16
    With a very low turnaround rate and no authentication, if those are acceptable tradeoffs.


    There ought to be some kind of smiley on that, but in a "Ha ha, only serious" way.
     
  17. uwbadger macrumors member

    Joined:
    May 20, 2009
    #17
    Yeah, while I'm glad you were able to help out the OP, I'd strongly discourage this sort of thing. OP: don't run random executables from people on the internet. It would have been trivial for chown33 to add a persistent backdoor to the code, or to make it delete files, or....
     
  18. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #18
    To be honest, I agree with you.

    One reason I didn't reply with any comments about trustworthiness or authenticity is because the OP said he came from Linux. It was also clear to me he'd been programming for a while. If he'd been a complete noob I likely wouldn't have replied at all, or would have launched the "Are you sure you understand all the security implications?" conversation.

    I might also have suggested rewriting the utility in an interpreted language that OS X has by default, such as python, perl, or awk. These are installed by default (I'm pretty sure), and they're interpreted so no compilation needed.
     
  19. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #19
    Reading the 'description' of the problem makes it seem like it could have been done in any language with regex, and possibly even pure bash with pipes into grep etc. "for free"
     
  20. Anitramane macrumors 6502

    Joined:
    Dec 23, 2013
    #20
    I would try doing compiling over the command line if xcode fails to install.
     
  21. moonman239 macrumors 68000

    Joined:
    Mar 27, 2009
    #21
    You don't need to install a C compiler if you install Xcode. Xcode comes with one: LLVM.

    Edit: But I'm glad you got help. Thank you, chown!


    ----------

    I think the C compiler installation caused the error, not the Xcode installation. Xcode comes from the App store, so it's very unlikely its installation caused the crash.
     
  22. blaster_boy macrumors 6502

    blaster_boy

    Joined:
    Jan 31, 2004
    Location:
    Belgium
    #22
    I got interested in this and rewrote it in Python. Put it up on Github (wee! my very first Github commit!) for all the world to see, and probably comment on how bad the code is :eek: :

    https://github.com/Lexstok/Search-s...-display-corresponding-paragraphs/tree/master
     

Share This Page