Jump to content
IGNORED

Glorious People's small c compiler


dhe

Recommended Posts

 

I recently re-setup Vern Jensen's c99 Starter Kit on Classic99, and though I'd put my notes here.

 

The starting article can be found here:

http://ftp.whtech.com/magazines/micropendium/mp961112.pdf

   -- isn't ftp.whtech.com a great resources? Many sites have come and gone, but this one has been around forever!

 

Software you will need:
  • Vern L. Jensens StarterKit - https://ftp.whtech.com/programming/c99/StarterKit/
  • Get all of the files:
             Size     Name of Archive File
         120,704               c99ccfwb.ark
           51,072                c99docs.ark
           34,688                  c99libs.ark
           04,576                 c99prog.ark
             1,152                 c99readme
            55,936                c99utils.ark 
 
Classic99 Setup Notes:
A few tricks I use with Classic99, of course we live in America, so you can also HIYW. I have a folder called classic99_vm\ under there I have directories with configured environments  like c99, rxb, tp99, fortran99
   classic99_vm\c99
                       \tp99
                       \rxb {etc}
 
   The default for Classic99 is having a bunch of directories off the root of classic99 like DSK1, DSK2, DSK3. I prefer to make a subdirectory called mydisks, then I create directories in lower case dsk1 .. dsk6.  This scheme keeps you from potentially having any upgrades write in to your disk file directories, also it's easy enough to copy mydisks and past them some place else as a backup.
 
     When I go to do a full backup, I just copy the Classic99_vm folder (under everything under it) to a USB sticker and rename it with the data.
 
     Let's start Classic99 and point the disks setup to the six directories you just made. Make sure you can catalog each without error.
 
      Shutdown Classic99.
 
Let's take a quick look at the readme from 1999.
 
"README
 
These five archive files represent the content of the five
disk in Vernon Jensens c99 starter kit.
 
These disk were originally offered as a companion for a series of tutorials
on c99 the Vernon wrote for Micropendium.
 
1. Funnelweb + c99 compiler               c99ccfwb@
2. c99 Programs                           c99prog@
3. c99 Utils by Bruce Harrison            c99utils@
4. c99 Libraries                          c99libs@
5. c99 Documentation                      c99docs@
 
Each archive file can unarc to a diskette with 720 free sectors, ie.
ds/sd or ss/dd. They were originally distributed in ds/sd format.
 
Warning: The document files are in a combination of formats, runoff
         and TI Writer Formatter.
 
Dan H. Eicher  <== still kicking.
03.29.1999
eicher@delphi.com <== Email address deader then a door nail.
 
Copy the files where your going to need/use them:
--------------------------------------------------------------
Start up ti99dir. (say a silent thanks to Fred).
Go to where you stashed the Starterkit Files.
     Put the contents of c99ccfwb.ark in to mydisks\dsk1\
     Put the contents of both c99libs.ark and c99utils.ark in mydisks\dsk2\
      Well put aside dsk3. for our source code.
      Well put aside dsk5 compiling to assembler, and compiling from assembler to object.
      dsk6 we can utilize for utilities - like I like to have dm2k on hand.
         maybe put in here some rxb utilitiy programs that help you in your programming.
-------------------------------------------
 

While the versions of the docs are for c99 Ver4, the c99 compiler was upgraded by Winfried Winkler and displays REV# 5.1.FW

 

You can let Vern's articles walk you from here, just remember, he was constrained by most people having only two drives, with Classic99 we can have as many as we want...

 
 
 
  • Like 5
Link to comment
Share on other sites

From Vern Jensen's Starter Kit:

"cleardot.gifIf, after quitting the c99 program, your computer locks up, it is because the c99 program was loaded "on top" of Funnelweb in memory and, therefore, when the TI tried to return to the Funnelweb program, it locked up. This won't happen if you load the c99 program from the Editor/Assembler cartridge, because the E/A program is kept on the cartridge, not in RAM, and therefore can't be overwritten. This isn't terribly important because most programs don't have a "Quit" option anyway; they simply force you to reset your computer when you want to stop the program."

 

Would it be reasonably possible, with assembler, to dump SRAM and 32K out to SAMS card, run Tom Bently's loader, run c99 program, then as a last assembly routine, copy everything back in place begin execution at the fweb menu screen - or are there two many variable like gpws, cpu status registers to make that viable?

 

- or would a better approach be -

 

