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
[email protected]
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]