Package: dc Version: 1.06.94-3 Severity: wishlist Tags: patch I would like dc to be able to do some simple string manipulation and file i/o. I'm attaching a patch that adds the & (concatenate string), @ (split string into characters), and w (manipulate a file, 'wo' for open, for example) operations. I have also documented these changes in the man page and texinfo page.
Hope it helps! -- System Information: Debian Release: squeeze/sid APT prefers testing-proposed-updates APT policy: (500, 'testing-proposed-updates'), (500, 'testing') Architecture: i386 (i686) Kernel: Linux 2.6.26-2-686 (SMP w/2 CPU cores) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Versions of packages dc depends on: ii libc6 2.9-4 GNU C Library: Shared libraries dc recommends no packages. dc suggests no packages. -- no debconf information *** /home/jakykong/dc.diff diff -Naur dc2/bc-1.06.94/dc/dc-proto.h dc/bc-1.06.94/dc/dc-proto.h --- dc2/bc-1.06.94/dc/dc-proto.h 2005-05-25 14:13:20.000000000 -0700 +++ dc/bc-1.06.94/dc/dc-proto.h 2009-04-20 18:29:47.000000000 -0700 @@ -77,6 +77,7 @@ extern dc_data dc_getnum DC_PROTO((int (*)(void), int, int *)); extern dc_data dc_int2data DC_PROTO((int)); extern dc_data dc_makestring DC_PROTO((const char *, size_t)); +extern dc_data dc_catstring DC_PROTO((dc_str, dc_str)); extern dc_data dc_readstring DC_PROTO((FILE *, int , int)); extern int dc_add DC_PROTO((dc_num, dc_num, int, dc_num *)); diff -Naur dc2/bc-1.06.94/dc/eval.c dc/bc-1.06.94/dc/eval.c --- dc2/bc-1.06.94/dc/eval.c 2006-06-04 04:04:40.000000000 -0700 +++ dc/bc-1.06.94/dc/eval.c 2009-04-21 09:16:02.000000000 -0700 @@ -90,6 +90,10 @@ */ static int input_pushback; +/* Use for the file manipulation characters g, h, j, m, and t + */ +static FILE *manip_fil_fp=0; + /* passed as an argument to dc_getnum */ static int input_fil DC_DECLVOID() @@ -513,6 +517,87 @@ dc_push(dc_array_get(peekc, tmpint)); } return DC_EATONE; +/* NOTE: adds string concatenation and split to dc */ + case '&': /* concatenate top two elements of stack as strings */ + if(dc_pop(&datum) == DC_SUCCESS) { + dc_data datum2; + if(dc_pop(&datum2) == DC_SUCCESS) { + if(datum.dc_type == DC_STRING && datum2.dc_type == DC_STRING) { + /* concatenate the strings */ + dc_push(dc_catstring(datum2.v.string, datum.v.string)); + } + } + } + else + return DC_FAIL; + break; + case '@': /* split top element of stack into individual characters and push each onto another stack. */ + if (peekc == EOF) + return DC_EOF_ERROR; + if (dc_pop(&datum) == DC_SUCCESS && datum.dc_type == DC_STRING) + for(tmpint = 0; tmpint < dc_strlen(datum.v.string); tmpint++) { + dc_array_set(peekc, tmpint, + dc_makestring( &dc_str2charp(datum.v.string)[tmpint], 1)); + } + else + fprintf(stderr, + "%s: top of stack must be string.\n", + progname); + return DC_EATONE; +/* NOTE: adds file open/close read/write to dc, sortof. */ + case 'w': /* do file manipulations. Just 'F' for compactness. */ + switch (peekc) + { + case 'o': /* open file */ + if(dc_pop(&datum) == DC_SUCCESS){ + if( datum.dc_type == DC_STRING) { + puts(dc_str2charp(datum.v.string)); + (manip_fil_fp = fopen( dc_str2charp(datum.v.string), "r+" )) || + (manip_fil_fp = fopen( dc_str2charp(datum.v.string), "w+")); + if( !manip_fil_fp ) + fprintf(stderr, "%s: error opening file\n", progname); + } + } + break; + case 'c': /* close file */ + fclose(manip_fil_fp); + break; + case 'r': /* read byte, move 1 forward */ + tmpint = fgetc(manip_fil_fp); + if( tmpint == EOF ) + dc_push(dc_int2data(-1)); + else + dc_push(dc_int2data(tmpint)); + break; + case 'w': /* write byte, move 1 forward */ + if(dc_pop(&datum) == DC_SUCCESS) { + if (datum.dc_type == DC_STRING) { + fputs(dc_str2charp(datum.v.string), manip_fil_fp); + } + if (datum.dc_type == DC_NUMBER) { + tmpint = dc_num2int(datum.v.number, DC_TOSS); + if(fputc(tmpint, manip_fil_fp) == EOF) + fprintf(stderr, "%s: write error\n", progname); + } + } + break; + case 'j': /* jump to byte number at top of stack */ + if(dc_pop(&datum) == DC_SUCCESS && datum.dc_type == DC_NUMBER) { + if (fseek(manip_fil_fp, dc_num2int(datum.v.number, DC_TOSS), SEEK_SET)) + fprintf(stderr, "%s: seek error\n",progname); + } + break; + case 's': /* what byte number are we at? */ + dc_push(dc_int2data(ftell(manip_fil_fp))); + break; + case EOF: + return DC_EOF_ERROR; + default: + fprintf(stderr, "%s: unknown file command: %c\n", progname, peekc); + break; + + } + return DC_EATONE; default: /* What did that user mean? */ fprintf(stderr, "%s: ", progname); diff -Naur dc2/bc-1.06.94/dc/string.c dc/bc-1.06.94/dc/string.c --- dc2/bc-1.06.94/dc/string.c 2006-03-29 05:08:25.000000000 -0800 +++ dc/bc-1.06.94/dc/string.c 2009-04-20 18:37:15.000000000 -0700 @@ -128,6 +128,28 @@ return result; } +dc_data +dc_catstring DC_DECLARG((s1,s2)) + const dc_str s1 DC_DECLSEP + const dc_str s2 DC_DECLEND +{ + dc_data result; + struct dc_string *string; + char *s = dc_malloc(s1->s_len + s2->s_len + 1); + + strcpy(s,s1->s_ptr); /* concatenate the strings */ + strcat(s,s2->s_ptr); + + string = dc_malloc(sizeof *string); + string->s_ptr = s; + string->s_len = s1->s_len + s2->s_len; + string->s_refs = 1; + result.v.string = string; + result.dc_type = DC_STRING; + + return result; +} + /* read a dc_str value from FILE *fp; * if ldelim == rdelim, then read until a ldelim char or EOF is reached; * if ldelim != rdelim, then read until a matching rdelim for the diff -Naur dc2/bc-1.06.94/doc/dc.1 dc/bc-1.06.94/doc/dc.1 --- dc2/bc-1.06.94/doc/dc.1 2006-04-29 02:05:36.000000000 -0700 +++ dc/bc-1.06.94/doc/dc.1 2009-04-21 09:37:23.000000000 -0700 @@ -328,9 +328,9 @@ \*(Dc has a limited ability to operate on strings as well as on numbers; the only things you can do with strings are -print them and execute them as macros +print, execute them as macros (which means that the contents of the string are processed as -\*(dc commands). +\*(dc commands), concatenate them, and split them into their constituent characters. All registers and the stack can hold strings, and \*(dc always knows whether any given object is a string or a number. Some commands such as arithmetic operations demand numbers @@ -388,6 +388,19 @@ .B lax invokes this macro. .TP +.B & +Concatenates the top two items on the stack (if they are strings), +in the order in which they were pushed. For example, +.B [Hello,][World]& +produces the string +.B [Hello,World] +.TP +.BI @r +Splits a string into its constituent characters and stores them in +array +.I r +. The original string is popped off the stack. +.TP .BI > r Pops two values off the stack and compares them assuming they are numbers, diff -Naur dc2/bc-1.06.94/doc/dc.info dc/bc-1.06.94/doc/dc.info --- dc2/bc-1.06.94/doc/dc.info 2006-06-09 10:05:15.000000000 -0700 +++ dc/bc-1.06.94/doc/dc.info 2009-04-21 09:54:02.000000000 -0700 @@ -322,14 +322,15 @@ ********* `dc' has a limited ability to operate on strings as well as on numbers; -the only things you can do with strings are print them and execute them +the only things you can do with strings are print them, execute them as macros (which means that the contents of the string are processed as -`dc' commands). Both registers and the stack can hold strings, and -`dc' always knows whether any given object is a string or a number. -Some commands such as arithmetic operations demand numbers as arguments -and print errors if given strings. Other commands can accept either a -number or a string; for example, the `p' command can accept either and -prints the object according to its type. +`dc' commands), concatenate them, and split them. Both registers and +the stack can hold strings, and `dc' always knows whether any given +object is a string or a number. Some commands such as arithmetic +operations demand numbers as arguments and print errors if given strings. +Other commands can accept either a number or a string; for example, the +`p' command can accept either and prints the object according to its +type. `[CHARACTERS]' Makes a string containing CHARACTERS and pushes it on the stack. @@ -355,6 +356,15 @@ Macros are most often stored in registers; `[1p]sa' stores a macro to print `1' into register `a', and `lax' invokes the macro. +`&' + Concatenates the top two items on the stack (if they are strings), + in the order in which they were pushed. For example, `[Hello,][World]&' + produces the string `[Hello,World]'. + +...@r' + Splits a string into its constituent characters and stores them in + array `r'. + `>R' Pops two values off the stack and compares them assuming they are numbers, executing the contents of register R as a macro if the @@ -451,6 +461,13 @@ associated with it. Thus `1 0:A 0SA 2 0:A LA 0;Ap' will print 1, because the 2 was stored in an instance of 0:A that was later popped. +`wR' + Performs file operations. `wo' opens the file, `wc' closes the file, + `wr' reads a byte, `ww' writes a byte or string, `wj' seeks in the + file, and `ws' tells in the file. Only one file is available to be + open or closed. If EOF is encountered, -1 is pushed onto the stack. + Note that this just treats a file as a stream of bytes. That should + work fine for a text file, but may not work well for anything else. File: dc.info, Node: Reporting bugs, Prev: Miscellaneous, Up: Top diff -Naur dc2/bc-1.06.94/doc/dc.texi dc/bc-1.06.94/doc/dc.texi --- dc2/bc-1.06.94/doc/dc.texi 2006-06-04 13:44:18.000000000 -0700 +++ dc/bc-1.06.94/doc/dc.texi 2009-04-21 09:56:02.000000000 -0700 @@ -412,10 +412,9 @@ @command{dc} has a limited ability to operate on strings as well as on numbers; -the only things you can do with strings are print them -and execute them as macros +the only things you can do with strings are print them, execute them as macros (which means that the contents of the string are processed -as @command{dc} commands). +as @command{dc} commands), concatenate them, and split them. Both registers and the stack can hold strings, and @command{dc} always knows whether any given object is a string or a number. @@ -454,6 +453,14 @@ @samp{[1p]sa} stores a macro to print @samp{1} into register @samp{a}, and @samp{lax} invokes the macro. +...@item & +Concatenates the top two items on the stack (if they are strings), in +the order in which they were pushed. For example, @samp{[Hello,][World]&} +produces the string @samp{[Hello,World]}. + +...@item \@@var{r} +Splits a string into its constituent characters and stores them in array r. + @item >@var{r} Pops two values off the stack and compares them assuming they are numbers, @@ -563,6 +570,14 @@ will print 1, because the 2 was stored in an instance of @var{0:a} that was later popped. +...@item w...@var{r} +Performs file operations. @samp{`wo'} opens the file, @samp{`wc'} closes the file, +...@samp{`wr'} reads a byte, @samp{`ww'} writes a byte or string, @samp{`wj'} seeks in the +file, and @samp{`ws'} tells in the file. Only one file is available to be +open or closed. If EOF is encountered, -1 is pushed onto the stack. +Note that this just treats a file as a stream of bytes. That should +work fine for a text file, but may not work well for anything else. + @node Reporting bugs, , Miscellaneous, Top @chapter Reporting bugs -- Sincerely, Jack Mudge jakyk...@theanythingbox.com -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org