Since running this on a pc, a more productive approach, figure out how to make Tom Bentley's C-Loader run automatically on restart of Classic99 and keep another window open with the Funnelweb Menu?

Link to comment
Share on other sites

  • 3 weeks later...

My current dev environment is open two copies of Classic99. In one open Freds Editor. In the 2nd copy funnelweb as configured in the starter pack. The c compiler will eat your source if you accidentally type output for input. So I keep a copy in memory so when that happens the day is saved, by just saving back out the source.

 

Does anyone have the source code to either c99 R4 by Clint or 5.1 by Winfried Winkler? Those would be very helpful to have. Supposedly each of these where available for the cost of a disk.

 

Last question for the night, did funnelweb ever make it back in to a compile-able form?

 

Other tricks - F7 pulls up QD Quick and dirty? directory manager, which is handy and sometimes if there is a problem with your compile, using the funnelweb editor you can pull up the assembler source and track the problem down.  I have a program that lists some examples and questions I will be putting up.

 

TI's documents where very liberal with examples, the c99 docs not so much.

 

Next challenge is a bit of file I/O - then I'll work up to the wall I hit in TP99 - doing a diskette directory.

 

If anyone has Clint's phone, I'd be happy to call him. PM me please.

Link to comment
Share on other sites

Yea, Lee appreciate your pointing out that resource. I'd seen it, and I'm hoping to learn to craw in c99 before I walk.

One of the quirks of c99 I'm getting adjusted to, is that the c compiler, almost always compiles.

It's when you go to the assembly process you get problems and have to look in to the assembler source.

 

Also, getting used to the fact, assembler comes with a manual, forth comes with a manual.

c99 comes with some programmer notes and a wish of good luck! ?

 

  • Like 3
Link to comment
Share on other sites

I've been stitching up some example programs in to working examples. I've found just like old floppies that experience bit rot, how-to articles suffer bit route and need correcting either because of versioning issues or printing issues. Here are the examples I've gotten working so far.

 

The biggest quirk I couldn't figure out was the switch function. I could not get the function to execute, until I assigned a variable to the function.. ODD...

 

DSK3.HELLO;L  /* THE LOADER FOR THE CODE */
DSK4.HELLO;O
DSK2.CSUP
DSK2.PRINTF
DSK2.GRF1
#include "DSK2.STDIO"
#include "DSK2.GRF1;H"
/* includes are dv */
 
extern printf();
/* extern are df - must be loaded */
 
#define FALSE 0
#define TRUE 1
/* sometimes true is def as !FALSE */
 
int num;       /* used for pointer test */
int a;         /* dumby variable */
int *p1;       /* pointer must be char or int types */
char Ain[10];  /* buffer to hold input */
int x,y;
 
main()
{
  int c;     /* compiler angered if vars not defined at begining */
 
  num=10;    /* only avaiable to main, not functions */
  x=2;
  y=19;
 
  puts("\nHello World\n\n");
 
/* display values in decimal, oct and hex */
  printf(">Print value of num different ways< \n");
  printf("Num in Dec is: %d \n", num);
  printf("Num in Oct is: %o \n", num);
  printf("Num in Hex is: %x \n", num);
  Fwait();
 
/* define values */
  printf(">Display defined values< \n");
  printf("def Value of FALSE is: %d \n",FALSE);
  printf("def Value of  TRUE is: %d \n",TRUE);
  Fwait();
 
/* call a function */
  c=Fadd(5,2);   /* call dan made function */
  printf(">Call a function to add 5 and 2< \n");
  printf("Result of add fct: %d \n",c);
  Fwait();
 
/* keyboard input */
  printf(">Get keyboard input< \n");
  printf("Hello. What's your name? \n");
  a=gets(Ain);
  puts("Nice to meet you: ");
  printf("%s \n",Ain);
  Fwait();
 
/* pointer */
  printf(">Pointer Examples< \n");
  printf("Address of var num: %d \n", &num);
  p1 = &num;   /* load memory address of num in p1 */
  printf("var num has a value of: %d \n",*p1);
     /*  give me the value at this memory address */
 
  printf("Value X,Y  %d, %d \n",x,y);
  a=Fswitch(&x,&y);
  printf("After switch.. \n");
  printf("Value X,Y  %d, %d \n",x,y);
  Fwait();
 
/* graphics and text */
  text();
  printf(">Text Mode Example< \n");
  printf("01234567890123456789001234567890123456789 \n");
  Fwait();
 
  grf1();
  printf(">Graphics 1 Mode Examples< \n");
  printf("01234567890123456789001234567890123456789 \n");
  Fwait();
 
 
  exit(0);
}
 
