Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /***********************************************************************
  2. // Modified at line 252 to print out DW value in list file by davidrjburke@hotmail.com 11 Nov 2005
  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. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <ctype.h>
  32.  
  33. #include "misc.h"
  34. #include "args.h"
  35. #include "avra.h"
  36. #include "device.h"
  37.  
  38. enum
  39. {
  40.         DIRECTIVE_BYTE = 0,
  41.         DIRECTIVE_CSEG,
  42.         DIRECTIVE_CSEGSIZE,
  43.         DIRECTIVE_DB,
  44.         DIRECTIVE_DEF,
  45.         DIRECTIVE_DEVICE,
  46.         DIRECTIVE_DSEG,
  47.         DIRECTIVE_DW,
  48.         DIRECTIVE_ENDM,
  49.         DIRECTIVE_ENDMACRO,
  50.         DIRECTIVE_EQU,
  51.         DIRECTIVE_ESEG,
  52.         DIRECTIVE_EXIT,
  53.         DIRECTIVE_INCLUDE,
  54.         DIRECTIVE_INCLUDEPATH,
  55.         DIRECTIVE_LIST,
  56.         DIRECTIVE_LISTMAC,
  57.         DIRECTIVE_MACRO,
  58.         DIRECTIVE_NOLIST,
  59.         DIRECTIVE_ORG,
  60.         DIRECTIVE_SET,
  61.         DIRECTIVE_DEFINE,
  62.         DIRECTIVE_UNDEF,
  63.         DIRECTIVE_IFDEF,
  64.         DIRECTIVE_IFNDEF,
  65.         DIRECTIVE_IF,
  66.         DIRECTIVE_ELSE,
  67.         DIRECTIVE_ELSEIF,                       /* B.A. : The Atmel AVR Assembler version 1.71 and later use ELSEIF and not ELIF */
  68.         DIRECTIVE_ELIF,                
  69.         DIRECTIVE_ENDIF,
  70.         DIRECTIVE_MESSAGE,
  71.         DIRECTIVE_WARNING,
  72.         DIRECTIVE_ERROR,
  73.         DIRECTIVE_PRAGMA,
  74.         DIRECTIVE_COUNT
  75. };
  76.  
  77. char *directive_list[] =
  78. {
  79.         "BYTE",
  80.         "CSEG",
  81.         "CSEGSIZE",
  82.         "DB",
  83.         "DEF",
  84.         "DEVICE",
  85.         "DSEG",
  86.         "DW",
  87.         "ENDM",
  88.         "ENDMACRO",
  89.         "EQU",
  90.         "ESEG",
  91.         "EXIT",
  92.         "INCLUDE",
  93.         "INCLUDEPATH",
  94.         "LIST",
  95.         "LISTMAC",
  96.         "MACRO",
  97.         "NOLIST",
  98.         "ORG",
  99.         "SET",
  100.         "DEFINE",
  101.         "UNDEF",
  102.         "IFDEF",
  103.         "IFNDEF",
  104.         "IF",
  105.         "ELSE",
  106.         "ELSEIF",               /* B.A. : The Atmel AVR Assembler version 1.71 and later use ELSEIF and not ELIF */
  107.         "ELIF",
  108.         "ENDIF",
  109.         "MESSAGE",
  110.         "WARNING",
  111.         "ERROR",
  112.         "PRAGMA"
  113. };
  114.  
  115.  
  116. int parse_directive(struct prog_info *pi)
  117. {
  118.         int directive;
  119.         int ok = True;
  120.         int i;
  121.         char *next, *data;
  122.         struct file_info *fi_bak;
  123.  
  124.         struct def *def;
  125.         struct data_list *incpath, *dl;
  126.  
  127.         next = get_next_token(pi->fi->scratch, TERM_SPACE);
  128.  
  129.         for(i = 0; pi->fi->scratch[i] != '\0'; i++) {
  130.                 pi->fi->scratch[i] = toupper(pi->fi->scratch[i]);
  131.         }
  132.         directive = get_directive_type(pi->fi->scratch + 1);
  133.         if(directive == -1) {
  134.                 print_msg(pi, MSGTYPE_ERROR, "Unknown directive: %s", pi->fi->scratch);
  135.                 return(True);
  136.         }
  137.         switch(directive) {
  138.                 case DIRECTIVE_BYTE:
  139.                         if(!next) {
  140.                                 print_msg(pi, MSGTYPE_ERROR, ".BYTE needs a size operand");
  141.                                 return(True);
  142.                         }
  143.                         if(pi->segment != SEGMENT_DATA)
  144.                                 print_msg(pi, MSGTYPE_ERROR, ".BYTE directive can only be used in data segment (.DSEG)");
  145.                         get_next_token(next, TERM_END);
  146.                         if(!get_expr(pi, next, &i))
  147.                                 return(False);
  148.                         if((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
  149.                                 fprintf(pi->list_file, "D:%06x    %s\n", pi->dseg_addr, pi->list_line);
  150.                                 pi->list_line = NULL;
  151.                         }
  152.                         pi->dseg_addr += i;
  153.                         if(pi->pass == PASS_1)
  154.                                 pi->dseg_count += i;
  155.                         break;
  156.                 case DIRECTIVE_CSEG:
  157.                         fix_orglist(pi);
  158.                         pi->segment = SEGMENT_CODE;
  159.                         def_orglist(pi);
  160.                         break;
  161.                 case DIRECTIVE_CSEGSIZE:
  162.                         break;
  163.                 case DIRECTIVE_DB:
  164.                         if((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
  165.                                 fprintf(pi->list_file, "          %s\n", pi->list_line);
  166.                                 pi->list_line = NULL;
  167.                         }
  168.                         return(parse_db(pi, next));
  169. //                      break;
  170.                 /* Directive .def */
  171.                 case DIRECTIVE_DEF:
  172.                         if(!next) {
  173.                                 print_msg(pi, MSGTYPE_ERROR, ".DEF needs an operand");
  174.                                 return(True);
  175.                         }
  176.                         data = get_next_token(next, TERM_EQUAL);
  177.                         if(!(data && (tolower(data[0]) == 'r') && isdigit(data[1]))) {
  178.                                 print_msg(pi, MSGTYPE_ERROR, "%s needs a register (e.g. .def BZZZT = r16)", next);
  179.                                 return(True);
  180.                         }
  181.                         i = atoi(&data[1]);
  182.                         /* check range of given register */
  183.                         if(i > 31)
  184.                                 print_msg(pi, MSGTYPE_ERROR, "R%d is not a valid register", i);
  185.                         /* check if this reg is already assigned */
  186.                         for(def = pi->first_def; def; def = def->next) {
  187.                                 if(def->reg == i && pi->pass == PASS_1 && !pi->NoRegDef) {
  188.                                     print_msg(pi, MSGTYPE_WARNING, "r%d is already assigned to '%s'!", i, def->name);
  189.                                         return(True);
  190.                                 }
  191.                         }
  192.                         /* check if this regname is already defined */
  193.                         for(def = pi->first_def; def; def = def->next) {
  194.                                 if(!nocase_strcmp(def->name, next)) {
  195.                                         if(pi->pass == PASS_1 && !pi->NoRegDef) {
  196.                                                 print_msg(pi, MSGTYPE_WARNING, "'%s' is already assigned as r%d but will now be set to r%i!", next, def->reg, i);
  197.                                         }
  198.                                         def->reg = i;
  199.                                         return(True);
  200.                                 }
  201.                         }
  202.                         /* B.A.: Check, if symbol is already defined as a label or constant */
  203.                         if(pi->pass == PASS_2) {
  204.                                 if(get_label(pi,next,NULL))
  205.                                         print_msg(pi, MSGTYPE_WARNING, "Name '%s' is used for a register and a label", next);
  206.                                 if(get_constant(pi,next,NULL))
  207.                                         print_msg(pi, MSGTYPE_WARNING, "Name '%s' is used for a register and a constant", next);
  208.                         }
  209.  
  210.                         def = malloc(sizeof(struct def));
  211.                         if(!def) {
  212.                                 print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  213.                                 return(False);
  214.                         }
  215.                         def->next = NULL;
  216.                         if(pi->last_def)
  217.                                 pi->last_def->next = def;
  218.                         else
  219.                                 pi->first_def = def;
  220.                         pi->last_def = def;
  221.                         def->name = malloc(strlen(next) + 1);
  222.                         if(!def->name) {
  223.                                 print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  224.                                 return(False);
  225.                         }
  226.                         strcpy(def->name, next);
  227.                         def->reg = i;
  228.                         break;
  229.                 case DIRECTIVE_DEVICE:
  230.                         if(pi->pass == PASS_2)
  231.                                 return(True);
  232.                         if(!next) {
  233.                                 print_msg(pi, MSGTYPE_ERROR, ".DEVICE needs an operand");
  234.                                 return(True);
  235.                         }
  236.                         if(pi->device->name!=NULL) { /* B.A.: Check for multiple device definitions */
  237.                                 print_msg(pi, MSGTYPE_ERROR, "More than one .DEVICE definition");
  238.                         }
  239.                         if(pi->cseg_count || pi->dseg_count || pi->eseg_count) { /* B.A.: Check if something was already assembled */
  240.                                 print_msg(pi, MSGTYPE_ERROR, ".DEVICE definition must be before any code lines");
  241.                         } else {
  242.                                 if(pi->cseg_addr  || pi->eseg_addr || (pi->dseg_addr != pi->device->ram_start)) { /* B.A.: Check if something was already assembled */
  243.                                         print_msg(pi, MSGTYPE_ERROR, ".DEVICE definition must be before any .ORG directive");
  244.                                 }
  245.                         }
  246.  
  247.                         get_next_token(next, TERM_END);
  248.                         pi->device = get_device(pi,next);
  249.                         if(!pi->device) {
  250.                                 print_msg(pi, MSGTYPE_ERROR, "Unknown device: %s", next);
  251.                                 pi->device = get_device(pi,NULL); /* B.A.: Fix segmentation fault if device is unknown */
  252.                         }
  253.  
  254.                         /* Now that we know the device type, we can
  255.                          * start memory allocation from the correct offsets.
  256.                          */
  257.                         fix_orglist(pi);
  258.                         pi->cseg_addr = 0;
  259.                         pi->dseg_addr = pi->device->ram_start;
  260.                         pi->eseg_addr = 0;
  261.                         def_orglist(pi);
  262.                         break;
  263.                 case DIRECTIVE_DSEG:
  264.                         fix_orglist(pi);
  265.                         pi->segment = SEGMENT_DATA;
  266.                         def_orglist(pi);
  267.                         if(pi->device->ram_size == 0) {
  268.                                 print_msg(pi, MSGTYPE_ERROR, "Can't use .DSEG directive because device has no RAM");
  269.                         }
  270.                         break;
  271.                 case DIRECTIVE_DW:
  272.                         if(pi->segment == SEGMENT_DATA) {
  273.                                 print_msg(pi, MSGTYPE_ERROR, "Can't use .DW directive in data segment (.DSEG)");
  274.                                 return(True);
  275.                         }
  276.                         while(next) {
  277.                                 data = get_next_token(next, TERM_COMMA);
  278.                                 if(pi->pass == PASS_2) {
  279.                                   if(!get_expr(pi, next, &i))
  280.                                     return(False);
  281.                                   if((i < -32768) || (i > 65535))
  282.                                     print_msg(pi, MSGTYPE_WARNING, "Value %d is out of range (-32768 <= k <= 65535). Will be masked", i);
  283.                 }
  284.                                 if(pi->segment == SEGMENT_EEPROM) {
  285.                                         if(pi->pass == PASS_2) {
  286.                                                 write_ee_byte(pi, pi->eseg_addr, (unsigned char)i);
  287.                                                 write_ee_byte(pi, pi->eseg_addr + 1, (unsigned char)(i >> 8));
  288.                                         }
  289.                                         pi->eseg_addr += 2;
  290.                                         if(pi->pass == PASS_1)
  291.                                                 pi->eseg_count += 2;
  292.                                 }
  293.                                 // Modified by David Burke to print DW word in list file 4/Nov/2005
  294.                                 else {
  295.                                         if((pi->pass == PASS_2) && pi->hfi) {
  296.                                                 write_prog_word(pi, pi->cseg_addr, i);
  297.                                                 // Actual fiddling
  298.                                                 if((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
  299.                                                         fprintf(pi->list_file, "          %s\n", pi->list_line);
  300.                                                         pi->list_line = NULL;
  301.                                                         fprintf(pi->list_file, "C:%06x %04x\n", pi->cseg_addr,i);
  302.                                                 }
  303.                                         }
  304.                                         pi->cseg_addr++;
  305.                                         if(pi->pass == PASS_1) pi->cseg_count++;
  306.                                 }
  307.                                 // End of Modification by David Burke
  308.                                 next = data;
  309.                         }
  310.                         break;
  311.                 case DIRECTIVE_ENDM:
  312.                 case DIRECTIVE_ENDMACRO:
  313.                         print_msg(pi, MSGTYPE_ERROR, "No .MACRO found before .ENDMACRO");
  314.                         break;
  315.                 case DIRECTIVE_EQU:
  316.                         if(!next) {
  317.                                 print_msg(pi, MSGTYPE_ERROR, ".EQU needs an operand");
  318.                                 return(True);
  319.                         }
  320.                         data = get_next_token(next, TERM_EQUAL);
  321.                         if(!data) {
  322.                                 print_msg(pi, MSGTYPE_ERROR, "%s needs an expression (e.g. .EQU BZZZT = 0x2a)", next);
  323.                                 return(True);
  324.                         }
  325.                         get_next_token(data, TERM_END);
  326.                         if(!get_expr(pi, data, &i))
  327.                                 return(False);
  328.                         if(test_label(pi,next,"%s have already been defined as a label")!=NULL)
  329.                                 return(True);
  330.                         if(test_variable(pi,next,"%s have already been defined as a .SET variable")!=NULL)
  331.                                 return(True);
  332.                         /* B.A. : New. Forward references allowed. But check, if everything is ok ... */
  333.                         if(pi->pass==PASS_1) { /* Pass 1 */
  334.                                 if(test_constant(pi,next,"Can't redefine constant %s, use .SET instead")!=NULL)
  335.                                         return(True);
  336.                                 if(def_const(pi, next, i)==False)
  337.                                         return(False);
  338.                         } else { /* Pass 2 */
  339.                                 int j;
  340.                                 if(get_constant(pi, next, &j)==False) {   /* Defined in Pass 1 and now missing ? */
  341.                                         print_msg(pi, MSGTYPE_ERROR, "Constant %s is missing in pass 2", next);
  342.                                         return(False);
  343.                                 }
  344.                                 if(i != j) {
  345.                                         print_msg(pi, MSGTYPE_ERROR, "Constant %s changed value from %d in pass1 to %d in pass 2", next,j,i);
  346.                                         return(False);
  347.                                 }
  348.                                 /* OK. Definition is unchanged */
  349.                         }
  350.                         if((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
  351.                                 fprintf(pi->list_file, "          %s\n", pi->list_line);
  352.                                 pi->list_line = NULL;
  353.                         }
  354.                         break;
  355.                 case DIRECTIVE_ESEG:
  356.                         fix_orglist(pi);
  357.                         pi->segment = SEGMENT_EEPROM;
  358.                         def_orglist(pi);
  359.                         if(pi->device->eeprom_size == 0) {
  360.                                 print_msg(pi, MSGTYPE_ERROR, "Can't use .ESEG directive because device has no EEPROM");
  361.                         }
  362.                         break;
  363.                 case DIRECTIVE_EXIT:
  364.                         pi->fi->exit_file = True;
  365.                         break;
  366.                 /*** .include ***/
  367.                 case DIRECTIVE_INCLUDE:    
  368.                         if(!next) {
  369.                                 print_msg(pi, MSGTYPE_ERROR, "Nothing to include");
  370.                                 return(True);
  371.                         }
  372.                         next = term_string(pi, next);
  373.                         if((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
  374.                                 fprintf(pi->list_file, "          %s\n", pi->list_line);
  375.                                 pi->list_line = NULL;
  376.                         }
  377.                         // Test if include is in local directory
  378.                         ok = test_include(next);
  379.                         data = NULL;
  380.                         if(!ok)
  381.                                 for(incpath = GET_ARG(pi->args, ARG_INCLUDEPATH); incpath && !ok; incpath = incpath->next) {
  382.                                         i = strlen(incpath->data);
  383.                                         if(data)
  384.                                                 free(data);
  385.                                         data = malloc(i + strlen(next) + 2);
  386.                                         if(!data) {
  387.                                                 print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  388.                                                 return(False);
  389.                                         }
  390.                                         strcpy(data, incpath->data);
  391.                                         if((data[i - 1] != '\\') && (data[i - 1] != '/'))
  392.                                                 data[i++] = '/';
  393.                                         strcpy(&data[i], next);
  394.                     //printf("testing: %s\n", data);
  395.                                         ok = test_include(data);
  396.                                 }
  397.                         if(ok) {
  398.                                 fi_bak = pi->fi;
  399.                                 ok = parse_file(pi, data ? data : next);
  400.                                 pi->fi = fi_bak;
  401.                         }
  402.                         else
  403.                                 print_msg(pi, MSGTYPE_ERROR, "Cannot find include file: %s", next);
  404.                         if(data)
  405.                                 free(data);
  406.                         break;
  407.                 /*** .includepath ***/
  408.                 case DIRECTIVE_INCLUDEPATH:
  409.                         if(!next) {
  410.                                 print_msg(pi, MSGTYPE_ERROR, ".INCLUDEPATH needs an operand");
  411.                                 return(True);
  412.                         }
  413.                         data = get_next_token(next, TERM_SPACE);
  414.                         if(data) {
  415.                                 print_msg(pi, MSGTYPE_ERROR, ".INCLUDEPATH needs an operand!!!");
  416.                                 get_next_token(data, TERM_END);
  417.                                 if(!get_expr(pi, data, &i))
  418.                                         return(False);
  419.                         }
  420.                         next = term_string(pi, next);
  421.                         /* get arg list start pointer */
  422.                         incpath = GET_ARG(pi->args, ARG_INCLUDEPATH);
  423.         /* search for last element */
  424.         if(incpath == NULL) {
  425.                 dl = malloc(sizeof(struct data_list));
  426.                 data = malloc(strlen(next)+1);
  427.                 if(dl && data) {
  428.                         dl->next = NULL;
  429.                         strcpy(data, next);
  430.                         dl->data = data;
  431.             SET_ARG(pi->args, ARG_INCLUDEPATH, dl);
  432.                 }
  433.                 else {
  434.                         printf("Error: Unable to allocate memory\n");
  435.                         return(False);
  436.                 }
  437.         }
  438.         else
  439.           add_arg(&incpath, next);
  440.                         break;
  441.                 case DIRECTIVE_LIST:
  442.                         if(pi->pass == PASS_2)
  443.                                 if(pi->list_file)
  444.           pi->list_on = True;
  445.                         break;
  446.                 case DIRECTIVE_LISTMAC:
  447.                         if(pi->pass == PASS_2)
  448.                                 SET_ARG(pi->args, ARG_LISTMAC, True);
  449.                         break;
  450.                 case DIRECTIVE_MACRO:
  451.                         return(read_macro(pi, next));
  452. //                      break;
  453.                 case DIRECTIVE_NOLIST:
  454.                         if(pi->pass == PASS_2)
  455.                                 pi->list_on = False;
  456.                         break;
  457.                 case DIRECTIVE_ORG:
  458.                         if(!next) {
  459.                                 print_msg(pi, MSGTYPE_ERROR, ".ORG needs an operand");
  460.                                 return(True);
  461.                         }
  462.                         get_next_token(next, TERM_END);
  463.                         if(!get_expr(pi, next, &i))
  464.                                 return(False);
  465.                         fix_orglist(pi);                /* Update last segment */
  466.                         switch(pi->segment) {
  467.                                 case SEGMENT_CODE:
  468.                                         pi->cseg_addr = i;
  469.                                         break;
  470.                                 case SEGMENT_DATA:
  471.                                         pi->dseg_addr = i;
  472.                                         break;
  473.                                 case SEGMENT_EEPROM:
  474.                                         pi->eseg_addr = i;
  475.                         }
  476.                         def_orglist(pi);                /* Create new segment */
  477.                         if(pi->fi->label)
  478.                                 pi->fi->label->value = i;
  479.                         if((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
  480.                                 fprintf(pi->list_file, "          %s\n", pi->list_line);
  481.                                 pi->list_line = NULL;
  482.                         }
  483.                         break;
  484.                 case DIRECTIVE_SET:
  485.                         if(!next) {
  486.                                 print_msg(pi, MSGTYPE_ERROR, ".SET needs an operand");
  487.                                 return(True);
  488.                         }
  489.                         data = get_next_token(next, TERM_EQUAL);
  490.                         if(!data) {
  491.                                 print_msg(pi, MSGTYPE_ERROR, "%s needs an expression (e.g. .SET BZZZT = 0x2a)", next);
  492.                                 return(True);
  493.                         }
  494.                         get_next_token(data, TERM_END);
  495.                         if(!get_expr(pi, data, &i))
  496.                                 return(False);
  497.  
  498.       if(test_label(pi,next,"%s have already been defined as a label")!=NULL)
  499.         return(True);
  500.       if(test_constant(pi,next,"%s have already been defined as a .EQU constant")!=NULL)
  501.         return(True);
  502.       return(def_var(pi, next, i));
  503. //                      break;
  504.                 case DIRECTIVE_DEFINE:
  505.                         if(!next) {
  506.                                 print_msg(pi, MSGTYPE_ERROR, ".DEFINE needs an operand");
  507.                                 return(True);
  508.                         }
  509.                         data = get_next_token(next, TERM_SPACE);
  510.                         if(data) {
  511.                                 get_next_token(data, TERM_END);
  512.                                 if(!get_expr(pi, data, &i))
  513.                                         return(False);
  514.                         }
  515.                         else
  516.                                 i = 1;
  517.       if(test_label(pi,next,"%s have already been defined as a label")!=NULL)
  518.         return(True);
  519.       if(test_variable(pi,next,"%s have already been defined as a .SET variable")!=NULL)
  520.         return(True);
  521.                         /* B.A. : New. Forward references allowed. But check, if everything is ok ... */
  522.                         if(pi->pass==PASS_1) { /* Pass 1 */
  523.               if(test_constant(pi,next,"Can't redefine constant %s, use .SET instead")!=NULL)
  524.               return(True);
  525.               if(def_const(pi, next, i)==False)
  526.               return(False);
  527.                         } else { /* Pass 2 */
  528.                                 int j;
  529.                                 if(get_constant(pi, next, &j)==False) {   /* Defined in Pass 1 and now missing ? */
  530.               print_msg(pi, MSGTYPE_ERROR, "Constant %s is missing in pass 2", next);
  531.               return(False);
  532.                                 }
  533.                                 if(i != j) {
  534.               print_msg(pi, MSGTYPE_ERROR, "Constant %s changed value from %d in pass1 to %d in pass 2", next,j,i);
  535.               return(False);
  536.                                 }
  537.                                 /* OK. Definition is unchanged */
  538.                         }
  539.                         if((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
  540.                                 fprintf(pi->list_file, "          %s\n", pi->list_line);
  541.                                 pi->list_line = NULL;
  542.                         }
  543.                         break;
  544.                 case DIRECTIVE_PRAGMA:
  545. #if 0
  546.                         may_do_something_with_pragma_someday();
  547. #else
  548.                         // if ( !flag_no_warnings )
  549.                         print_msg(pi, MSGTYPE_MESSAGE, "PRAGMA directives currently ignored");
  550. #endif
  551.                         break;
  552.                 case DIRECTIVE_UNDEF: // TODO
  553.                         break;
  554.                 case DIRECTIVE_IFDEF:
  555.                         if(!next)
  556.                                 {
  557.                                 print_msg(pi, MSGTYPE_ERROR, ".IFDEF needs an operand");
  558.                                 return(True);
  559.                                 }
  560.                         get_next_token(next, TERM_END);
  561.                         /* B.A. : Forward referenc is not allowed for ifdef and ifndef */
  562.                         /* Store undefined symbols in blacklist in pass1 and check, if they are still undefined in pass2 */
  563.                         if(get_symbol(pi, next, NULL)) {
  564. #if 0
  565.                                         // If it's not defined in the first pass, but was defined later
  566.                                         // then it should be considered OK with regards to ifdef..endif and
  567.                                         // ifndef..endif code sections. Removed this code.
  568.                                 if(pi->pass==PASS_2) { /* B.A. : 'Still undefined'-test in pass 2 */
  569.                           if(test_blacklist(pi,next,"Forward reference (%s) not allowed in .ifdef directive")!=NULL)
  570.                                         return(False);
  571.                                 }
  572. #else
  573.                                 pi->conditional_depth++;
  574. #endif
  575.                         } else {
  576.                                 if(pi->pass==PASS_1) { /* B.A. : Store undefined symbols in pass 1 */
  577.           if(def_blacklist(pi, next)==False)
  578.                 return(False);
  579.                                 }
  580.                                 if(!spool_conditional(pi, False))
  581.                 return(False);
  582.                         }
  583.                         break;
  584.                 case DIRECTIVE_IFNDEF:
  585.                         if(!next)
  586.                                 {
  587.                                 print_msg(pi, MSGTYPE_ERROR, ".IFNDEF needs an operand");
  588.                                 return(True);
  589.                                 }
  590.                         get_next_token(next, TERM_END);
  591.                         /* B.A. : Forward referenc is not allowed for ifdef and ifndef */
  592.                         /* Store undefined symbols in blacklist in pass1 and check, if they are still undefined in pass2 */
  593.                         if(get_symbol(pi, next, NULL))
  594.                         {
  595. #if 0
  596.                                 if(pi->pass==PASS_2) { /* B.A. : 'Still undefined'-test in pass 2 */
  597.                                         // If it's not defined in the first pass, but was defined later
  598.                                         // then it should be considered OK with regards to ifdef..endif and
  599.                                         // ifndef..endif code sections. Removed this code.
  600.                           if(test_blacklist(pi,next,"Forward reference (%s) not allowed in .ifndef directive")!=NULL)
  601.                                         return(False);
  602.                                 }
  603.                                 if(!spool_conditional(pi, False))
  604.                                         return(False);
  605. #else
  606.                                 pi->conditional_depth++;
  607. #endif
  608.                                 }
  609.                         else {
  610.                                 if(pi->pass==PASS_1) { /* B.A. : Store undefined symbols in pass 1 */
  611.                           if(def_blacklist(pi, next)==False)
  612.                                 return(False);
  613.                                 }
  614.                                 pi->conditional_depth++;
  615.                         }
  616.                         break;
  617.                 case DIRECTIVE_IF:
  618.                         if(!next)
  619.                                 {
  620.                                 print_msg(pi, MSGTYPE_ERROR, ".IF needs an expression");
  621.                                 return(True);
  622.                                 }
  623.                         get_next_token(next, TERM_END);
  624.                         if(!get_expr(pi, next, &i))
  625.                                 return(False);
  626.                         if(i)
  627.                                 pi->conditional_depth++;
  628.                         else
  629.                                 {
  630.                                 if(!spool_conditional(pi, False))
  631.                                         return(False);
  632.                                 }
  633.                         break;
  634.                 case DIRECTIVE_ELSE:
  635.                 case DIRECTIVE_ELIF:
  636.                 case DIRECTIVE_ELSEIF:
  637.                         if(!spool_conditional(pi, True))
  638.                                 return(False);
  639.                         break;
  640.                 case DIRECTIVE_ENDIF:
  641.                         if(pi->conditional_depth == 0)
  642.                                 print_msg(pi, MSGTYPE_ERROR, "Too many .ENDIF");
  643.                         else
  644.                                 pi->conditional_depth--;
  645.                         break;
  646.                 case DIRECTIVE_MESSAGE:
  647.                         if(pi->pass == PASS_1)
  648.                                 return(True);
  649.                         if(!next) {
  650.                                 print_msg(pi, MSGTYPE_ERROR, "No message parameter supplied");
  651.                                 return(True);
  652.                         }
  653.                         /* B.A : Extended .MESSAGE. Now a comma separated list like in .db is possible and not only a string */
  654.                         print_msg(pi, MSGTYPE_MESSAGE_NO_LF, NULL);     /* Prints Line Header (filename, linenumber) without trailing /n */
  655.                     while(next) {       /* Modified code from parse_db(). Thank you :-) */
  656.                           data = get_next_token(next, TERM_COMMA);
  657.                                 if(next[0] == '\"') {   /* string parsing */
  658.                       next = term_string(pi, next);
  659.                                   print_msg(pi, MSGTYPE_APPEND,"%s",next);
  660.                               while(*next != '\0') {
  661.                                         next++;
  662.                           }
  663.                                 } else {
  664.                           if(!get_expr(pi, next, &i)) {
  665.                                         print_msg(pi, MSGTYPE_APPEND,"\n"); /* Add newline */
  666.                             return(False);
  667.                                   }
  668.                                   print_msg(pi, MSGTYPE_APPEND,"0x%02X",i);
  669.                    }                   
  670.                 next = data;
  671.                     }
  672.                         print_msg(pi, MSGTYPE_APPEND,"\n"); /* Add newline */
  673.                         break;
  674.                 case DIRECTIVE_WARNING:
  675.                         if(pi->pass == PASS_1)
  676.                                 return(True);
  677.                         if(!next) {
  678.                                 print_msg(pi, MSGTYPE_ERROR, "No warning string supplied");
  679.                                 return(True);
  680.                         }
  681.                         next = term_string(pi, next);
  682.                         print_msg(pi, MSGTYPE_WARNING, next);
  683.                         break;
  684.                 case DIRECTIVE_ERROR:          
  685.                         if(!next) { /* B.A : Fix segfault bug if .error without parameter was used */
  686.                                 print_msg(pi, MSGTYPE_ERROR, "No error string supplied");
  687.                                 return(True);
  688.                     }
  689.                         next = term_string(pi, next);          
  690.                         /* B.A. : Don't use this. It may cause segfaults if the 'next' contains printf control sequences %s,%d etc.
  691.                         print_msg(pi, MSGTYPE_ERROR, next);
  692.                         */
  693.                         print_msg(pi, MSGTYPE_ERROR,"%s",next); /* B.A. : This is '%s' save :-) */
  694.             pi->error_count = pi->max_errors;
  695.                         if(pi->pass == PASS_1)
  696.                                 return(True);
  697.                         break;
  698.         }
  699.         return(ok);
  700. }
  701.  
  702.  
  703. int get_directive_type(char *directive) {
  704.   int i;
  705.  
  706.   for(i = 0; i < DIRECTIVE_COUNT; i++) {
  707.         if(!strcmp(directive, directive_list[i])) return(i);
  708.   }
  709.   return(-1);
  710. }
  711.  
  712.  
  713. char *term_string(struct prog_info *pi, char *string) {
  714.   int i;
  715.  
  716.   if(string[0] != '\"') {
  717.           print_msg(pi, MSGTYPE_ERROR, "String must be enclosed in \"-signs");
  718.   }
  719.   else {
  720.           string++;
  721.   }
  722.   /* skip to the end of the string*/
  723.   for(i = 0; (string[i] != '\"') && !((string[i] == 10) || (string[i] == 13) || (string[i] == '\0')); i++);
  724.   if((string[i] == 10) || (string[i] == 13) || (string[i] == '\0')) {
  725.           print_msg(pi, MSGTYPE_ERROR, "String is missing a closing \"-sign");
  726.   }
  727.   string[i] = '\0'; /* and terminate it where the " was */
  728.   return(string);
  729. }
  730.  
  731. /* Parse data byte directive */
  732. int parse_db(struct prog_info *pi, char *next) {
  733.   int i;
  734.   int count;
  735.   char *data;
  736.   char prev = 0;
  737.  
  738.   /* check if .db is allowed in this segment type */
  739.   if(pi->segment == SEGMENT_DATA) {
  740.           print_msg(pi, MSGTYPE_ERROR, "Can't use .DB directive in data segment (.DSEG) !");
  741.           return(True);
  742.   }
  743.  
  744.   count = 0;
  745.   if(pi->pass == PASS_2 && pi->list_on) {
  746.     if(pi->segment == SEGMENT_EEPROM)
  747.       fprintf(pi->list_file, "E:%06X ", pi->eseg_addr);
  748.     if(pi->segment == SEGMENT_CODE)
  749.       fprintf(pi->list_file, "C:%06X ", pi->cseg_addr);
  750.   }
  751.   /* get each db token */
  752.   while(next) {
  753.         data = get_next_token(next, TERM_COMMA);
  754.         /* string parsing */
  755.         if(next[0] == '\"') {
  756.             next = term_string(pi, next);
  757.             while(*next != '\0') {
  758.                 count++;
  759.                 write_db(pi, *next, &prev, count);
  760.                 if(pi->pass == PASS_2 && pi->list_on)
  761.                         fprintf(pi->list_file, "%02X", (unsigned char)*next);   // B.A.: Patch for chars with bit 7 = 1 (Example: °)
  762.                 if((unsigned char)*next > 127 && pi->pass == PASS_2)
  763.                         print_msg(pi, MSGTYPE_WARNING, "Found .DB string with characters > code 127. Be careful !"); // B.A.: Print warning for codes > 127
  764.                 next++;
  765.             }
  766.         }
  767.         else {
  768.             if(pi->pass == PASS_2) {
  769.                 if(!get_expr(pi, next, &i))
  770.                         return(False);
  771.                 if((i < -128) || (i > 255))
  772.                         print_msg(pi, MSGTYPE_WARNING, "Value %d is out of range (-128 <= k <= 255). Will be masked", i);
  773.                 if(pi->list_on) fprintf(pi->list_file, "%02X", i);
  774.             }
  775.             count++;
  776.             write_db(pi, (char)i, &prev, count);
  777.           }
  778.         next = data;
  779.   }
  780.   if(pi->segment == SEGMENT_CODE) {
  781.         if((count % 2) == 1) {
  782.           if(pi->pass == PASS_2)  {
  783.         if(pi->list_on) fprintf(pi->list_file, "00 ; zero byte added");
  784.                 write_prog_word(pi, pi->cseg_addr, prev & 0xFF);
  785.                 print_msg(pi, MSGTYPE_WARNING, "A .DB segment with an odd number of bytes is detected. A zero byte is added.");
  786.           }
  787.           pi->cseg_addr++;
  788.           if(pi->pass == PASS_1) {
  789.                 pi->cseg_count++;
  790.           }
  791.         }
  792.   }
  793.   if(pi->pass == PASS_2 && pi->list_on) {
  794.     fprintf(pi->list_file, "\n");
  795.     pi->list_line = NULL;
  796.   }
  797.   return(True);
  798. }
  799.  
  800.  
  801. void write_db(struct prog_info *pi, char byte, char *prev, int count) {
  802.   if(pi->segment == SEGMENT_EEPROM)     {
  803.     if(pi->pass == PASS_2) {
  804.       write_ee_byte(pi, pi->eseg_addr, byte);
  805.         }
  806.         pi->eseg_addr++;
  807.         if(pi->pass == PASS_1) {
  808.           pi->eseg_count++;
  809.         }
  810.   }
  811.   else { /* pi->segment == SEGMENT_CODE */
  812.     if((count % 2) == 0) {
  813.           if(pi->pass == PASS_2) {
  814.                 write_prog_word(pi, pi->cseg_addr, (byte << 8) | (*prev & 0xff));
  815.           }
  816.           pi->cseg_addr++;
  817.           if(pi->pass == PASS_1) {
  818.                 pi->cseg_count++;
  819.           }
  820.         }
  821.         else {
  822.           *prev = byte;
  823.         }
  824.   }
  825. }
  826.  
  827.  
  828. int spool_conditional(struct prog_info *pi, int only_endif) {
  829.         int current_depth = 0, do_next;
  830.  
  831.         if(pi->macro_line) {
  832.       while((pi->macro_line = pi->macro_line->next)) {
  833.                 pi->macro_call->line_index++;
  834.                 if(check_conditional(pi, pi->macro_line->line, &current_depth,  &do_next, only_endif)) {
  835.                   if(!do_next)
  836.                   return(True);
  837.                 }
  838.                 else
  839.                   return(False);
  840.           }
  841.           print_msg(pi, MSGTYPE_ERROR, "Found no closing .ENDIF in macro");
  842.         }
  843.         else {
  844.           while(fgets_new(pi,pi->fi->buff, LINEBUFFER_LENGTH, pi->fi->fp)) {
  845.           pi->fi->line_number++;
  846.             if(check_conditional(pi, pi->fi->buff, &current_depth,  &do_next, only_endif)) {
  847.                   if(!do_next)
  848.                   return(True);
  849.                 }
  850.                 else
  851.                   return(False);
  852.           }
  853.           if(feof(pi->fi->fp)) {
  854.                 print_msg(pi, MSGTYPE_ERROR, "Found no closing .ENDIF");
  855.                 return(True);
  856.       }
  857.           else {
  858.                 perror(pi->fi->include_file->name);
  859.                 return(False);
  860.           }
  861.         }
  862.         return(True);
  863. }
  864.  
  865.  
  866. int check_conditional(struct prog_info *pi, char *pbuff, int *current_depth, int *do_next, int only_endif)
  867. {
  868.         int i = 0;
  869.         char *next;
  870.         char linebuff[LINEBUFFER_LENGTH];
  871.  
  872.     strcpy(linebuff, pbuff); /* avoid cutting of the end of .elif line */
  873.  
  874.         *do_next = False;
  875.         while(IS_HOR_SPACE(linebuff[i]) && !IS_END_OR_COMMENT(linebuff[i])) i++;
  876. #if 0
  877.         if(linebuff[i] == '.') {
  878. #else
  879.         if((linebuff[i] == '.') || (linebuff[i] == '#')){
  880. #endif
  881.           i++;
  882.           if(!nocase_strncmp(&linebuff[i], "if", 2))
  883.             (*current_depth)++;
  884.           else
  885.                   if(!nocase_strncmp(&linebuff[i], "endif", 5)) {
  886.         if(*current_depth == 0)
  887.           return(True);
  888.                     (*current_depth)--;
  889.             } else
  890.                                 if(!only_endif && (*current_depth == 0)) {
  891.                                         /* B.A.  : Add ELSEIF  =  ELIF */
  892.                                         if((!nocase_strncmp(&linebuff[i], "else", 4)) && (nocase_strncmp(&linebuff[i], "elseif", 6))) {
  893.                                         pi->conditional_depth++;
  894.                         return(True);
  895.                                         }       else
  896.                                                 if((!nocase_strncmp(&linebuff[i], "elif", 4)) || (!nocase_strncmp(&linebuff[i], "elseif", 6))) {
  897.                                                   next = get_next_token(&linebuff[i], TERM_SPACE);
  898.                                                   if(!next) {
  899.                                                     print_msg(pi, MSGTYPE_ERROR, ".ELSEIF / .ELIF needs an operand");
  900.                                                           return(True);
  901.                                                   }
  902.                                                   get_next_token(next, TERM_END);
  903.                                                   if(!get_expr(pi, next, &i))
  904.                                                     return(False);
  905.                                                   if(i)
  906.                                                     pi->conditional_depth++;
  907.                                                   else {
  908.                                                                 if(!spool_conditional(pi, False))
  909.                                                                   return(False);
  910.                                                   }
  911.                                                   return(True);
  912.                                 }
  913.                         }
  914.         }
  915.         *do_next = True;
  916.         return(True);
  917. }
  918.  
  919. int test_include(const char *filename)
  920. {
  921.   FILE *fp;
  922.   fp = fopen(filename, "r");
  923.   if(fp)
  924.   {
  925.     fclose(fp);
  926.     return(True);
  927.   }
  928.   else
  929.     return(False);
  930. }
  931.  
  932. /* end of directiv.c */
  933.  
  934.  
  935.