Simple C example for beginners and bug fix for libLQ-qt version 3.0.x
Posted 01-13-2013 at 06:57 PM by rainbowsally
Simple C example for beginners and bug fix for libLQ-qt version 3.0.x
[v.3.0 (mc2 and libLQ) will no longer be the current version(s) but it still works and we have a bug fix here that applies to all 3.0.x versions.]
Today's feature:
While 'canonicalize_file_name()' is great for paths that don't have macros in them, and for dereferencing symlinks, this expands macros and doesn't dereference the links.
There was at least one bug in the 3.0 lib version, this doubles as a bug fix. Just pop it into the libLQ src folder and 'make install'.
Here's the file. It itself has no dependenices on the lib so this might be a good one for folks just starting out in C or C++.
file: src/filename_absolute.cpp
purpose: source file
Here's a tester for it. See if you can fool it. Note that "..this_file..txt" (note the dots) IS a valid file name for a file in the current directory, but it will be a hidden file, of course.
file: src/main.cpp
purpose: source file
Here's some makefile definitions, if you want to create a makefile with mc2. Type mc2 -init, then after that just 'make update' if you add or remove files from the build.
file: mc2.def
purpose: makefile definitions
Here's the last of the 3.0 series mc2 uploads.
http://www.linuxquestions.org/questi...support-34783/
And here's some stuff I checked. You can run this as 'sh testit.txt'. It's assumed that the output file is simply named main.
file: testit.txt
purpose: avoid excessive typing
The Computer Mad Science Team
:-)
[v.3.0 (mc2 and libLQ) will no longer be the current version(s) but it still works and we have a bug fix here that applies to all 3.0.x versions.]
Today's feature:
- A simple C/C++ example.
- A converter from relative paths to absolute.
- A bug fix for the libLQ-qt/mc2 3.0 d/load.
While 'canonicalize_file_name()' is great for paths that don't have macros in them, and for dereferencing symlinks, this expands macros and doesn't dereference the links.
There was at least one bug in the 3.0 lib version, this doubles as a bug fix. Just pop it into the libLQ src folder and 'make install'.
Here's the file. It itself has no dependenices on the lib so this might be a good one for folks just starting out in C or C++.
file: src/filename_absolute.cpp
purpose: source file
Code:
// Simple C -- translate paths to canonical form with or without macros. #include <sys/types.h> // probably not needed here #include <stdlib.h> // getenv() #include <string.h> // str*() #include <stdio.h> // sprintf() static char* find_double_dot_path(char* p); static char* find_dot_path(char* p); bool filename_absolute(char* buf, size_t buflen, const char* filename) { //int maxlen = strlen(getenv("HOME")); //maxlen = MAX(strlen(getenv("PWD"), maxlen); //maxlen += 256; // bail if null pointer if(!filename) { *buf = 0; return false; } char absname[1024]; // overkill, we hope, though linux allows 2K paths // init string printer var char* p = absname; *p = 0; int changed; //////////////////////////////////////////// // prefixes -- these are OR-ed changed = 0; // expand ~ if(strstr(filename, "~/") == filename) { p += sprintf(absname, "%s", getenv("HOME")); filename ++; changed++; } // expand ../ if(!changed && (strstr(filename, "..") == filename)) { char* updir = strrchr(getenv("PWD"), '/'); if(updir) { p += sprintf(absname, "%s", getenv("PWD")); // delete the updir p -= strlen(updir); filename +=2; changed++; } // else leave this broken. Can't have a ../ above root } // expand ./ if(!changed && (strstr(filename, ".") == filename)) { p += sprintf(absname, "%s", getenv("PWD")); filename ++; changed++; } // no prefix and not pointing to '/', so it must be in the current directory if(!changed && (*filename != '/')) p += sprintf(absname, "%s/", getenv("PWD")); ///////////////////////////////////////////////////// // get the rest of the path loaded into absname for // cleanup cycle p += sprintf(p, "%s", filename); ////////////////////////////////////////////////////// // now go through absname and remove unnecessary stuff changed = 1; while(changed) { // loop until stays unchanged changed = 0; // remove all .. p = absname; for(;;) { char* e = find_double_dot_path(p); if(e) { // strip previous part of path and the double dots *e = 0; p = strrchr(p, '/'); if(!p) { *e = '/'; break; // no p } strcpy(p, e + 3); changed++; } else // no e break; } // .. // remove all . p = absname; for(;;) { p = find_dot_path(p); if(!p) break; // step to '.' and copy from next char to here. // this may create a double '//' if it's not at // the end of a path but we'll get all those in // a sec. p++; strcpy(p, p + 1); changed++; } // . // reduce redundant // to to / p = absname; for(;;) { p = strstr(p, "//"); if(!p) break; strcpy(p, p + 1); changed++; } // . } // while changed if(buflen <= strlen(absname)) { *buf = 0; return false; // buffer too short } // else strcpy(buf, absname); return true; } static char* find_double_dot_path(char* p) { if(!p) return 0; // between path parts char* found = strstr(p, "/../"); if(found) return found; // else at end found = strstr(p, "/.."); if(found && !found[3]) return found; else return 0; } static char* find_dot_path(char* p) { if(!p) return 0; // between path parts char* found = strstr(p, "/./"); if(found) return found; // else at end found = strstr(p, "/."); if(!p[2]) return found; else return 0; }
Here's a tester for it. See if you can fool it. Note that "..this_file..txt" (note the dots) IS a valid file name for a file in the current directory, but it will be a hidden file, of course.
file: src/main.cpp
purpose: source file
Code:
// Usage: Input the path you want to check #include <stdio.h> #include <malloc.h> #include <string.h> #include <stdbool.h> // if you try this in straight C void dbg(){} extern bool filename_absolute(char* buf, size_t buflen, const char* filename); int usage(int errocode); int main(int argc, char *argv[]) { dbg(); if(argc != 2) return usage(1); char buf[256]; size_t buflen = 256; const char* filename = argv[1]; if(!filename_absolute(buf, buflen, filename)) { printf("Failed to get absolute file name for\n'%s'", filename); return 1; } else { printf( "In : '%s'\n" "Out : '%s'\n\n", filename, buf ); } } int usage(int errcode) { printf( "Usage:\n No, no, no, no...\n" " All wrong, you got it, young Skywalker\n" " You must use the source\n" ":-)\n\n"); return errcode; }
Here's some makefile definitions, if you want to create a makefile with mc2. Type mc2 -init, then after that just 'make update' if you add or remove files from the build.
file: mc2.def
purpose: makefile definitions
Code:
OUTNAME = main SRCDIR = src OBJDIR = o BINDIR = . # compile function overrides COMPILE = g++ -m32 -c -o # COMPILE <output_file> ... # CFLAGS = -Wall -g3 # debug CFLAGS = -Wall -O2 # optimized INCLUDE = -I $(SRCDIR) -I /usr/include # link function overrides LINK = g++ -m32 -o # LINK <output_file> ... LDFLAGS = LIB = -L/usr/lib clean: @rm -f $(MAIN) @rm -f $(OBJ) @rm -f *~ */*~ */*/*~ */*/*/*~
http://www.linuxquestions.org/questi...support-34783/
And here's some stuff I checked. You can run this as 'sh testit.txt'. It's assumed that the output file is simply named main.
file: testit.txt
purpose: avoid excessive typing
Code:
echo "Testing some paths with the filename_absolute routine." echo main "." main ".." main "./filename" main "../filename" main "../.." main "needs/pwd/prefix" main "~/needs/HOME/prefix" main "./needs/pwd/(dot)/prefix" main "../needs/pwd-1/prefix" main "/needs/some/../double/.and/./single/dot/../dots/./removed/here/.." main "/checking/..valid/...but/.crazy/./or/hidden/../../names"
:-)
Total Comments 0