Fadd(n1,n2)
int n1, n2;
{
  int sum;
 
  sum=n1+n2;
  return(sum);
}
 
Fswitch(n1,n2)
int *n1,*n2;
{
  int temp;
 
  temp=*n1;
  *n1=*n2;
  *n2=temp;
}
 
Fwait()
{
  printf("Press any key to continue. \n\n");
  a=getchar();  /* wait to end */
}
 
/* dhe L.D.O.M. 12/21/2021 */
 
/* need to figure out puts/twrite/display */
/* because we are using twos compliment for decimal rep
   we get back negative numbers */
/* Doesn't look like fprint respect %x vs %X */
/* puts doesn't accept format specs like %s */
 
/* 12/20/2021
   Odd quirk Fadd works, Fswitch didn't.
   the only diff c=fadd(); vs fswitch
   after adding an c=fswitch(); then it was
   actually called
 
   To keep sane, make sure you have a line between
   int x,y,z and then next line of code */
 
/* naming conventions
    starts with:
    A  Array Ain[] = array input
    F  Function Fwait = a wait funtion
*/

 

Link to comment
Share on other sites

In February 1986 - Tom Bentley release TCIO for file I/O.

In November 1986 - Clint Pulley released version 4 of his c99 compiler - and it included fscanf.

 

Is anyone here familiar enough with the two libraries to list the advantages/dis-advantages of each?

Link to comment
Share on other sites

I know it doesn't matter too much if you're just programming for fun, but be warned that c99's syntax is /really/ obsolete and it will teach you bad habits that will make moving to gcc or anything more modern a little harder. I know this, because that's the path I took and the battles I fought. ;) It's a good compiler, but it's really really dated.

 

The code it generates is also very naive - this is mentioned in the manual. There's little to no optimization. According to the docs, even stuff like "A=4+1;" is compiled as adding 4 to 1, and storing it in A. So your assembly code will be much larger than with an optimizing compiler. It's almost more of a translator.

 

Quote

main()

I recommend specifying return types - that's one of the rules that got stricter in modern c. It will save you lots of fixups if you ever port your code forward. Good time to learn that habit. ;)

 

Quote

  int c;     /* compiler angered if vars not defined at begining */

That's a requirement of C. It wasn't loosened until C99, IIRC (the 1999 spec, not c99 ;) ), and even then there are limits.

 

Quote

Fadd(n1,n2)
int n1, n2;

This is the original K&R syntax, and you've probably noticed it's completely gone from modern code. ;) You don't have any choice, just be aware of it... the types are now declared inline with the function declaration instead of after it.

 

The issue commented with Fswitch() is interesting, but when you don't declare a return type, it's assumed to be int. Perhaps declaring the function as "void Fswitch(n1, n2)" would fix it... 

 

I can't help with the libs. I did a lot of c99 but I didn't get the libraries back then ;)

 

  • Like 4
  • Thanks 1
Link to comment
Share on other sites

I have been working on moving off TCIO - which Vern Jensen did a good job documented, to fscanf - which came out in R4 of c99.

Vern mentions he was learning the new system, with the help of Dr. Donald L Mahler of the BCS.

 

After a good bit of trial and error, I hit this little snag.

 

image.png.7e1ea024b83e6bdc956e67bcbf21ca67.png

 

Now, where in the heck is that routine?

 

I think I might have found it, but it was using a sledgehammer to find it...

 

root@DESKTOP-TTA01OD:/mnt/d/classic99_vms/c99/mydisks/dsk2# strings  -f -- * | grep ASCAN
FSCANF: VASCAN 4
SCANF: 0ASCAN F                                                    :       99/4 AS                                                             00413
SSCANF: PASCAN F                                                             :       99/4 AS                                                             0011MOV @CARG,8

 

I think I need to load scanf, even though, I'm not directly using it.

 

For now, I'm in search of as many BCS articles by Dr. Mahler as I can find.

Fortunately, his articles, are around 88/89/90 - so he would have been using the latest libraries, and not referencing limitations of prior libraries.

  • Like 1
Link to comment
Share on other sites

Another one of the better writers on c99 was Dr. Donald L. Mahler (dlm) here is some of his stuff I found on whtech - what and where:


 

BCS / Dr. Donald L Mahler (dlm)

