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

Reply via email to