Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /***********************************************************************
  2.  *
  3.  *  avra - Assembler for the Atmel AVR microcontroller series
  4.  *
  5.  *  Copyright (C) 1998-2004 Jon Anders Haugum, TObias Weber
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; see the file COPYING.  If not, write to
  19.  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  20.  *  Boston, MA 02111-1307, USA.
  21.  *
  22.  *
  23.  *  Authors of avra can be reached at:
  24.  *     email: jonah@omegav.ntnu.no, tobiw@suprafluid.com
  25.  *     www: http://sourceforge.net/projects/avra
  26.  */
  27.  
  28. /*
  29.  * In append_type: added generic register names support
  30.  * Alexey Pavluchenko, 16.Nov.2005
  31.  */
  32.  
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <ctype.h>
  37.  
  38. #include "misc.h"
  39. #include "args.h"
  40. #include "avra.h"
  41. #include "device.h"
  42.  
  43. /* Only Windows LIBC does support itoa, so we add this
  44.    function for other systems here manually. Thank you
  45.    Peter Hettkamp for your work. */
  46.  
  47. #ifndef WIN32
  48. char * itoa(int num, char *str, const int number_format)
  49. {
  50.         int num1 = num;
  51.         int num_chars = 0;
  52.         int pos;
  53.        
  54.         while (num1>0)
  55.         {
  56.                 num_chars++;
  57.                 num1 /= number_format;
  58.         }
  59.  
  60.         if (num_chars == 0) num_chars = 1;
  61.  
  62.         str[num_chars] = 0;
  63.        
  64.         for (pos = num_chars-1; pos>=0; pos--)
  65.         {
  66.                 int cur_char = num % number_format;
  67.                
  68.                 if (cur_char < 10) /* Insert number */
  69.                 {
  70.                         str[pos] = cur_char + '0';
  71.                 }
  72.                 else
  73.                 {
  74.                         str[pos] = cur_char-10 + 'A';
  75.                 }
  76.                
  77.                 num /= number_format;
  78.         }
  79.         return(str);
  80. }
  81. #endif
  82.  
  83.  
  84. int read_macro(struct prog_info *pi, char *name)
  85. {
  86.         int loopok;
  87.     int i;
  88.     int start;
  89.         struct macro *macro;
  90.         struct macro_line *macro_line;
  91.     struct macro_line **last_macro_line = NULL;
  92.         struct macro_label *macro_label;
  93.  
  94.         if(pi->pass == PASS_1) {
  95.                 if(!name) {
  96.                         print_msg(pi, MSGTYPE_ERROR, "missing macro name");
  97.                         return(True);
  98.                 }
  99.                 get_next_token(name, TERM_END);
  100.  
  101.                 for(i = 0; !IS_END_OR_COMMENT(name[i]); i++) { 
  102.                         if(!IS_LABEL(name[i])) {
  103.                                 print_msg(pi, MSGTYPE_ERROR, "illegal characters used in macro name '%s'",name);
  104.                                 return(False);
  105.                         }
  106.                 }
  107.  
  108.                 macro = calloc(1, sizeof(struct macro));
  109.                 if(!macro) {
  110.                         print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  111.                         return(False);
  112.                 }
  113.  
  114.                 if(pi->last_macro)
  115.                         pi->last_macro->next = macro;
  116.                 else
  117.                         pi->first_macro = macro;
  118.                 pi->last_macro = macro;
  119.                 macro->name = malloc(strlen(name) + 1);
  120.                 if(!macro->name) {
  121.                         print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  122.                         return(False);
  123.                 }
  124.                 strcpy(macro->name, name);
  125.                 macro->include_file = pi->fi->include_file;
  126.                 macro->first_line_number = pi->fi->line_number;
  127.                 last_macro_line = &macro->first_macro_line;
  128.         }
  129.         else {  /* pi->pass == PASS_2 */
  130.                 if(pi->list_line && pi->list_on) {
  131.                         fprintf(pi->list_file, "          %s\n", pi->list_line);
  132.                         pi->list_line = NULL;
  133.                 }
  134.                 // reset macro label running numbers
  135.                 get_next_token(name, TERM_END);
  136.                 macro = get_macro(pi, name);
  137.                 if (!macro) {
  138.                         print_msg(pi, MSGTYPE_ERROR, "macro inconsistency in '%s'", name);
  139.                         return(True);
  140.                 }
  141.                 for(macro_label = macro->first_label; macro_label; macro_label = macro_label->next) {
  142.                         macro_label->running_number = 0;
  143.                 }
  144.         }
  145.  
  146.         loopok = True;
  147.         while(loopok) {
  148.                 if(fgets_new(pi,pi->fi->buff, LINEBUFFER_LENGTH, pi->fi->fp)) {
  149.                         pi->fi->line_number++;
  150.                         i = 0;
  151.                         while(IS_HOR_SPACE(pi->fi->buff[i]) && !IS_END_OR_COMMENT(pi->fi->buff[i])) i++;
  152.                         if(pi->fi->buff[i] == '.') {
  153.                           i++;
  154.                           if(!nocase_strncmp(&pi->fi->buff[i], "endm", 4))
  155.                                 loopok = False;
  156.                           if(!nocase_strncmp(&pi->fi->buff[i], "endmacro", 8))
  157.                                 loopok = False;
  158.                         }
  159.                         if(pi->pass == PASS_1) {
  160.                                 if(loopok) {
  161.                                         i = 0; /* find start of line */
  162.                                         while(IS_HOR_SPACE(pi->fi->buff[i]) && !IS_END_OR_COMMENT(pi->fi->buff[i])) {
  163.                                         i++;
  164.                                         }
  165.                                         start = i;
  166.                                         /* find end of line */
  167.                                         while(!IS_END_OR_COMMENT(pi->fi->buff[i]) && (IS_LABEL(pi->fi->buff[i]) || pi->fi->buff[i] == ':')) {
  168.                                         i++;
  169.                                         }
  170.                                         if(pi->fi->buff[i-1] == ':' && (pi->fi->buff[i-2] == '%'
  171.                                         && (IS_HOR_SPACE(pi->fi->buff[i]) || IS_END_OR_COMMENT(pi->fi->buff[i])))) {
  172.                                                 if(macro->first_label) {
  173.                                                         for(macro_label = macro->first_label; macro_label->next; macro_label=macro_label->next){}
  174.                                         macro_label->next = calloc(1,sizeof(struct macro_label));
  175.                                         macro_label = macro_label->next;
  176.                                                 }
  177.                                         else {
  178.                                         macro_label = calloc(1,sizeof(struct macro_label));
  179.                                         macro->first_label = macro_label;
  180.                                 }
  181.                                 macro_label->label = malloc(strlen(&pi->fi->buff[start])+1);
  182.                                 pi->fi->buff[i-1] = '\0';
  183.                                         strcpy(macro_label->label, &pi->fi->buff[start]);
  184.                                 pi->fi->buff[i-1] = ':';
  185.                                         macro_label->running_number = 0;
  186.                                         }
  187.                                
  188.                                         macro_line = calloc(1, sizeof(struct macro_line));
  189.                                         if(!macro_line) {
  190.                                                 print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  191.                                                 return(False);
  192.                                         }
  193.                                         *last_macro_line = macro_line;
  194.                                         last_macro_line = &macro_line->next;
  195.                                         macro_line->line = malloc(strlen(pi->fi->buff) + 1);
  196.                                         if(!macro_line->line) {
  197.                                                 print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  198.                                                 return(False);
  199.                                         }
  200.                                         strcpy(macro_line->line, &pi->fi->buff[start]);
  201.                                 }
  202.                         }
  203.                         else if(pi->fi->buff && pi->list_file && pi->list_on) {
  204.                                 if(pi->fi->buff[i] == ';')
  205.                                         fprintf(pi->list_file, "         %s\n", pi->fi->buff);
  206.                                 else
  207.                                         fprintf(pi->list_file, "          %s\n", pi->fi->buff);
  208.                         }
  209.                 }
  210.                 else {
  211.                         if(feof(pi->fi->fp)) {
  212.                                 print_msg(pi, MSGTYPE_ERROR, "Found no closing .ENDMACRO");
  213.                                 return(True);
  214.                         }
  215.                         else {
  216.                                 perror(pi->fi->include_file->name);
  217.                                 return(False);
  218.                         }
  219.                 }
  220.         }
  221.         return(True);
  222. }
  223.  
  224.  
  225. struct macro *get_macro(struct prog_info *pi, char *name)
  226. {
  227.         struct macro *macro;
  228.  
  229.         for(macro = pi->first_macro; macro; macro = macro->next)       
  230.                 if(!nocase_strcmp(macro->name, name))
  231.                         return(macro);
  232.         return(NULL);
  233. }
  234.  
  235. void append_type(struct prog_info *pi, char *name, int c, char *value)
  236. {
  237.         int p, l;
  238.         struct def *def;
  239.  
  240.         p = strlen(name);
  241.         name[p++] = '_';
  242.  
  243.         if(c == 0)
  244.         {
  245.                 name[p++] = 'v';
  246.                 name[p] = '\0';
  247.                 return;
  248.         }
  249.  
  250.         l = strlen(value);
  251.         if ((l==2 || l==3) && (tolower(value[0])=='r') && isdigit(value[1]) && (l==3?isdigit(value[2]):1) && (atoi(&value[1])<32))
  252.         {
  253.                 itoa((c*8),&name[p],10);
  254.                 return;
  255.         }
  256.                        
  257.  
  258.         for(def = pi->first_def; def; def = def->next)
  259.                 if(!nocase_strcmp(def->name, value))
  260.                 {
  261.                         itoa((c*8),&name[p],10);
  262.                         return;
  263.                 }
  264.  
  265.         name[p++] = 'i';
  266.         name[p] = '\0';
  267. }
  268.  
  269.  
  270. /*********************************************************
  271.  * This routine replaces the macro call with mnemonics.  *
  272.  *********************************************************/
  273.  
  274. int expand_macro(struct prog_info *pi, struct macro *macro, char *rest_line)
  275. {
  276.   int   ok = True, macro_arg_count = 0, off, a, b = 0, c, i = 0, j = 0;
  277.   char  *line = NULL;
  278.   char  *temp;
  279.   char  *macro_args[MAX_MACRO_ARGS];
  280.   char  tmp[7];
  281.   char  buff[LINEBUFFER_LENGTH];
  282.   char  arg = False;
  283.   char  *nmn; //string buffer for 'n'ew 'm'acro 'n'ame
  284.   struct        macro_line *old_macro_line;
  285.   struct        macro_call *macro_call;
  286.   struct        macro_label *macro_label;
  287.  
  288.   if(rest_line) {
  289.     //we reserve some extra space for extended macro parameters
  290.     line = malloc(strlen(rest_line) + 20);
  291.         if(!line) {
  292.           print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  293.           return(False);
  294.     }
  295.                
  296.         /* exchange amca word 'src' with YH:YL and 'dst' with ZH:ZL */
  297.         for(c = 0, a = strlen(rest_line); c < a; c++) {
  298.           switch (tolower(rest_line[c])) {
  299.                 case 's':
  300.           if(IS_SEPARATOR(rest_line[c-1]) && (rest_line[c+1] == 'r') && (rest_line[c+2] == 'c') && IS_SEPARATOR(rest_line[c+3])) {
  301.             strcpy(&line[b],"YH:YL");
  302.             b += 5;
  303.             c += 2;
  304.           }
  305.           else {
  306.                         line[b++] = rest_line[c];
  307.                   }
  308.           break;
  309.         case 'd':
  310.           if(IS_SEPARATOR(rest_line[c-1]) && (rest_line[c+1] == 's') && (rest_line[c+2] == 't') && IS_SEPARATOR(rest_line[c+3])) {
  311.             strcpy(&line[b],"ZH:ZL");
  312.             b += 5;
  313.             c += 2;
  314.                   }
  315.           else {
  316.                         line[b++] = rest_line[c];
  317.                   }
  318.           break;
  319. //        case ';':
  320. //          break;
  321.         default:
  322.           line[b++] = rest_line[c];                
  323.           }
  324.         }
  325.     strcpy(&line[b],"\n"); /* set CR/LF at the end of the line */
  326.                
  327.        
  328.         /*  here we split up the macro arguments into "macro_args"
  329.          *  Extended macro code interpreter added by TW 2002
  330.          */
  331.                
  332.         temp = line;
  333.     /* test for advanced parameters */
  334.         if( temp[0] == '[' ) { // there must be "[" " then "]", else it is garbage
  335.       if(!strchr(temp, ']')) {
  336.         print_msg(pi, MSGTYPE_ERROR, "found no closing ']'");
  337.                 return(False);
  338.           }
  339.  
  340.       // Okay now we are within the advanced code interpreter
  341.        
  342.           temp++; // = &temp[1]; // skip the first bracket
  343.           nmn = malloc(LINEBUFFER_LENGTH);
  344.       if(!nmn) {
  345.             print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  346.             return(False);
  347.           }
  348.           strcpy(nmn,macro->name); // create a new macro name buffer
  349.           c = 1; // byte counter
  350.           arg = True; // loop flag
  351.  
  352.           while(arg) {
  353.                 while(IS_HOR_SPACE(temp[0])) { //skip leading spaces
  354.           temp++; // = &temp[1];
  355.                 }
  356.                 off = 0; // pointer offset
  357.                 do {
  358.                   switch(temp[off]) { //test current character code
  359.                         case ':':
  360.                   temp[off] = '\0';
  361.                           if(off > 0) {
  362.                                 c++;
  363.                         macro_args[macro_arg_count++] = temp;
  364.                           }
  365.                           else {
  366.                                 print_msg(pi, MSGTYPE_ERROR, "missing register before ':'",nmn);
  367.                                 return(False);
  368.                           }
  369.                           break;
  370.                         case ']':
  371.                           arg = False;
  372.                 case ',':
  373.                           a = off;
  374.                           do temp[a--] = '\0'; while( IS_HOR_SPACE(temp[a]) );
  375.                   if(off > 0) {
  376.                         macro_args[macro_arg_count++] = temp;
  377.                                 append_type(pi, nmn, c, temp);
  378.                                 c = 1;
  379.                           }
  380.                           else {
  381.                                 append_type(pi, nmn, 0, temp);
  382.                                 c = 1;
  383.                           }
  384.                           break;
  385.  
  386.                  default:
  387.                   off++;
  388.                   }
  389.                 }
  390.                 while(temp[off] != '\0');
  391.  
  392.                 if(arg) temp = &temp[off+1];
  393.                 else break;
  394.           }
  395.  
  396.           macro = get_macro(pi,nmn);
  397.           if(macro == NULL) {
  398.             print_msg(pi, MSGTYPE_ERROR, "Macro %s is not defined !",nmn);
  399.             return(False);
  400.           }
  401.       free(nmn);
  402.         }
  403.     /* or else, we handle the macro as normal macro */
  404.     else {
  405.       line = malloc(strlen(rest_line) + 1);
  406.       if(!line) {
  407.         print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  408.         return(False);
  409.       }
  410.       strcpy(line, rest_line);
  411.       temp = line;
  412.       while(temp) {
  413.         macro_args[macro_arg_count++] = temp;
  414.         temp = get_next_token(temp, TERM_COMMA);
  415.       }
  416.         }
  417.   }
  418.  
  419.   if(pi->pass == PASS_1) {
  420.         macro_call = calloc(1, sizeof(struct macro_call));
  421.         if(!macro_call) {
  422.           print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  423.           return(False);
  424.         }
  425.         if(pi->last_macro_call)
  426.           pi->last_macro_call->next = macro_call;
  427.         else
  428.           pi->first_macro_call = macro_call;
  429.                
  430.         pi->last_macro_call = macro_call;
  431.         macro_call->line_number = pi->fi->line_number;
  432.         macro_call->include_file = pi->fi->include_file;
  433.         macro_call->macro = macro;
  434.         macro_call->prev_on_stack = pi->macro_call;
  435.                
  436.         if(macro_call->prev_on_stack) {
  437.           macro_call->nest_level = macro_call->prev_on_stack->nest_level + 1;
  438.           macro_call->prev_line_index = macro_call->prev_on_stack->line_index;
  439.         }
  440.   }
  441.   else {
  442.         for(macro_call = pi->first_macro_call; macro_call; macro_call = macro_call->next) {
  443.           if((macro_call->include_file->num == pi->fi->include_file->num) && (macro_call->line_number == pi->fi->line_number)) {
  444.                 if(pi->macro_call) {
  445.                 /* Find correct macro_call when using recursion and nesting */
  446.                   if(macro_call->prev_on_stack == pi->macro_call)
  447.                         if((macro_call->nest_level == (pi->macro_call->nest_level + 1)) && (macro_call->prev_line_index == pi->macro_call->line_index))
  448.                           break;
  449.                 }
  450.                 else break;
  451.           }
  452.         }
  453.         if(pi->list_line && pi->list_on) {
  454.           fprintf(pi->list_file, "C:%06x   +  %s\n", pi->cseg_addr, pi->list_line);
  455.           pi->list_line = NULL;
  456.         }
  457.   }
  458.  
  459.   macro_call->line_index = 0;
  460.   pi->macro_call = macro_call;
  461.   old_macro_line = pi->macro_line;
  462.                
  463.   //printf("\nconvert macro: '%s'\n",macro->name);
  464.  
  465.   for(pi->macro_line = macro->first_macro_line; pi->macro_line && ok; pi->macro_line = pi->macro_line->next) {
  466.     macro_call->line_index++;
  467.         if(GET_ARG(pi->args, ARG_LISTMAC))
  468.           pi->list_line = buff;
  469.         else
  470.           pi->list_line = NULL;
  471.                                
  472.         /* here we change jumps/calls within macro that corresponds to macro labels.
  473.            Only in case there is an entry in macro_label list */
  474.    
  475.     strcpy(buff,"\0");
  476.     macro_label = get_macro_label(pi->macro_line->line,macro);
  477.         if(macro_label) {
  478.       /* test if the right macro label has been found */
  479.           temp = strstr(pi->macro_line->line,macro_label->label);
  480.       c = strlen(macro_label->label);
  481.       if(temp[c] == ':') { /* it is a label definition */
  482.         macro_label->running_number++;
  483.         strncpy(buff, macro_label->label, c - 1);
  484.                 buff[c - 1] = 0;
  485.         i = strlen(buff) + 2; /* we set the process indeafter label */
  486.         /* add running number to it */
  487.                 strcpy(&buff[c-1],itoa(macro_label->running_number, tmp, 10));
  488.                 strcat(buff, ":\0");
  489.           }
  490.       else if(IS_HOR_SPACE(temp[c]) || IS_END_OR_COMMENT(temp[c]))      { /* it is a jump to a macro defined label */
  491.         strcpy(buff,pi->macro_line->line);
  492.         temp = strstr(buff, macro_label->label);
  493.         i = temp - buff + strlen(macro_label->label);
  494.         strncpy(temp, macro_label->label, c - 1);
  495.         strcpy(&temp[c-1], itoa(macro_label->running_number, tmp, 10));
  496.           }
  497.         }
  498.         else {
  499.       i = 0;
  500.         }
  501.  
  502.         /* here we check every character of current line */
  503.         for(j = i; pi->macro_line->line[i] != '\0'; i++) {
  504.           /* check for register place holders */
  505.           if(pi->macro_line->line[i] == '@') {
  506.                 i++;
  507.                 if(!isdigit(pi->macro_line->line[i]))
  508.                   print_msg(pi, MSGTYPE_ERROR, "@ must be followed by a number");
  509.         else if((pi->macro_line->line[i] - '0') >= macro_arg_count)
  510.           print_msg(pi, MSGTYPE_ERROR, "Missing macro argument (for @%c)", pi->macro_line->line[i]);
  511.         else {
  512.           /* and replace them with given registers */
  513.           strcat(&buff[j], macro_args[pi->macro_line->line[i] - '0']);
  514.           j += strlen(macro_args[pi->macro_line->line[i] - '0']);
  515.                 }
  516.           }
  517.       else if (pi->macro_line->line[i] == ';') {
  518.         strncat(buff, "\n", 1);
  519.         break;
  520.       }
  521.       else {
  522.         strncat(buff, &pi->macro_line->line[i], 1);
  523.           }
  524.         }
  525.    
  526.     ok = parse_line(pi, buff);
  527.     if(ok) {
  528.           if((pi->pass == PASS_2) && pi->list_line && pi->list_on)
  529.             fprintf(pi->list_file, "         %s\n", pi->list_line);
  530.           if(pi->error_count >= pi->max_errors) {
  531.             print_msg(pi, MSGTYPE_MESSAGE, "Maximum error count reached. Exiting...");
  532.             ok = False;
  533.           break;
  534.           }
  535.         }
  536.   }
  537.  
  538.   pi->macro_line = old_macro_line;
  539.   pi->macro_call = macro_call->prev_on_stack;
  540.   if(rest_line)
  541.     free(line);
  542.   return(ok);
  543. }
  544.  
  545. struct macro_label *get_macro_label(char *line, struct macro *macro)
  546. {
  547.         char *temp ;
  548.         struct macro_label *macro_label;
  549.        
  550.         for(macro_label = macro->first_label; macro_label; macro_label = macro_label->next) {
  551.             temp = strstr(line,macro_label->label);
  552.                 if(temp) {
  553.                         return macro_label;
  554.                 }
  555.         }
  556.         return NULL;
  557. }
  558.  
  559. /* end of macro.c */
  560.  
  561.