Often times, in his programs, you’ll see modified from Chirlian. I’ll save you the google.

  Paul M. Chirlian - Introduction to C.

8703 - Nada

8704 - FWB & C99 and how to create a program image.

8707 - Two dimensional array with strcmp and index of earlier columns.

8804 - Version 4, scanf, printf

8806 - Nothing from dlm

8808 - tips for using c99 on the geneve, full updated VJ program scanf, printf, fprintf

8809 - strlen ex. Warren Agee, fix for VJ sort program, and update changing base program

8810 - Nothing from dlm

8811 - A calculating benchmark in c99 - to compare to a similar UCSD program

8901 - Array’s of pointers and pointer arithmetics

8902 - Duplicate of article in 8901

8903 - Exponent test and find the ph value

8904 - Nada by dlm

8905 - Release of c99MDOS and 70 page manual, example of volume of box, scanf and sprintf examples - MDOS environment.

8906 - nothing from dlm - JPH gone, after JPH graduated the local content of the newsletter decreased dramatically.

8908 - volume of a sphere writing in c99 with old libs, Vern Jensen’s lib and new TIC libs.

8909 - Demo of graphic functions available in tic (c99mdos) - using prior volume of sphere

9004 - nothing from dlm

9005 - nothing from dlm

900607 - using multiplan by dlm - no c99 content.

9008 - nothing from dlm

901011 - nothing from dlm

9102 - nothing from dlm

9103 - nothing from dlm

910405 - nothing from dlm

910708 - nothing from dlm

9109 - nothing from dlm - fweb 4.4 released

9112 - nothing from dlm - BT’s CAN - Cottage Archiving and Networking.

9202 - nothing from dlm


 

 Note: Lot’s of good P-System information in this newsletter by Ron Williams.

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

After looking through whtech and the cyc, I couldn't find an example of fscanf, unfortunately, by the time Clint released version 4 and Winfried released version 5.1, most of the columnist had moved on. So the example code we are left with mainly revolves around the TCIO library.

 

After perseverance, I did manage to get fscanf going, and here is the example. One trick I didn't know about, or had forgotten, was being able to right or left justify a field using printf.

 

GRADE;L

DSK3.GRADE;O
DSK2.CSUP
DSK2.PRINTF
DSK2.GRF1
DSK2.FSCANF
DSK2.CFIO
DSK2.SCANF

GRADE;C

#include "DSK2.STDIO"
#include "DSK2.GRF1;H"
/* includes are dv */
 
extern printf(),fprintf(),scanf(),fscanf();
/* extern are df - must be loaded */
 
#define FALSE 0
#define TRUE 1
/* sometimes true is def as !FALSE */
 
char a;        /* used by Fwait sub */
int num;
 
int reccnt;    /* holds number of records read */
int grdtot;    /* total of all grades */
int grdavg;    /* used to hold simple average */
 
int filptr;
char buff[81];
 
main()
{
  char fname[10];
  int  fgrade;
 
  reccnt=0;
  grdtot=0;
 
  text();
  clear();
 
 
  filptr=fopen("DSK3.GRADE;D","r");
/*  printf("file pointer:  %d \n", &filptr); */
 
  if (filptr==NULL) {
    printf("no such file");
    return(0);
  }
 
  printf(">File IO Example< \n\n");
  printf("Student     Grade \n\n");
 
  while (!feof(filptr)) {
    fscanf(filptr,"%s %d",fname, &fgrade);
    printf("%-10s   ", fname);
    printf("%3d \n", fgrade);
    reccnt++;
    grdtot=grdtot+fgrade;
  }
 
  printf("\n");
  grdavg=grdtot/reccnt;   /* get a simple average */
  printf("Average Grade: %d \n\n",grdavg);
 
  Fwait();
  exit(0);
 
  Fwait();
}   /* end of main */
 
Fadd(n1,n2)
int n1, n2;
{
  int sum;
 
  sum=n1+n2;
  return(sum);
}
 
Fswitch(n1,n2)
int *n1,*n2;
{
  int temp;
 
  temp=*n1;
  *n1=*n2;
  *n2=temp;
}
 
Fwait()
{
  printf("Press any key to continue. \n\n");
  a=getchar();  /* wait to end */
}
 
/* dhe L.D.O.M. 01/05/2022 */
 
/* need to figure out puts/twrite/display */
/* because we are using twos compliment for decimal rep
   we get back negative numbers */
/* Doesn't look like fprint respect %x vs %X */
/* puts doesn't accept format specs like %s */
 
