The C/C++ Parser Generator (v. 2.x)-- Example 2 (SuperDOSEX)
Posted 04-22-2015 at 02:31 PM by rainbowsally
Updated 05-05-2015 at 03:06 AM by rainbowsally (added warning about shell expansion of wildcard chars)
Updated 05-05-2015 at 03:06 AM by rainbowsally (added warning about shell expansion of wildcard chars)
[If you have problems with super-dosex, see the notes at the bottom of this blog entry.]
This example/test produces a parser similar to old DOS wildcards.
On the way to Madalay, I met a man with GTK.
What this is all about is testing the parser for a "real" application that will take a glade output file and write the code in C/C++. How far will we get? ;-) Doesn't matter, we can have some fun along the way.
And so...
Todays Mad Science Features
Before you decide this one isn't for you, let's take a peek at what it does.
The parser lib files can be downloaded here:
http://www.linuxquestions.org/questi...-brains-36510/
file: src/common/super_dosex_str.dat
purpose: usage help strings
file: src/super-dosex.cpp
purpose: the main source file, uses parser v 2.2 or greater
If you want it, here a makefile for the last two examples.
File: Makefile.base64
purpose: source file - extract using 'base64 -d Makefile.base64 > Makefile
And here's an mc2.def file that will update whatever makefile you have to include and and compile any source files it finds in your src directory.
file: mc2.def
purpose: source file
Having problems with this one?
If you have problems with super-dosex, get the latest parser lib
http://www.linuxquestions.org/questi...-brains-36510/
and make sure your wildcards are in quotes so your shell doesn't expand them before super-dosex does.
Here's an example that (in effect) outputs the names of all the files named *.cpp in your src folder to *.cxx. Note the use of quoted strings.
It won't change the names in of the files, it just tells you what the names would be if they had been changed.
-The Computer Mad Science Team
:-)
This example/test produces a parser similar to old DOS wildcards.
On the way to Madalay, I met a man with GTK.
What this is all about is testing the parser for a "real" application that will take a glade output file and write the code in C/C++. How far will we get? ;-) Doesn't matter, we can have some fun along the way.
And so...
Todays Mad Science Features
- Uses the parser d/load to create an MSDOS-like wildcard matcher/translator
- Examples of C/C++ code that takes on the appearance and sense of a grammar
- Test and action combined in one operation
- With minor tweeks the generated parser can be used to change names of files such as "this*.abc" to "that*.xy"
Before you decide this one isn't for you, let's take a peek at what it does.
Quote:
> super-dosex examples:
super-dosex absldef ab*def wea*e
(replace text between wea-e with text between ab-def)
-------------------
Input: absldef
Filter: ab*def
Match = TRUE
Replace: wea*e
Result: weasle
> super-dosex 'hellow world' '*w w*' '* W*'
(replace text before and after "w w" with space and capital W)
-------------------
Input: hellow world
Filter: *w w*
Match = TRUE
Replace: * W*
Result: hello World
> super-dosex 'hellow world' '*w *' '*'
(discard text "w " and following text, i.e., keep only the first splat match)
-------------------
Input: hellow world
Filter: *w *
Match = TRUE
Replace: *
Result: hello
super-dosex absldef ab*def wea*e
(replace text between wea-e with text between ab-def)
-------------------
Input: absldef
Filter: ab*def
Match = TRUE
Replace: wea*e
Result: weasle
> super-dosex 'hellow world' '*w w*' '* W*'
(replace text before and after "w w" with space and capital W)
-------------------
Input: hellow world
Filter: *w w*
Match = TRUE
Replace: * W*
Result: hello World
> super-dosex 'hellow world' '*w *' '*'
(discard text "w " and following text, i.e., keep only the first splat match)
-------------------
Input: hellow world
Filter: *w *
Match = TRUE
Replace: *
Result: hello
http://www.linuxquestions.org/questi...-brains-36510/
file: src/common/super_dosex_str.dat
purpose: usage help strings
Code:
const char* usage_str = "Usage: super-dosex <input> <filter> <replace>\n" "r\n" " Determines if <input> string matches <filter> and if it does,\n" " it replaces it with the <replace> string.\n" " \n" " The <filter> and <replace> string MAY include splats and question \n" " marks which will represent text to be inserted into the matched text \n" " wherever filter had the same wildcard.\n" "\n" " For example, \n" " \n" " Input: abcdefg\n" " Filter: ab*e?g\n" " \n" " will match so the text between b and e will be saved as the first\n" " spat string and the 'f' between e and g will be saved as the first\n" " single character wildcard so that if\n" " \n" " Replace: x*y?z\n" " \n" " will receive both the splat and the single character replacements and\n" " returns\n" " \n" " Output: xcdyfz\n" "\n" " Note: The <replace> string may have fewer wildcards than the <filter>\n" " string, or none at all, but those present in the the <replace> string\n" " must occur in the same order they appear in the <filter> string.\n" " \n" " This: \n" " absldefsx ab*def?x wea*e\n" " Results in this:\n" " weasle\n" " While this:\n" " absldefsx ab*def?x wea*e?\n" " Results in this: \n" " weasles (with the 's')\n" "\n" " Up to eight wildcard chars per parse are supported in this demo.\n" " \n" ;
file: src/super-dosex.cpp
purpose: the main source file, uses parser v 2.2 or greater
Code:
// super-dosex.cpp --MSDOS-like wildcards & text translation /* See notes <somewhere> about the types cstr = constant char*; and vstr = char* mainly because... well, uh... if you need to know why, find the note or write a parser to replace them with something more to your liking. */ #include <stdio.h> #include <malloc.h> #include <string.h> #include "parser.h" #include "common/parser.cpp" // don't need a lib void dbg(){} // for a non-moving breakpoint #define streq(a, b) (strcmp(a, b) == 0) #define VERSION_MAJOR 1 #define VERSION_MINOR 0 int usage(int errcode); int print_version(); /* parser functions all exit with 'return obj.state = <whatever>;' so that both the internal state and the returned values are the same. Here's a typical parser_t function prototype. */ bool match_outstr(); // and here's one that accepts a parameter. bool match_input(cstr controlstr); int main(int argc, char** argv) { dbg(); // add a switch or hard code this if you want to // add or remove error output. #if 1 int verbose = 1; #else int verbose = 0; #endif if(argc == 2) { if(streq(argv[1], "--help")) return usage(0); else if (streq(argv[1], "--version")) return print_version(); } if(argc < 4) return usage(1); // we need a constant array of chars, null terminated for the // input buffer. cstr input = argv[1]; cstr filter = argv[2]; cstr replace = argv[3]; // The output buffer is not resizable due to the added // complexity and risks invovled in a tracking a moving // buffer if/when it resizes. So we anticipate a worst // case, which we'll "catch" if an error occurs. #define OUTLEN (1024) /* longest anticipated filename or line of text */ // We need a variable array of chars for the output buffer. vstr outbuf = (vstr)malloc(OUTLEN); // We need one global obj, but we can't use the name 'obj' anywhere // except in any new parser_t functions we may create. PARSER_OBJ o; // Set up the globals using (in this case) an OBJ created on our // stack. (It's safe here at the top level.) parser_init(&o, input, strlen(input), outbuf, OUTLEN); bool ok = true; // Example of C-like syntax for parser funcs. ok = match_input(filter) || (verbose && parse_error() && false) ; if(ok && verbose) { printf( "Input: %s\n" "Filter: %s\n" "Match = TRUE\n", input, filter ); } if(ok) { // char outstr[256]; // strcpy(outstr, obj.outbuf); parser_init(&o, replace, strlen(replace), outbuf, OUTLEN); ok = match_outstr() || (verbose && parse_error()) ; if(ok && verbose) printf("Replace: %s\n" "Result: ", replace ); // it we made it to here, we always do this printf("%s\n", obj.outbuf); } free(outbuf); return 0; } int usage(int errcode) { #include "common/super_dosex_str.dat" fprintf( errcode == 0 ? stdout : stderr, "%s", usage_str); return errcode; } //////////////////////////////////////////////////////////////// // How to deal with the input and input filter control str. // // We'll cut the text matching a wildcard to a string for // optionally pasting back into a replacement string with // the same wildcard sequence // init or reset pointer to stored wildcard data bool wildstr_reset(bool clear); // true if its is not any wildcard char bool not_wildcard(); // just copy from the input to the output and adance // control string pointer. bool copy_exact(cstr* pptr); // cut text fron imput matchaing the '?' to a string bool wildstr_cut_qmark(cstr* pcontrol_ip); // cut text matching the '*' to a string. bool wildstr_cut_splat(cstr* pcontrol_ip); // when processing the output control string in the // match_output() function , this replaces matching // wildcards with data stored during match_input(). bool wildstr_paste(); // the main input processing. bool match_input(cstr controlstr) { bool ok = true; // init the control string pointer and the wildcard // strings. static cstr errmsg = "in match_input()"; SAVE_STATIC_ERRMSG(errmsg); cstr control_ip = controlstr; wildstr_reset(true); // the main loop runs until any of the following end conditions // occur. while(ok && not_eoi() && *control_ip != 0) { // pass wildcards at the input directly to the output OR // match single char at the input with the the char at // the control string. '?' matches any char. ok = ( ( not_wildcard() && copy_exact(&control_ip) ) || wildstr_cut_qmark(&control_ip) ) || wildstr_cut_splat(&control_ip) ; } // while if(ok) RESTORE_STATIC_ERRMSG(); return obj.state = ok; } ///////////////////////////////////////////////////////////////// // restores text for control string wildcards. bool wildstr_paste(); // and this is the main output processing loopl bool match_outstr() { bool ok = true; // on this side of the operation we copy the control string // to op until we hit a wildcard replacing the text of the // wildcard with that recorded in the wildstrings. static cstr errmsg = "in match_output()"; SAVE_STATIC_ERRMSG(errmsg); wildstr_reset(false); // don't clear while(ok && not_eoi()) { UPDATE_STATIC_ERRMSG(); ok = ( not_wildcard() && copy_1() ) || wildstr_paste() ; } if(ok) RESTORE_STATIC_ERRMSG(); return obj.state = ok; } // the parser lib has a function 'copy_to(str)' that can // be used to load the output buffer easily, but it requires // the end-delimiting text. This function gets that text. // The delims are not the delimiting text, but in this app // they will be the list of wildcars chars that will mark // the end of the delimiting text. This is used to find // the end mark of wildcard text to cut to a wildstr. static bool get_delimstr(vstr dest, cstr cip, cstr delims) { bool ok = true; // advance past '*' char cstr src = cip + 1; int n = strlen(delims); int searchlen = strlen(cip); int wildlen = -1; // find first occurance of any wildcard char. for(int end = 0; wildlen == -1 && end < searchlen; end++) { for(int i = 0; i < n; i++) { if(src[end] == delims[i]) { wildlen = end; break; } // if } // for i } // for end // the control string has a wildcard delimiter if(wildlen >= 0) { for(int i = 0; i < wildlen; i++) dest[i] = src[i]; dest[wildlen] = 0; // terminate } else // the control string is not wildcard delimited strcpy(dest, src); return obj.state = ok; } // initializes pointer to obj.op for cutting. bool mark_wildstr(); // cuts and pastes string with wildcard prefix // for matching replacement wildcards. bool cut_wildstr(char wildcard); // save and restore wildcard string storage strings #define SAVE_WILDSTR() \ shortstr* _sv_SAVE_WILDSTR = wildstr_ndx #define RESTORE_WILDSTR() \ wildstr_ndx = _sv_SAVE_WILDSTR typedef struct { char str[256]; }shortstr; static shortstr wildstr_array[16]; static shortstr* wildstr; static int wildstr_ndx = 0; static vstr wildstr_op = 0; bool is_wildcard() { bool ok = not_eoi() && strchr("?*", *obj.ip) ; return obj.state = ok; } bool not_wildcard() { bool ok = not_eoi() && ! is_wildcard(); return obj.state = ok; } bool wildstr_paste() { bool ok = false; char c = *obj.ip; cstr p = wildstr_array[wildstr_ndx].str; if(p[0] == c) { // attempt to write the located string ok = write_str(p+1) && skip_1() ; wildstr_ndx++; } return obj.state = ok; } bool wildstr_reset(bool clear) { wildstr = wildstr_array; wildstr_ndx = 0; if(clear) memset(wildstr_array, 0, sizeof(wildstr_array)); return obj.state = true; } bool mark_wildstr() { wildstr_op = obj.op; return obj.state = true; } bool cut_wildstr(char wildcard) { vstr p = wildstr[wildstr_ndx].str; *p++ = wildcard; strcpy(p, wildstr_op); wildstr_ndx++; // cut from output buffer obj.op = wildstr_op; * obj.op = 0; return obj.state = true; } bool wildstr_reset(bool clear); bool mark_wildstr(); bool mark_wildstr(); bool cut_wildstr(char wildcard); static bool get_delimstr(vstr dest, cstr cip, cstr delims); bool not_wildcard(); bool wildstr_paste(); bool advance_ptr(cstr* pptr); bool copy_exact(cstr* pptr) { cstr ptr = *pptr; bool ok = (*obj.ip == *ptr) && copy_1() && advance_ptr(pptr) ; return obj.state = ok; } bool wildstr_cut_qmark(cstr* pcip) { cstr cip = *pcip; bool ok = (*cip == '?') && mark_wildstr() && copy_1() && cut_wildstr('?') && advance_ptr(pcip); ; return obj.state = ok; } bool advance_ptr(cstr* pptr) { (*pptr)++; return obj.state; // presumably true } bool wildstr_cut_splat(cstr* pcontrol_ip) { cstr cip = *pcontrol_ip; char tempstr[256]; bool ok = true; ok = false; // unless... if(*cip == '*') { // if * is the last control char in the string copy input to the end if(cip[1] == 0) { // AND is last_ctrl_char() ok = // AND copy_splat_string() mark_wildstr() && do_while(copy_1) && cut_wildstr('*') ; } // else copy up until the next string delimited by null, *, or ? else // OR { // cut_splat_substring() ok = get_delimstr(tempstr, cip, "?*") && mark_wildstr() && copy_to(tempstr) // from ip to op until tempstr && cut_wildstr('*'); ; if(ok) cip++; } // strchr } if(ok) advance_ptr(pcontrol_ip); return obj.state = ok; }
File: Makefile.base64
purpose: source file - extract using 'base64 -d Makefile.base64 > Makefile
Code:
IyMgTWFrZWZpbGUgY3JlYXRlZCB3aXRoIG1ha2VmaWxlIGNyZWF0b3IgJ21jMicgdiAzLjIuMAoK IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIwojIyBOb3RlOiBUaGUgZm9sbG93aW5nIHNlY3Rpb24gY2FuIGJlIHB1dCBpbnRvIGEg J21jMi5kZWYnIGFuZCAKIyMgbW9kaWZpZWQgZm9yIGF1dG9tYXRpYyBvdmVycmlkZSBvZiBkZWZh dWx0cyBhcyBuZWVkZWQuCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMgVmFyaWFibGUgRGVmaW5pdGlvbnMg U2VjdGlvbgoKIyMgVXNlciBEZWZpbmVkIFZhcnMKClBSRUZJWCA9ICQoSE9NRSkvdXNyCkJVSUxE RElSIDo9ICQoUFdEKQpFWFRfQUxMID0gTWFrZWZpbGUKIyMgVGhlIG91dHB1dCBmaWxlIG5hbWUg bm90IGluY2x1ZGluZyBwYXRoCk9VVE5BTUUgPSBNVUxUSQoKIyMgVGhlIGRpcmVjdG9yaWVzIGZv ciBzb3VyY2VzLCAodGVtcCkgb2JqZWN0cywgYW5kIGJpbmFyeSBvdXRwdXQocykKQklORElSID0g LgpTUkNESVIgPSBzcmMKT0JKRElSID0gbwoKIyMgV2hhdCBDT01QSUxFIHNob3VsZCBkby4KQ09N UElMRSA9IGcrKyAtYyAtbwpDRkxBR1MgPSAtV2FsbCAtV25vLWNvbW1lbnQgLWczCklOQ0xVREUg PSAtSSAkKFNSQ0RJUikgLUkuIC1JIC91c3IvaW5jbHVkZQoKIyMgV2hhdCBMSU5LIHNob3VsZCBk by4KTElOSyA9IGcrKyAtbwpMREZMQUdTID0gCkxJQiA9IC1ML3Vzci9saWIgLUwkKFBSRUZJWCkv bGliCgojIyBNT0RJRlkgQkVMT1cgVEhJUyBMSU5FIFdJVEggR1JFQVQgQ0FSRQojIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMj IEZpbGUgTGlzdHMgU2VjdGlvbgoKIyMgVGhlIGZ1bGwgcGF0aCB0byB0aGUgb3V0cHV0IGZpbGUK TUFJTiA9ICQoTUFJTl9GSUxFUykKClNSQyA9IFwKICBzcmMvc3VwZXItZG9zZXguY3BwIFwKICBz cmMvdG8tY2FtZWwuY3BwIFwKICAjIyMjIyMjIyMjIyMjCgpIRFIgPSBcCiAgc3JjL3BhcnNlci5o IFwKICAjIyMjIyMjIyMjIyMjCgpPQkogPSBcCiAgby9zdXBlci1kb3NleC5vIFwKICBvL3RvLWNh bWVsLm8gXAogICMjIyMjIyMjIyMjIyMKCk1BSU5fRklMRVMgPSBcCiAgLi9zdXBlci1kb3NleCBc CiAgLi90by1jYW1lbCBcCiAgIyMjIyMjIyMjIyMjIwoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyBSdWxlcyBTZWN0aW9u CgphbGw6ICQoRVhUX0FMTCkgJChNQUlOKSAkKEhEUikgJChTUkMpCgokKEJJTkRJUikvc3VwZXIt ZG9zZXg6ICQoT0JKRElSKS9zdXBlci1kb3NleC5vCglAZWNobwoJQGVjaG8gIkxpbmtpbmcgc3Vw ZXItZG9zZXgiCgkkKExJTkspICQoQklORElSKS9zdXBlci1kb3NleCAkKE9CSkRJUikvc3VwZXIt ZG9zZXgubyAkKExERkxBR1MpICQoTElCKQoJJChQT1NUKQoKJChPQkpESVIpL3N1cGVyLWRvc2V4 Lm86ICQoU1JDRElSKS9zdXBlci1kb3NleC5jcHAgJChIRFIpCglAZWNobwoJQGVjaG8gIkNvbXBp bGluZyBzdXBlci1kb3NleCIKCSQoQ09NUElMRSkgJChPQkpESVIpL3N1cGVyLWRvc2V4Lm8gJChT UkNESVIpL3N1cGVyLWRvc2V4LmNwcCAkKENGTEFHUykgJChJTkNMVURFKQoKJChCSU5ESVIpL3Rv LWNhbWVsOiAkKE9CSkRJUikvdG8tY2FtZWwubwoJQGVjaG8KCUBlY2hvICJMaW5raW5nIHRvLWNh bWVsIgoJJChMSU5LKSAkKEJJTkRJUikvdG8tY2FtZWwgJChPQkpESVIpL3RvLWNhbWVsLm8gJChM REZMQUdTKSAkKExJQikKCSQoUE9TVCkKCiQoT0JKRElSKS90by1jYW1lbC5vOiAkKFNSQ0RJUikv dG8tY2FtZWwuY3BwICQoSERSKQoJQGVjaG8KCUBlY2hvICJDb21waWxpbmcgdG8tY2FtZWwiCgkk KENPTVBJTEUpICQoT0JKRElSKS90by1jYW1lbC5vICQoU1JDRElSKS90by1jYW1lbC5jcHAgJChD RkxBR1MpICQoSU5DTFVERSkKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMgQWRkaXRpb25hbCBUYXJnZXRzCgp1cGRhdGU6 ICQoRVhUX1VQREFURSkKCUBtYzIgLXVwZGF0ZQoKIyBleGFtcGxlIHRhcmdldHMKI21jMi1zZW1p Y2xlYW46ICQoRVhUX1NFTUlDTEVBTikKIwlAcm0gLWYgKn4gKi8qfiAqLyovKn4KCiNtYzItY2xl YW46ICQoRVhUX0NMRUFOKQojCUBybSAtZiAkKE1BSU4pCiMJQHJtIC1mICQoT0JKKQojCUBybSAt ZiAqfiAqLyp+ICovKi8qfiAqLyovKi8qfgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIFVzZXIgRGVmaW5lZCBUYXJnZXRz CgoKTWFrZWZpbGU6IG1jMi5kZWYKCUBtYzIgLXUKCUBzbGVlcCAyCgpzZW1pY2xlYW46ICQoRVhU X1NFTUlDTEVBTikKCUBybSAtZiAkKE9CSikKCUBybSAtZiAqfiAqLyp+ICovKi8qfiAqLyovKi8q fgoJQHJtIC1mICoua2RldmVsb3AuZmlsZWxpc3QgICoua2RldmVsb3AucGNzICAqLmtkZXZzZXMg RG94eWZpbGUKCnN0cmlwOgoJQHN0cmlwICQoTUFJTl9GSUxFUykKCUBtYWtlIHNlbWljbGVhbgoK Y2xlYW46ICQoRVhUX0NMRUFOKQoJQHJtIC1mICQoTUFJTl9GSUxFUykKCUBybSAtZiAkKE9CSikK CUBybSAtZiAqLmtkZXZlbG9wLnBjcyAqLmtkZXZzZXMKCUBybSAtZiAqfiAqLyp+ICovKi8qfiAq LyovKi8qfiB0bXAubWFrCgpmb3JjZTogIyB1c2VkIHRvIGZvcmNlIGV4ZWN1dGlvbgoKIAojIyMj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjCiAK
And here's an mc2.def file that will update whatever makefile you have to include and and compile any source files it finds in your src directory.
file: mc2.def
purpose: source file
Code:
# mc2.def template created with Makefile Creator 'mc2' # sandbox path and other new variables PREFIX = $(HOME)/usr BUILDDIR := $(PWD) OUTNAME = MULTI EXT_ALL = Makefile SRCDIR = src OBJDIR = o BINDIR = . # what COMPILE should do COMPILE = g++ -c -o # COMPILE <output_file> ... CFLAGS = -Wall -Wno-comment -g3 # debug # CFLAGS = -Wall -O2 # optimized INCLUDE = -I $(SRCDIR) -I. -I /usr/include # what LINK should do LINK = g++ -o # LINK <output_file> ... LDFLAGS = LIB = -L/usr/lib -L$(PREFIX)/lib Makefile: mc2.def @mc2 -u @sleep 2 semiclean: $(EXT_SEMICLEAN) @rm -f $(OBJ) @rm -f *~ */*~ */*/*~ */*/*/*~ @rm -f *.kdevelop.filelist *.kdevelop.pcs *.kdevses Doxyfile strip: @strip $(MAIN_FILES) @make semiclean clean: $(EXT_CLEAN) @rm -f $(MAIN_FILES) @rm -f $(OBJ) @rm -f *.kdevelop.pcs *.kdevses @rm -f *~ */*~ */*/*~ */*/*/*~ tmp.mak force: # used to force execution
If you have problems with super-dosex, get the latest parser lib
http://www.linuxquestions.org/questi...-brains-36510/
and make sure your wildcards are in quotes so your shell doesn't expand them before super-dosex does.
Here's an example that (in effect) outputs the names of all the files named *.cpp in your src folder to *.cxx. Note the use of quoted strings.
Code:
for i in src/*.*; do super-dosex $i "*.cpp" "*.cxx" done
-The Computer Mad Science Team
:-)
Total Comments 0