home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / hf / dsp / dsp4tool / utils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-07  |  9.2 KB  |  377 lines

  1. /*  UTILS.C -- Various utilities for DLIB and DL
  2.  *
  3.  *  Copyright (C) by Alef Null 1990, 1991, 1992, 1993, 1994
  4.  *  Author(s): Jarkko Vuori, OH2LNS
  5.  *  Modification(s):
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <malloc.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #include "utils.h"
  14.  
  15. #if defined(__TURBOC__)
  16.     #undef  halloc
  17.     #define halloc(a, b)    farcalloc(a, b)
  18.     #undef  hfree
  19.     #define hfree(a)        farfree(a)
  20. #endif
  21.  
  22. /*
  23.  * Calculate CCITT (HDLC, X25) CRC
  24.  */
  25. unsigned crc(unsigned char *blk, unsigned len) {
  26.     const unsigned poly = 0x8408;   // x^16+x^12+x^5+1
  27.  
  28.     register unsigned        result;
  29.     register unsigned char  ch;
  30.     int             i;
  31.     unsigned char       *p;
  32.  
  33.     result = 0xffff;
  34.     for (p = blk; p < blk+len; p++) {
  35.     ch = *p;
  36.     for (i = 0; i < 8; i++) {
  37.         if ((result^ch) & 0x001) {
  38.         result >>= 1;
  39.         result ^= poly;
  40.         } else
  41.         result >>= 1;
  42.         ch >>= 1;
  43.     }
  44.     }
  45.  
  46.     return (result);
  47. }
  48.  
  49.  
  50. /*
  51.  * Add extension to the filename
  52.  */
  53. char *AddExtension(char *FileName, char *Extension) {
  54.     static char  Name[_MAX_PATH];
  55.     char    *s1;
  56.  
  57.     /* copy basename */
  58.     s1 = Name;
  59.     while(*FileName && *FileName != '.')
  60.         *s1++ = *FileName++;
  61.  
  62.     /* copy extension (if there are already no extension) */
  63.     strcpy(s1, !*FileName ? Extension : FileName);
  64.  
  65.     return(Name);
  66. }
  67.  
  68.  
  69. /*
  70.  * Parse and execute command line options
  71.  *
  72.  *  returns zero if everything is ok
  73.  *        nonzero otherwise
  74.  */
  75. int ParseCommands(int argc, char *argv[], CMDS *cmds, int cmdcount, int desc_len, void (*usage)(void)) {
  76.     FILE *files[MAX_FILES];
  77.     CMDS *p;
  78.     int   i, numArg;
  79.     char  description[256];
  80.  
  81.     /* check that we have at least some arguments */
  82.     if (argc--, argv++, !argc) {
  83.     usage();
  84.     return (-1);
  85.     }
  86.  
  87.     /* then parse arguments */
  88.     while (argc)
  89.     switch (argc, **argv) {
  90.     case '-':
  91.         /* was command mark, search for that command */
  92.         ++(*argv);
  93.         for (p = cmds; p < &cmds[cmdcount]; p++)
  94.         if (toupper(**argv) == p->cmd) {
  95.             /* given command was legal check if we need numeric argument */
  96.             if (p->numericArgument)
  97.             if (isdigit(*(++(*argv))))
  98.                 numArg = atoi(*argv);
  99.             else {
  100.                 fprintf(stderr, "numeric argument must be given\n");
  101.                 return (-1);
  102.             }
  103.  
  104.             argc--; argv++;
  105.  
  106.             /* then open necessary files */
  107.             for (i = 0; p->fileModes[i] != Last; i++) {
  108.             if (!argc) {
  109.                 usage();
  110.                 return (-1);
  111.             }
  112.  
  113.             switch (p->fileModes[i]) {
  114.             case Modify:
  115.                 if ((files[i] = fopen(AddExtension(*argv, p->extension[i]), "rb+")) == NULL)
  116.                 if ((files[i] = fopen(AddExtension(*argv, p->extension[i]), "wb+")) == NULL) {
  117.                     fprintf(stderr, "can't create file '%s'\n", *argv);
  118.                     return (-1);
  119.                 }
  120.                 setvbuf(files[i], NULL, _IOFBF, 8192);
  121.                 break;
  122.  
  123.             case ReadOnly:
  124.                 if ((files[i] = fopen(AddExtension(*argv, p->extension[i]), "rb")) == NULL) {
  125.                 fprintf(stderr, "can't open file '%s'\n", *argv);
  126.                 return (-1);
  127.                 }
  128.                 setvbuf(files[i], NULL, _IOFBF, 8192);
  129.                 break;
  130.             }
  131.  
  132.             argc--; argv++;
  133.             }
  134.  
  135.             /* then fetch remaining comments */
  136.             *description = '\0';
  137.             if (p->fDescription) {
  138.             while (argc) {
  139.                 if (strlen(description)+strlen(*argv) > desc_len) {
  140.                 fprintf(stderr, "given comment too long\n");
  141.                 return (-1);
  142.                 }
  143.                 strcat(description, *argv); strcat(description, " ");
  144.  
  145.                 argv++, argc--;
  146.             }
  147.             if (*description)
  148.                 description[strlen(description)-1] = '\0';
  149.             }
  150.  
  151.             /* and finally execute the given command */
  152.             if (p->operation) {
  153.             if (!(*p->operation)(files, numArg, description))
  154.                 return (-1);
  155.             } else
  156.             fprintf(stderr, "not yet implemented\n");
  157.  
  158.             break;
  159.         }
  160.  
  161.         /* check if we found any legal commands */
  162.         if (p == &cmds[cmdcount]) {
  163.         usage();
  164.         return (-1);
  165.         }
  166.         break;
  167.  
  168.     case '?':
  169.         usage();
  170.         return (0);
  171.         break;
  172.  
  173.     default:
  174.         usage();
  175.         return (-1);
  176.         break;
  177.     }
  178.  
  179.     return (0);
  180. }
  181.  
  182.  
  183. /* read next token from input */
  184. static char *ReadToken(FILE *fd) {
  185.     static char line[80];
  186.     char c, *p;
  187.  
  188.     #define WHITESPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\r' || (x) == '\n')
  189.  
  190.     /* flush leading whitespace out */
  191.     do {
  192.     fread(&c, 1, 1, fd);
  193.     } while (WHITESPACE(c) && !feof(fd));
  194.  
  195.     /* then read next token */
  196.     p = line;
  197.     while (p < &line[80] && !feof(fd) && !WHITESPACE(c)) {
  198.     *p++ = c;
  199.     fread(&c, 1, 1, fd);
  200.     }
  201.     *p = '\0';
  202.  
  203.     return (line);
  204. }
  205.  
  206. /* convert ASCII-Hex argument to long number */
  207. static long HexToLong(char *data) {
  208.     long val;
  209.  
  210.     sscanf(data, "%lX", &val);
  211.  
  212.     return (val);
  213. }
  214.  
  215. /* Read next word from LNK56000 output file */
  216. static int ReadWord(FILE *fd, unsigned char *space, unsigned *address, long *word) {
  217.     static unsigned char currentspace;
  218.     static Bool      longspace;
  219.     static unsigned     currentaddress;
  220.     static enum {
  221.     ignore, spaceheader, collectdata
  222.     }             state = ignore;
  223.     char        *token;
  224.  
  225.     while (True) {
  226.     token = ReadToken(fd);
  227.  
  228.     if (strlen(token) == 0) {
  229.         fprintf(stderr, "rdlod error: inputfile too short or no _END record, not a valid Motorola load file\n");
  230.         return (-1);
  231.     }
  232.  
  233.     if (*token == '_') {
  234.         if (!strcmp(token, "_END"))
  235.         return (1);
  236.  
  237.         else if (!strcmp(token, "_DATA"))
  238.         state = spaceheader;
  239.  
  240.         else if (!strcmp(token, "_START") || !strcmp(token, "_SYMBOL"))
  241.         state = ignore;
  242.         else {
  243.         fprintf(stderr, "rdlod error: unknown record '%s'\n", token);
  244.         return (-1);
  245.         }
  246.     }
  247.  
  248.     switch (state) {
  249.     case ignore:
  250.         /* ignore this record */
  251.         break;
  252.  
  253.     case spaceheader:
  254.         /* data space header */
  255.         switch (*ReadToken(fd)) {
  256.         case 'P': currentspace = p; longspace = False; break;
  257.         case 'L': currentspace = x; longspace = True;  break;
  258.         case 'X': currentspace = x; longspace = False; break;
  259.         case 'Y': currentspace = y; longspace = False; break;
  260.         default:
  261.         fprintf(stderr, "rdlod error: illegal data space, not a valid Motorola load file\n");
  262.         return (-1);
  263.         break;
  264.         }
  265.  
  266.         currentaddress = (unsigned)HexToLong(ReadToken(fd));
  267.  
  268.         state = collectdata;
  269.         break;
  270.  
  271.     case collectdata:
  272.         /* read next data */
  273.         *space   = currentspace;
  274.         *address = currentaddress;
  275.         *word    = HexToLong(token);
  276.  
  277.         if (longspace) {
  278.         /* fill x and y spaces from l space */
  279.         if (currentspace == x)
  280.             currentspace = y;
  281.         else {
  282.             currentspace = x;
  283.             currentaddress++;
  284.         }
  285.         } else
  286.         currentaddress++;
  287.  
  288.         return (0);
  289.         break;
  290.     }
  291.     }
  292. }
  293.  
  294.  
  295. /*
  296.  * Reads consecutive memory blocks from the LNK56000 output file
  297.  */
  298. Bool ReadBlocks(FILE *fp, Bool (*block)(BLKHEADER *pHeader, long huge *data)) {
  299.     static struct {
  300.     char      *name;
  301.     unsigned   words,
  302.            maxaddress;
  303.     long huge *data;
  304.     Bool huge *touched;
  305.     } memspaces[3] = {
  306.     /* normal program */
  307.     { "X", 0, 0x1fff, },
  308.     { "P", 0, 0x1fff, },
  309.     { "Y", 0, 0x3fff, }
  310.     };
  311.     BLKHEADER header;
  312.     long      word;
  313.     unsigned  i;
  314.     int       result;
  315.     Bool      fResult = True, fHunt;
  316.  
  317.     /* first allocate space for loadable data */
  318.     for (header.space = x; header.space <= y; header.space++)
  319.     if (!(
  320.         (memspaces[header.space].data    = halloc((long)memspaces[header.space].maxaddress+1, sizeof(long))) &&
  321.         (memspaces[header.space].touched = halloc((long)memspaces[header.space].maxaddress+1, sizeof(Bool)))
  322.     )) {
  323.         fprintf(stderr, "loader error: not enought memory\n");
  324.         fResult = False; goto endload;
  325.     }
  326.  
  327.     /* read program from file to memspaces */
  328.     while (!(result = ReadWord(fp, &header.space, &header.address, &word))) {
  329.     if (header.address > memspaces[header.space].maxaddress) {
  330.         fprintf(stderr, "loader error: too big %s header.space, allowed range %04XH-%04XH\n", memspaces[header.space].name, 0, memspaces[header.space].maxaddress);
  331.         fResult = False; goto endload;
  332.     }
  333.  
  334.     memspaces[header.space].data[header.address]    = word;
  335.     memspaces[header.space].words            = max(memspaces[header.space].words, header.address+1);
  336.     memspaces[header.space].touched[header.address] = True;
  337.     }
  338.     if (result < 0) {
  339.     fResult = False; goto endload;
  340.     }
  341.  
  342.     for (header.space = x; header.space <= y; header.space++) {
  343.     /* search for continuous blocks */
  344.     fHunt = True;
  345.     for (i = 0; i < memspaces[header.space].maxaddress; i++)
  346.         if (fHunt) {
  347.         if (memspaces[header.space].touched[i]) {
  348.             /* start of data found */
  349.             fHunt       = False;
  350.             header.address = i;
  351.         }
  352.         } else {
  353.         if (!memspaces[header.space].touched[i]) {
  354.             /* end of data found */
  355.             fHunt      = True;
  356.             header.len = i-header.address;
  357.             if (!(*block)(&header, &memspaces[header.space].data[header.address])) {
  358.             fResult = False; goto endload;
  359.             }
  360.         }
  361.         }
  362.     if (!fHunt) {
  363.         header.len = i-header.address;
  364.         if (!(*block)(&header, &memspaces[header.space].data[header.address])) {
  365.         fResult = False; goto endload;
  366.         }
  367.     }
  368.     }
  369.  
  370. endload:
  371.     for (header.space = x; header.space <= y; header.space++) {
  372.     hfree(memspaces[header.space].data); hfree(memspaces[header.space].touched);
  373.     }
  374.  
  375.     return (fResult);
  376. }
  377.