/* other formatting things....  printf
    %10d - will pad a field to 10 chars, your text on the right
    %10d - will pad to the right, your chars on the right
       printf doesn't respect \t   */
 
/* NULL already define, compiler unhappy if
   you try to define it */
 
/* 12/20/2021
   Odd quirk Fadd works, Fswitch didn't.
   the only diff c=fadd(); vs fswitch
   after adding an c=fswitch(); then it was
   actually called
 
   To keep sane, make sure you have a line between
   int x,y,z and then next line of code */
 
/* naming conventions
    starts with:
    A  Array Ain[] = array input
    F  Function Fwait = a wait funtion
*/
 
/* 12/23/2021
   great swap from tcio to console i/o functions
   fopen is contained in CFIO library
   only ref so far - 6:1:16 trials of a c beginner
    points to articles by Dr. Donald I Mahler of the BCS
*/
 

 

GRADE;D

DAN    100
SALLY  70
BOB    43
KIM    97

 

The run:

image.png.d3b1237255405a3c1a15423e23ba0f5f.png

  • Like 1
Link to comment
Share on other sites

Very good sleuthing by you.

 

It took me a second to understand that this meant. Looks strange. :) 

 

#include "DSK2.GRF1;H"

I use a comma in these cases now. Semi-colon is burned too hard into my brain as the end of the something. :) 

 

I remember Small C generating working code but tending to be not overly efficient. 

Is C99 a "regular" Small implementation from what you see or is there some optimization going on?

 

  • Like 1
Link to comment
Share on other sites

Vern Jensen's starterpack is pretty easy to find on WHTECH.

Vern Jensen's Beginning c99 articles are easy to find in Micropendium.

 

What I was missing was the source code to his signature program virus attack. It was not published in Micropendium, nor part of the starter pack.

 

It took a bit of digging on WHTECH, but I found Virus.ark, it has not only the executable, but the source to snake (which was in Micropendium) and Virus Attack.

 

 

virus.ark

  • Like 3
  • Thanks 2
Link to comment
Share on other sites

Grade File I/O Example.

New and improved using Floating Point.

 

image.png.2efc02a7c312cccc5917ef29e0c931c0.png

 

FPEX;l

 

DSK3.FPEX;O
DSK2.CSUP
DSK2.PRINTF
DSK2.GRF1
DSK2.FSCANF
DSK2.CFIO
DSK2.SCANF
DSK2.FLOAT

FPEX;C

 

#include "DSK2.STDIO"
#include "DSK2.GRF1;H"
#include "DSK2.FLOAT;H"
/* includes are dv */
 
extern printf(),fprintf(),scanf(),fscanf();
/* extern are df - must be loaded */
 
#define FALSE 0
#define TRUE 1
/* sometimes true is def as !FALSE */
 
char a;        /* used by Fwait sub */
int num;
 
float frcnt[8];   /* mirror of int based vars */
float fgtot[8];
float fgavg[8];
char  sgrdav[12];    /* string for grade avg */
 
int reccnt;    /* holds number of records read */
int grdtot;    /* total of all grades */
int grdavg;    /* used to hold simple average */
 
int filptr;
char buff[81];
 
main()
{
  char fname[10];     /* variable to hold values read from file */
  int  fgrade;
 
  reccnt=0;
  grdtot=0;
 
  text();
  clear();
 
 
  filptr=fopen("DSK3.GRADE;D","r");
/*  printf("file pointer:  %d \n", &filptr); */
 
  if (filptr==NULL) {
    printf("no such file");
    return(0);
  }
 
  printf(">File IO  w/t FP Example< \n\n");
  printf("Student     Grade \n\n");
 
  while (!feof(filptr)) {
    fscanf(filptr,"%s %d",fname, &fgrade);
    printf("%-10s   ", fname);
    printf("%3d \n", fgrade);
    reccnt++;
    grdtot=grdtot+fgrade;
  }
 
  printf("\n");
  grdavg=grdtot/reccnt;   /* get a simple average */
  printf("Average Grade: %d \n\n",grdavg);
 
  itof(grdtot,fgtot);
  itof(reccnt,frcnt);
  fexp(fgtot,"/",frcnt,fgavg);
 
  ftos(fgavg,sgrdav,0,0,0);
  printf("Float Avg. Grade: %s \n\n", sgrdav);
 
/*   fpput(fgavg,sgrdav);   */
/*   combines ftos and print */
 
  Fwait();
  exit(0);
 
  Fwait();
}   /* end of main */
 
