home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol144 / ucsd2cpm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1984-04-29  |  15.2 KB  |  479 lines

  1. /*      ------------------------------------------------------- 
  2.         *** Template for Procedure Heading *** 
  3.  
  4.         Name: 
  5.         Result: 
  6.         Errors: 
  7.         Globals: 
  8.         Macros: 
  9.         Procedures: 
  10.  
  11.         Action: 
  12.  
  13.         ------------------------------------------------------- */ 
  14.  
  15. /*      : : : : : : : : : : : : : : : : : : : : : : : : : : : : 
  16.  
  17.         ucsd2cpm -- Transfer '.TEXT' files from a UCSD directory 
  18.                     formatted disk to a CP/M directory formatted 
  19.                     disk. 
  20.  
  21.                 1) header blocks removed 
  22.                 2) linefeeds added after carriage returns 
  23.                 3) indents converted to appropriate # of spaces 
  24.                 4) filler nulls removed 
  25.                 5) control-A's removed  (added 2/13/80 hrm) 
  26.  
  27.         6) fixed to work with 1.4x 'c' compilers
  28.            by Chris Undery 5th oct '82
  29.  
  30.            
  31.         : : : : : : : : : : : : : : : : : : : : : : : : : : : : */ 
  32.  
  33.  
  34.  
  35.  
  36.  
  37. /*      : : : : : : : : : : : : : : : : : : : : : : : : : : : : 
  38.  
  39.                 Constants 
  40.  
  41.         : : : : : : : : : : : : : : : : : : : : : : : : : : : : */ 
  42.  
  43. #include bdscio.h
  44.  
  45. #define DLE     0x10            /* Data Link Escape -- indent flag */ 
  46. #define CR      0x0D            /* carriage return */ 
  47. #define LF      0x0A            /* linefeed */ 
  48. #define NULL    0               /* ascii null */ 
  49. #define CPM_EOF 0X1A            /* CP/M ascii endfile mark */ 
  50.  
  51. #define TRUE    1               /* booleans */ 
  52. #define FALSE   0 
  53.  
  54. #define SEL_DSK 14              /* bdos function number */ 
  55. #define SET_DMA 26              /* bdos function number */ 
  56.  
  57. #define SET_TRK 10              /* bios index number (was 9 c.u.) */ 
  58. #define SET_SEC 11              /* bios index number (was 10 c.u) */ 
  59. #define READ    13              /* bios index number (was 12 c.u) */ 
  60.  
  61. #define DUMMY   0               /* dummy parameter for bios routine */ 
  62.  
  63. #define EOF_F   0xFFFF          /* end of file flag */ 
  64. #define D_ENT_SZ 26             /* UCSD directory entry size */ 
  65. #define D_TITLE 6               /* offset to entry title */ 
  66. #define UCSD_NAM_SZ 20          /* size of the name part of ucsd dir entry */ 
  67. #define UCSD_DIR_SZ 2048        /* size of UCSD directory in bytes */ 
  68.  
  69. #define SECT_SIZE 128           /* bytes per physical sector */ 
  70. #define BLOK_SIZE 512           /* bytes per UCSD logical block */ 
  71. #define SECT_PER_BLOK 4         /* physical sectors per logical block */ 
  72.  
  73.  
  74.  
  75.  
  76. /*      : : : : : : : : : : : : : : : : : : : : : : : : : : : : 
  77.  
  78.         Globals -- these would be static if it were available 
  79.  
  80.         : : : : : : : : : : : : : : : : : : : : : : : : : : : : */ 
  81.  
  82. int lsn;                /* logical sector number */ 
  83. int lstlsn;             /* last logical sector number */ 
  84. int nbytes;             /* number of bytes remaining in ucsd file buffer */ 
  85. char ucsdbuf[BLOK_SIZE]; /* 1 block buffer for ucsd file */ 
  86. char *ptr;              /* pointer to current byte in ucsd file buffer */ 
  87. char tofile[BUFSIZ];    /* cp/m destination file buffer */ 
  88.  
  89.  
  90.  
  91.  
  92.  
  93. /*     ------------------------------------------------------- 
  94.  
  95.         Name:           main(argc,argv) 
  96.         Result:         --- 
  97.         Errors:         invocation syntax 
  98.         Globals:        lsn,lstlsn,nbytes,ptr,ucsdbuf 
  99.         Macros:         CPM_FILE,UCSD_FILE,UCSD_NAM_SZ 
  100.  
  101.         Procedures:     puts(),exit(),force_upr(),printf() 
  102.                         putchar(),close(),unlink(),strcpy() 
  103.                         strcat(),getchar(),open(),copy() 
  104.                         tolower() 
  105.  
  106.         Action:         Call copy() to copy a '.TEXT' file 
  107.                         from a UCSD formatted disk in drive B 
  108.                         to a user specified file name in 
  109.                         drive A 
  110.  
  111.                         Handle invocation errors 
  112.                         Handle case of already existing 
  113.                         destination  file 
  114.  
  115.         ------------------------------------------------------- */ 
  116.  
  117. #define CPM_FILE argv[1] 
  118. #define UCSD_FILE argv[2] 
  119.  
  120. main(argc,argv) 
  121.         int argc; 
  122.         char *argv[]; 
  123.         { 
  124.         int file_id; 
  125.         char ucsdname[UCSD_NAM_SZ]; 
  126.  
  127.         lsn = lstlsn = nbytes = 0;      /* init globals */ 
  128.         ptr = ucsdbuf; 
  129.  
  130.         if( argc != 3 ) { 
  131.           puts("Proper invocation form is:\n\n"); 
  132.           puts("UCSD2CPM <cpm-file-name> <ucsd-file-name>\n"); 
  133.           puts("This copies B:<ucsd-file-name>.TEXT to A:<cpm-file-name>\n"); 
  134.           exit(1); 
  135.           } 
  136.         force_upr(UCSD_FILE);   /* make <ucsd-file-name> upper case */ 
  137.     if (fopen(CPM_FILE,tofile) >= 0 ) {
  138.           printf("%s already exists. Delete it ? ",CPM_FILE); 
  139.           if( tolower(getchar()) != 'y' ) { 
  140.             puts("\naborted\n"); 
  141.             exit(1); 
  142.             } 
  143.           putchar('\n'); 
  144.           fclose(tofile); 
  145.           unlink(CPM_FILE); 
  146.           } 
  147.         else 
  148.           fclose(tofile); 
  149.         strcpy(ucsdname,UCSD_FILE); 
  150.         strcat(ucsdname,".TEXT"); 
  151.         if(copy(ucsdname,CPM_FILE)) 
  152.           printf("\n\nno such file %s .. aborted\n",ucsdname); 
  153.         exit(0); 
  154.         } 
  155.  
  156. /*     ------------------------------------------------------- 
  157.  
  158.         Name:           copy (ucsd_file,cpm_file) 
  159.         Result:         TRUE if error , FALSE if transfer ok 
  160.  
  161.         Errors:         no such '.TEXT' file 
  162.  
  163.         Globals:        struct buf, 
  164.         Macros:         TRUE,EOF_F,CR,DLE,NULL,CPM_EOF,FALSE 
  165.  
  166.         Procedures:     find_file(),fcreat(),getbyte() 
  167.                         putc(),fflush(),fclose() 
  168.  
  169.         Action:         Find '.TEXT' file in UCSD directory 
  170.                         on drive B 
  171.                         Create user specified file on 
  172.                         drive A 
  173.                         copy file content from UCSD to CP/M 
  174.                         car by char translating: 
  175.                                 Skip header block 
  176.                                 Ignore NULL's 
  177.                                 Add LF after CR 
  178.                                 Convert DLE <count> to 
  179.                                 appropriate number of spaces 
  180.                         close output file 
  181.  
  182.         ------------------------------------------------------- */ 
  183.  
  184. copy(ucsd_file,cpm_file) 
  185.         char *ucsd_file,*cpm_file; 
  186.         { 
  187.  
  188.         int c; 
  189.  
  190.         if( ! find_file(ucsd_file) )            /* no such file */ 
  191.           return TRUE; 
  192.         if (fcreat(cpm_file,tofile) == ERROR) {
  193.       printf("Can't create %s, aborting..\n",cpm_file);
  194.       exit();
  195.     }
  196.         while( (c = getbyte()) != EOF_F ) 
  197.           switch(c) { 
  198.  
  199.             case CR:    putc(CR,tofile);       /* LF after CR */ 
  200.                         putc(LF,tofile); 
  201.                         break; 
  202.  
  203.             case DLE:   for( c = (getbyte() - 32); c; c-- ) 
  204.                           putc(' ',tofile);    /* fill spaces */ 
  205.                         break; 
  206.  
  207.             case '\1':                          /* ignore ^A's */ 
  208.             case NULL:  break;                  /* ignore nulls */ 
  209.  
  210.             default:    putc(c,tofile);        /* pass char unmodified */ 
  211.                         break; 
  212.             } 
  213.         putc(CPM_EOF,tofile);                  /* send cp/m ascii endfile */ 
  214.         fflush(tofile); 
  215.         fclose(tofile); 
  216.         return FALSE;                           /* signal transfer ok */ 
  217.         } 
  218.  
  219. /*     ------------------------------------------------------- 
  220.  
  221.         Name:           getbyte() 
  222.         Result:         next sequential byte from UCSD '.TEXT' file 
  223.         Errors: 
  224.         Globals:        lsn,lstlsn,nbytes,ptr,ucsdbuf[] 
  225.         Macros:         EOF_F,BLOK_SIZE,SECT_PER_BLOK 
  226.         Procedures:     read_ucsd() 
  227.  
  228.         Action:         read block at a time 
  229.                         pass along byte at a time 
  230.                         return EOF_F if end of UCSD file 
  231.  
  232.         ------------------------------------------------------- */ 
  233.  
  234.  
  235. getbyte() 
  236.         { 
  237.         if( lsn > lstlsn) 
  238.           return EOF_F; 
  239.         if( nbytes-- ) 
  240.           return *ptr++; 
  241.         read_ucsd(ucsdbuf,lsn,1); 
  242.         nbytes = (BLOK_SIZE-1); 
  243.         ptr = ucsdbuf; 
  244.         lsn += SECT_PER_BLOK; 
  245.         return *ptr++; 
  246.         } 
  247.  
  248.  
  249. /*     ------------------------------------------------------- 
  250.  
  251.         Name:           find_file(ucsd_name) 
  252.         Result:         TRUE if found, FALSE if not found 
  253.         Errors: 
  254.         Globals:        lsn,lstlsn 
  255.         Macros:         D_ENT_SZ,SECT_PER_BLOK,D_TITLE 
  256.                         TRUE,FALSE,UCSD_DIR_SZ 
  257.  
  258.         Procedures:     read_ucsd() 
  259.  
  260.         Action:         --- 
  261.  
  262.         ------------------------------------------------------- */ 
  263.  
  264.  
  265. find_file(ucsd_name) 
  266.         char *ucsd_name; 
  267.         { 
  268.         char ucsd_dir[UCSD_DIR_SZ]; 
  269.         char *dir,*saved_dir,*name; 
  270.         int name_len; 
  271.  
  272.         name = ucsd_name; 
  273.         read_ucsd(ucsd_dir,(2*SECT_PER_BLOK),4); 
  274.         dir = &ucsd_dir[D_TITLE + D_ENT_SZ];    /* skip title block */ 
  275.         while ( dir < &ucsd_dir[UCSD_DIR_SZ] ) { 
  276.           saved_dir = dir; 
  277.           if( (name_len = *dir++) <=0 || name_len > 19 ) 
  278.             return FALSE; 
  279.           while( *dir++ == *name++ ) { 
  280.             if( --name_len )    /* continue comparison check */ 
  281.               ; 
  282.             else {                              /* entry found */ 
  283.               dir = saved_dir - D_TITLE;        /* point to alloc. info. */ 
  284.               lsn = *dir++; 
  285.               lsn += *dir++ << 8;   /* lsn = starting logical block number */ 
  286.               lsn += 2;             /* bypass header blocks */ 
  287.               lsn *= SECT_PER_BLOK; /* 1'st logical sector number */ 
  288.  
  289.               lstlsn = *dir++; 
  290.               lstlsn += *dir++ << 8;    /* lstlsn = ending logical block # */ 
  291.               lstlsn *= SECT_PER_BLOK;  /* lstlsn = last logical sector # */ 
  292.               return TRUE;              /* indicate file found */ 
  293.               } 
  294.             } 
  295.           name = ucsd_name;             /* reset comparison name pointer */ 
  296.           dir = saved_dir + D_ENT_SZ;   /* point at next entry name */ 
  297.           } 
  298.         return FALSE;                           /* no such file */ 
  299.         } 
  300.  
  301. /*     ------------------------------------------------------- 
  302.  
  303.         Name:           read_ucsd() 
  304.         Result:         status of selecting drive A 
  305.         Errors:         sector read error 
  306.         Globals:        --- 
  307.         Macros:         SEL_DSK,SET_DMA,SET_TRK,SET_SEC 
  308.                         READ,DUMMY,SECT_SIZE 
  309.         Procedures:     bios(),bdos(),printf(),exit() 
  310.  
  311.         Action:         Read count blocks from drive B 
  312.                         into buf starting at UCSD logical 
  313.                         record number rn 
  314.  
  315.         ------------------------------------------------------- */ 
  316.  
  317.  
  318. read_ucsd(buf,rn,count) 
  319.         char *buf; 
  320.         unsigned rn; 
  321.         int count; 
  322.         { 
  323.         char bios(); 
  324.         int seccnt; seccnt = count*4; 
  325.  
  326.         bdos(SEL_DSK,1); 
  327.         while( seccnt-- ) { 
  328.           bdos(SET_DMA,buf); 
  329.           bios(SET_TRK,track(rn)); 
  330.           bios(SET_SEC,sector(rn)); 
  331.           if( bios(READ,DUMMY) ) { 
  332.             printf("read error @ track %2d sector %2d",track(rn),sector(rn)); 
  333.             exit(1); 
  334.             } 
  335.           buf += SECT_SIZE; 
  336.           rn++; 
  337.           } 
  338.         return bdos(SEL_DSK,0); 
  339.         } 
  340.  
  341. /*     ------------------------------------------------------- 
  342.  
  343.         Name:           sector(rn) 
  344.         Result:         absolute sector number 
  345.         Errors:         --- 
  346.         Globals:        --- 
  347.         Macros:         --- 
  348.         Procedures:     --- 
  349.  
  350.         Action:         convert logical record number 
  351.                         to absolute sector 
  352.  
  353.                         maps logical records to physical sectors 
  354.                         by selecting every second sector in order 
  355.                         (accounting for the modulo 26 process) 
  356.                         on the diskette except that at a track 
  357.                         switchover point there is an additional 
  358.                         'gap' of 6 sectors (total of 7) to allow 
  359.                         for the drive to seek. This is UCSD's 
  360.                         attempt to minimize disk access time. 
  361.  
  362.         ------------------------------------------------------- */ 
  363.  
  364. sector(rn) 
  365.         unsigned rn; 
  366.         { 
  367.         unsigned t1,t2,trk,t3,sect; 
  368.  
  369.         t1 = rn % 26; 
  370.         t2 = t1 << 1; 
  371.         if(t1 > 12) 
  372.           t2++; 
  373.         trk = rn/26;            /* zero based absolute track */ 
  374.         t3 = t2 + 6*trk;        /* new logical sector number */ 
  375.         sect = t3 % 26;         /* new zero based absolute sector */ 
  376.         return ++sect;          /* one based absolute sector */ 
  377.         } 
  378.  
  379. /*      ------------------------------------------------------- 
  380.  
  381.         Name:           track(rn) 
  382.         Result:         absolute track number 
  383.         Errors:         --- 
  384.         Globals:        --- 
  385.         Macros:         --- 
  386.         Procedures:     --- 
  387.  
  388.         Action:         convert logical sector number to 
  389.                         absolute track This is simply the modulo 
  390.                         26 process except that track 0 is not 
  391.                         considered part of the logical 
  392.                         sector space. 
  393.  
  394.         ------------------------------------------------------- */ 
  395.  
  396.  
  397. track(rn) 
  398.         unsigned rn; 
  399.         { 
  400.         return rn/26 + 1; 
  401.         } 
  402.  
  403. /*     ------------------------------------------------------- 
  404.  
  405.         Name:           index(str,sstr) 
  406.         Result:         position of string sstr in string str 
  407.                         -1 if not a substring 
  408.         Errors:         --- 
  409.         Globals:        --- 
  410.         Macros:         --- 
  411.         Procedures:     --- 
  412.  
  413.         Action:         --- 
  414.  
  415.         ------------------------------------------------------- */ 
  416.  
  417.  
  418. index(str,sstr) 
  419.         char *str,*sstr; 
  420.         { 
  421.         int first_match; 
  422.  
  423.         if( *sstr == 0 )  /* null string is a substring of all strings */ 
  424.           return 0; 
  425.         for( first_match=0; *str != *sstr; first_match++) 
  426.           if( *str == 0 ) 
  427.             return -1; 
  428.           else 
  429.             str++; 
  430.         while( *sstr ) 
  431.           if( *str++ != *sstr++ ) 
  432.             return -1; 
  433.         return first_match; 
  434.         } 
  435.  
  436. /*      ------------------------------------------------------- 
  437.  
  438.         Name:           force_upr(string) 
  439.         Result:         --- 
  440.         Errors:         --- 
  441.         Globals:        --- 
  442.         Macros:         --- 
  443.         Procedures:     --- 
  444.  
  445.         Action:         force each char of string to upper case 
  446.  
  447.         ------------------------------------------------------- */ 
  448.  
  449. force_upr(string) 
  450.         char *string; 
  451.         { 
  452.         while(*string) 
  453.           *string = *string++; 
  454.         return; 
  455.         } 
  456.  
  457. /*      ------------------------------------------------------- 
  458.  
  459.         Name:           print(string,n) 
  460.         Result:         --- 
  461.         Errors:         --- 
  462.         Globals:        --- 
  463.         Macros:         --- 
  464.         Procedures:     putchar() 
  465.  
  466.         Action:         print n chars to console starting 
  467.                         at char pointer string 
  468.  
  469.         ------------------------------------------------------- */ 
  470.  
  471. print(string,n) 
  472.         char *string; 
  473.         int n; 
  474.         { 
  475.         while(n--) 
  476.           putchar(*string++); 
  477.         return; 
  478.         } 
  479.