Fadd(n1,n2)
int n1, n2;
{
  int sum;
 
  sum=n1+n2;
  return(sum);
}
 
Fswitch(n1,n2)
int *n1,*n2;
{
  int temp;
 
  temp=*n1;
  *n1=*n2;
  *n2=temp;
}
 
Fwait()
{
  printf("Press any key to continue. \n\n");
  a=getchar();  /* wait to end */
}
 
/* dhe L.D.O.M. 01/13/2022 */
 
/* need to figure out puts/twrite/display */
/* because we are using twos compliment for decimal rep
   we get back negative numbers */
/* Doesn't look like fprint respect %x vs %X */
/* puts doesn't accept format specs like %s */
 
/* other formatting things....  printf
    %10d - will pad a field to 10 chars, your text on the right
    %10d - will pad to the right, your chars on the right
       printf doesn't respect \t   */
 
/* NULL already define, compiler unhappy if
   you try to define it */
 
/* 12/20/2021
   Odd quirk Fadd works, Fswitch didn't.
   the only diff c=fadd(); vs fswitch
   after adding an c=fswitch(); then it was
   actually called
 
   To keep sane, make sure you have a line between
   int x,y,z and then next line of code */
 
/* naming conventions
    starts with:
    A  Array Ain[] = array input
    F  Function Fwait = a wait funtion
*/
 
/* 12/23/2021
   great swap from tcio to console i/o functions
   fopen is contained in CFIO library
   only ref so far - 6:1:16 trials of a c beginner
    points to articles by Dr. Donald I Mahler of the BCS
*/
 

 

  • Like 2
Link to comment
Share on other sites

I wanted to do a program in TGPSCC (TM) that would do relative (random) file I/O. I have never done that thing before on the TI.

After hitting a couple of road blocks, I decided to prototype a working program in RXB2020. I went back to my my trio of TICodED, RXB2020 and Classic99.

I was surprised at how fast using these three tools, I was able to prototype some simple working examples.

 

Since in this program I was trying to figure out what was going on with file I/O,  Fred's TI99dir was of great value. It allow me to perform a function and look at the resulting data file in real time by looking at another window.

 

One thing that kind of surprised me, was the TI Basic doesn't have a delete record. To delete a record you need to write something that will tell you program to skip record processing that record. Then later you could write a compression utility, that would skip over that record, writing keeper records to another file, then rename the new file as/if needed.

 

The other problem, which I didn't know until I hit the Basic Manual PHA2603 - and I suspect the reason my c99 code wasn't working, is relative I/O doesn't work with variable data, you have to have fixed.

 

Now that I have a working example, I will try moving on to implementing the same with TGPSCC.

 

rem createdb
rem 01-19-2022 - dhe

call clear

open #1:"DSK4.GRADE-D",OUTPUT,FIXED,DISPLAY,RELATIVE

rem lets write data Name, Grade, Exam #

print "Creating Records"
print #1:"Dan,",96,",",1
print #1:"Sally,",87,",",1
print #1:"Harry,",72,",",1
print #1:"Bob,",44,",",1
print #1:"Greyson,",77,",",1
close #1
rem Yes, looks strange, guess you have to manually enter the field seperator.



rem optionally you can add :delete
print "go check your file, I'll wait."
call my_wait


open #1:"DSK4.GRADE-D",APPEND,FIXED,DISPLAY,RELATIVE
print ""
print "Adding a record with append"
print #1:"Thorton,",99,",",1
close #1
rem record doesn't get added to file until you close the file.

print "Record added, go check"
print "don't forget to refresh dir in ti99dir"
call my_wait

open #1:"DSK4.GRADE-D",INPUT,FIXED,DISPLAY,RELATIVE
print ""
print "Fetching 3rd record"
input #1,REC 3:Name$,Grade,Exam
print Name$;Grade;Exam
close #1
print "press any key to continue"
call my_wait

open #1:"DSK4.GRADE-D",UPDATE,FIXED,DISPLAY,RELATIVE
print ""
print "Print Modifying old Bob"
Print #1,REC 3:"Robert,",Grade,",",Exam
input #1,REC 3:Name$,Grade,Exam
print Name$;Grade;Exam
close #1
print "press any key to continue"
call my_wait

print ""
print "Record Count"
reccnt = 0
open #1:"DSK4.GRADE-D",UPDATE,FIXED,DISPLAY,RELATIVE

mylabel1:
if eof(1) then mylabel2
reccnt = reccnt + 1
input #1:Name$,Grade,Exam
goto mylabel1

mylabel2:
print "There are";reccnt;"records."
close #1



sub my_wait
  loop1:
    call key(5,k,s)
    if s=0 then loop1
subend



rem a couple of things here.
rem 1) output will overwrite, not append.
rem 2) ti99dir doesn't update unless you re-read the directory.

rem INPUT files may be read only.
rem OUTPUT files may be written only. new file created
rem UPDATE files may be both read and written
rem  The usual processing is to read a record, change it in some way, then write the altered record back out on the file.
rem APPEND mode allows data to be added

rem !! in order to use RELATIVE (RANDOM ACCESS) file must be of the type fixed. !!

rem Delete - the only way to delete appears to be writting something like blanks
rem   to all fields and skipping them. Then you need to write a file compressor
rem   utility.


rem see relative files by James H. Harvey.

 

  • Like 1
Link to comment
Share on other sites

33 minutes ago, dhe said:

One thing that kind of surprised me, was the TI Basic doesn't have a delete record. To delete a record you need to write something that will tell you program to skip record processing that record. Then later you could write a compression utility, that would skip over that record, writing keeper records to another file, then rename the new file as/if needed.

 

Yeah—Though “SCRATCH RECORD” is listed in the Editor/Assembler Manual, p. 297:

18.2.1.9  SCRATCH RECORD-8
The SCRATCH RECORD operation removes the record specified in bytes 6 and 7
(Record Number) from the specified relative record file. This operation causes an
error for peripherals opened as sequential files.

it was never implemented in the TI disk DSR past linking its opcode (8) directly to the error routine with a “bad attributes” error. 

 

...lee

 

  • Like 2
Link to comment
Share on other sites

DON ONEIL of Western Horizon had a ROS for  his Western Horizon RAMDISK.

But like my GPL Scratch Record in RXB was to slow to be really useful.

 

1. Search file for the record to delete and here is a snag if it is not unusual it only works on first one.

Example: files has names and it the one you want is SMITH out of 20 it picks first one.

 

2. Unless you know exactly where it is the entire thing is like looking for a needle in haystack.

Example: You know where this particular "SMITH" is at record 47 out of 800 records.

 

3. Now you need twice as much space to run SCRATCH RECORD as normal due to needing twice the buffers.

Example: even if you find the record and replace it two buffers are needed to recheck your results.

 

4. It takes a long long time to read every record and write it again. Not to mention you cannot use one single file to do it.

Link to comment
Share on other sites

 

Today's Mis-Adventures in Programming!

 

Printing out an array of strings.

6sTbrzYAybVCZWrAbGQXkhg3pQIAsR-x0FH7SIMybW9GICKGmvilzhYHgHuQY3PjekGs_nkIFjxdzCfutpbzXZnWPhd1XAf2bPzUllbha5vHW3xEbITFUDjpH4a1CjcWNhuut78F

 

Output (this tells me printf doesn’t know the size to print):

pX_PVWN64Vg4AqtmSqPd_Y3nKdBR6YU2LpMvNsCYHDTk5bneQ-or4tsisJEjN5mbnl4CJ4RLEx2K3t5tRMNGFJPIIfEk9cFWdAGSbRtiAOObf2pc5Sm62nezCf7Ow_8fWkGZQ7Oz

 

Try passing printf a pointer..

shcxuJ4Hk2PE6s5PoNUJsNIs1xPjHrN_waFX9yyX6k1rCPQcpxh4_QuDOud-eSLp3cjMvd6yl3FWPdS181nPE-dqK6sH7JDKaq3oEgsDKLgBRqSoSWUZfUeNn14Dr0FLfzuQaDfO

 

And it increments one character position.

Which indicates what exactly?

 

rKOz1GySiQsVfTWaVohUlYp8t59fYHWu3pR1dfHIukSYxGeYTm5_hjVuorqJAX4Hmb6dMcs_wJMJ7DEbe3q9lEJzo88UXAJAaQb9nLrwW05cC_LAN72MlMSmwVD9OipfiLj_qmUT

 

The solution was found in this posting...

https://www.delftstack.com/howto/c/array-of-strings-in-c/

char arr2[NUM_STRINGS][MAX_LENGTH] = { {"first string"},

                                          {"second string"},

                                          {"third string"},

                                          {"fourth string"},

                                          {"fifth string"} };

VS

  char *arr3[NUM_STRINGS] = { "first string",

                                "second string",

                                "third string",

                                "fourth string",

                                "fifth string" };

So at the end of the day {literally} the fix was to put an * in front of names on the array declaration line!

The three main tutorials we have our Kirkwood (Micropendium), Jensen (Micropendium) and Agee (Orphan Survival Guide). None of them covered an array of strings.

  • Like 1
Link to comment
Share on other sites

21 hours ago, dhe said:

char arr2[NUM_STRINGS][MAX_LENGTH] = { {"first string"},

                                          {"second string"},

                                          {"third string"},

                                          {"fourth string"},

                                          {"fifth string"} };

VS

  char *arr3[NUM_STRINGS] = { "first string",

                                "second string",

                                "third string",

                                "fourth string",

                                "fifth string" };

So at the end of the day {literally} the fix was to put an * in front of names on the array declaration line!

So a quick discussion of why... C pointers are probably the most confusing aspect of it, especially with "strings".

 

The first concept to really internalize is there is no such thing as a string in C. There are only series of bytes. The double quotes tell the compiler to put a 0 byte at the end of the sequence, and that's really it.

 

Now type declarations:

char arr2[NUM_STRINGS][MAX_LENGTH] : this defines a two-dimensional array. The type of the elements is "char", a single byte integer.

char *arr3[NUM_STRINGS] : this defines a one-dimensional array. The type of the elements is "char *", a pointer to a single byte integer.

 

Let's look at the initialization.

In the first case, you are defining five strings. The byte patterns that define these strings, including the 0, are copied into arr2 at arr2[0], arr2[1], arr2[2], etc. The unused space in MAX_LENGTH is undefined, but usually zeroed on modern systems and not zeroed on older systems. You can access one of the strings like "arr2[0]", but because this is a 2 dimensional array, the compiler knows you really want "&arr2[0][0]" ('&' meaning "address of"... basically, leaving off the array index turns it into a pointer. This is why printing it works!) Because the data is loaded into the array, it is fully read/write (ie: you can change the strings). In memory, it looks like this (using your screenshot code cause the strings are shorter):

arr2:
 BYTE D, A, N, 0, ?, ?, ?, ?, ?, ?
 BYTE S, T, E, V, E, 0, ?, ?, ?, ?,
 BYTE B, I, L, L, 0, ?, ?, ?, ?, ?,
 BYTE G, R, E, G, 0, ?, ?, ?, ?, ?,
 BYTE ?, ?, ?, ?, ?, ?, ?, ?, ?, ?

('?' represents uninitialized memory - could be anything)

 

In the second case, you are also defining five strings, but there is no copying this time. The strings are stored where the compiler sees fit, and arr3 is loaded with the memory addresses of each string (ie: the pointers). The strings are also defined as constants, which means that trying to change them may not work, depending on the compiler and operating system. 

In memory, it looks something like this:

STRING1: BYTE D, A, N, 0
STRING2: BYTE S, T, E, V, E, 0
STRING3: BYTE B, I, L, L, 0
STRING4: BYTE G, R, E, G, 0

arr3:
 DATA STRING1, STRING2, STRING3, STRING4, ?

Note there is far less padding, because the data type (char *) is fully used.

 

So finally, let's look at the samples.

Your first example actually /should/ work (except, of course, that names[4] is undefined). That suggests your C compiler isn't handling the incomplete array reference properly. names[a] and &names[a] should be equivalent. That's just something you'll need to be aware of - code that you reference from others won't include the address operator when using it that way.

 

The increment on your second example tells me the compiler is not remembering that it's a two dimensional array, and so doing the pointer math incorrectly. It should be multiplying 'a' by 10 (the size of names[x] is 10 bytes), but it's multiplying by 1 (the size of 'char'). To be honest, this is a pretty major bug and would dissuade me from using it. At the very least, you should probably assume that two dimensional arrays are buggy.

 

My point is, both of those examples should have worked.

 

So why does the final version work? Probably because it's a one dimensional array. The size of "char *" on the TI is 2 bytes, and the compiler is correctly multiplying 'a' by that to get a pointer to the constant string, thus your strings work.

 

Unfortunately, with retro and embedded software development, buggy compilers is a fact of life that you learn to deal with - so it's valuable to learn what works and what to avoid. But I want to emphasize that as far as C code goes, your first pass was correct. The only advice I'd have given on it would be to initialize all entries of the array. ;)



 

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...