moved mcs51 linker to as/link/mcs51
[fw/sdcc] / as / link / mcs51 / lklex.c
diff --git a/as/link/mcs51/lklex.c b/as/link/mcs51/lklex.c
new file mode 100644 (file)
index 0000000..7c48130
--- /dev/null
@@ -0,0 +1,640 @@
+/* lklex.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module      lklex.c
+ *
+ *     The module lklex.c contains the general lexical analysis
+ *     functions used to scan the text lines from the .rel files.
+ *
+ *     lklex.c contains the fllowing functions:
+ *             char    endline()
+ *             char    get()
+ *             VOID    getfid()
+ *             VOID    getid()
+ *             VOID    getSid()
+ *             int     as_getline()
+ *             int     getmap()
+ *             char    getnb()
+ *             int     more()
+ *             VOID    skip()
+ *             VOID    unget()
+ *
+ *     lklex.c contains no local variables.
+ */
+
+/*)Function    VOID    getid(id,c)
+ *
+ *             char *  id              a pointer to a string of
+ *                                     maximum length NCPS
+ *             int     c               mode flag
+ *                                     >=0     this is first character to
+ *                                             copy to the string buffer
+ *                                     <0      skip white space
+ *
+ *     The function getid() scans the current input text line
+ *     from the current position copying the next LETTER | DIGIT string
+ *     into the external string buffer (id).  The string ends when a non
+ *     LETTER or DIGIT character is found. The maximum number of
+ *     characters copied is NCPS.  If the input string is larger than
+ *     NCPS characters then the string is truncated, if the input string
+ *     is shorter than NCPS characters then the string is NULL filled.
+ *     If the mode argument (c) is >=0 then (c) is the first character
+ *     copied to the string buffer, if (c) is <0 then intervening white
+ *     space (SPACES and TABS) are skipped.
+ *
+ *     local variables:
+ *             char *  p               pointer to external string buffer
+ *             int     c               current character value
+ *
+ *     global variables:
+ *             char    ctype[]         a character array which defines the
+ *                                     type of character being processed.
+ *                                     This index is the character
+ *                                     being processed.
+ *
+ *     called functions:
+ *             char    get()           lklex.c
+ *             char    getnb()         lklex.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             use of getnb(), get(), and unget() updates the
+ *             global pointer ip the position in the current
+ *             input text line.
+ */
+
+VOID
+getid(id, c)
+register int c;
+char *id;
+{
+       register char *p;
+
+       if (c < 0) {
+               c = getnb();
+       }
+       p = id;
+       do {
+               if (p < &id[NCPS])
+                       *p++ = c;
+       } while (ctype[c=get()] & (LETTER|DIGIT));
+       unget(c);
+       while (p < &id[NCPS])
+               *p++ = 0;
+}
+
+/*)Function    VOID    getSid (char *id)
+ *
+ *             char *  id              a pointer to a string of
+ *                                     maximum length NCPS
+ *
+ *  getSid is derived from getid. It is called from newsym()
+ *  in lksym.c, when an S-record has to be scanned. getSid accepts
+ *  much more characters than getid, which is necessary for SDCC.
+ * 
+ *     The function getSid() scans the current input text line
+ *     from the current position copying the next string
+ *     into the external string buffer (id).  The string ends when a space
+ *  character (space, tab, \0) is found. The maximum number of
+ *     characters copied is NCPS.  If the input string is larger than
+ *     NCPS characters then the string is truncated, if the input string
+ *     is shorter than NCPS characters then the string is NULL filled.
+ *     Intervening white space (SPACES and TABS) are skipped.
+ *
+ *     local variables:
+ *             char *  p               pointer to external string buffer
+ *             int     c               current character value
+ *
+ *     global variables:
+ *             char    ctype[]         a character array which defines the
+ *                                     type of character being processed.
+ *                                     This index is the character
+ *                                     being processed.
+ *
+ *     called functions:
+ *             char    get()           lklex.c
+ *             char    getnb()         lklex.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             use of getnb(), get(), and unget() updates the
+ *             global pointer ip the position in the current
+ *             input text line.
+ */
+
+VOID
+getSid (id)
+char *id;
+{
+  register int c;
+       register char *p;
+
+  c = getnb();
+       p = id;
+       do {
+               if (p < &id[NCPS])
+                       *p++ = c;
+               c = get();
+       } while (c != '\0' && c != ' ' && c != '\t');
+       unget(c);
+       while (p < &id[NCPS])
+               *p++ = 0;
+}
+
+/*)Function    VOID    getfid(fid,c)
+ *
+ *             char *  str             a pointer to a string of
+ *                                     maximum length PATH_MAX
+ *             int     c               this is first character to
+ *                                     copy to the string buffer
+ *
+ *     The function getfid() scans the current input text line from
+ *     the current position copying the next string into the external
+ *     string buffer (str).  The string ends when end of line is found.
+ *     Trailing spacers are removed. The maximum number of characters
+ *     copied is PATH_MAX. If the input string is larger than PATH_MAX
+ *     characters then the string is truncated. The string is NULL
+ *     terminated.
+ *
+ *     local variables:
+ *             char *  p               pointer to external string buffer
+ *             int     c               current character value
+ *
+ *     global variables:
+ *             char    ctype[]         a character array which defines the
+ *                                     type of character being processed.
+ *                                     This index is the character
+ *                                     being processed.
+ *
+ *     called functions:
+ *             char    get()           lklex.c
+ *
+ *     side effects:
+ *             use of get() updates the global pointer ip
+ *             the position in the current input text line.
+ */
+
+VOID
+getfid(str, c)
+register int c;
+char *str;
+{
+       register char *p;
+
+       p = str;
+       do
+       {
+               if (p < &str[PATH_MAX-1])
+                       *p++ = c;
+               c = get();
+               if (c == ';')
+                       while (c)
+                               c = get();
+       } while (c);
+       /* trim trailing spaces */
+       --p;
+       while (p >= str && ctype[(int)*p] == SPACE)
+               --p;
+       /* terminate the string */
+       *(++p) = '\0';
+}
+
+/*)Function    char    getnb()
+ *
+ *     The function getnb() scans the current input text
+ *     line returning the first character not a SPACE or TAB.
+ *
+ *     local variables:
+ *             int     c               current character from input
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             char    get()           lklex.c
+ *
+ *     side effects:
+ *             use of get() updates the global pointer ip, the position
+ *             in the current input text line
+ */
+
+char
+getnb()
+{
+       register int c;
+
+       while ((c=get())==' ' || c=='\t')
+               ;
+       return (c);
+}
+
+/*)Function    VOID    skip()
+ *
+ *     The function skip() scans the input text skipping all
+ *     letters and digits.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             char    ctype[]         array of character types, one per
+ *                                     ASCII character
+ *             
+ *     functions called:
+ *             char    get()           lklex.c
+ *             char    getnb()         lklex.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             Input letters and digits are skipped.
+ */
+
+VOID
+skip(c)
+register int c;
+{
+       if (c < 0)
+               c = getnb();
+       while (ctype[c=get()] & (LETTER|DIGIT)) { ; }
+       unget(c);
+}
+
+/*)Function    char    get()
+ *
+ *     The function get() returns the next character in the
+ *     input text line, at the end of the line a
+ *     NULL character is returned.
+ *
+ *     local variables:
+ *             int     c               current character from
+ *                                     input text line
+ *
+ *     global variables:
+ *             char *  ip              pointer into the current
+ *                                     input text line
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             updates ip to the next character position in the
+ *             input text line.  If ip is at the end of the
+ *             line, ip is not updated.
+ */
+
+char
+get()
+{
+       register int c;
+
+       if ((c = *ip) != 0)
+               ++ip;
+       return (c);
+}
+
+/*)Function    VOID    unget(c)
+ *
+ *             int     c               value of last character
+ *                                     read from input text line
+ *
+ *     If (c) is not a NULL character then the global pointer ip
+ *     is updated to point to the preceeding character in the
+ *     input text line.
+ *
+ *     NOTE:   This function does not push the character (c)
+ *             back into the input text line, only
+ *             the pointer ip is changed.
+ *
+ *     local variables:
+ *             int     c               last character read
+ *                                     from input text line
+ *
+ *     global variables:
+ *             char *  ip              position into the current
+ *                                     input text line
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             ip decremented by 1 character position
+ */
+
+VOID
+unget(c)
+{
+       if (c != 0)
+               --ip;
+}
+
+/*)Function    int     getmap(d)
+ *
+ *             int     d               value to compare with the
+ *                                     input text line character
+ *
+ *     The function getmap() converts the 'C' style characters \b, \f,
+ *     \n, \r, and \t to their equivalent ascii values and also
+ *     converts 'C' style octal constants '\123' to their equivalent
+ *     numeric values.  If the first character is equivalent to (d) then
+ *     a (-1) is returned, if the end of the line is detected then
+ *     a 'q' error terminates the parse for this line, or if the first
+ *     character is not a \ then the character value is returned.
+ *
+ *     local variables:
+ *             int     c               value of character
+ *                                     from input text line
+ *             int     n               looping counter
+ *             int     v               current value of numeric conversion
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             char    get()           lklex.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             use of get() updates the global pointer ip the position
+ *             in the current input text line
+ */
+
+int
+getmap(d)
+{
+       register int c, n, v;
+
+       if ((c = get()) == '\0')
+               return (-1);
+       if (c == d)
+               return (-1);
+       if (c == '\\') {
+               c = get();
+               switch (c) {
+
+               case 'b':
+                       c = '\b';
+                       break;
+
+               case 'f':
+                       c = '\f';
+                       break;
+
+               case 'n':
+                       c = '\n';
+                       break;
+
+               case 'r':
+                       c = '\r';
+                       break;
+
+               case 't':
+                       c = '\t';
+                       break;
+
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+                       n = 0;
+                       v = 0;
+                       while (++n<=3 && c>='0' && c<='7') {
+                               v = (v<<3) + c - '0';
+                               c = get();
+                       }
+                       unget(c);
+                       c = v;
+                       break;
+               }
+       }
+       return (c);
+}
+
+/*)Function    int     as_getline()
+ *
+ *     The function as_getline() reads a line of input text from a
+ *     .rel source text file, a .lnk command file or from stdin.
+ *     Lines of text are processed from a single .lnk file or
+ *     multiple .rel files until all files have been read.
+ *     The input text line is copied into the global string ib[]
+ *     and converted to a NULL terminated string.  The function
+ *     as_getline() returns a (1) after succesfully reading a line
+ *     or a (0) if all files have been read.
+ *     This function also opens each input .lst file and output
+ *     .rst file as each .rel file is processed.
+ *
+ *     local variables:
+ *             int     i               string length
+ *             int     ftype           file type
+ *             char *  fid             file name
+ *
+ *     global variables:
+ *             lfile   *cfp            The pointer *cfp points to the
+ *                                     current lfile structure
+ *             lfile   *filep          The pointer *filep points to the
+ *                                     beginning of a linked list of
+ *                                     lfile structures.
+ *             int     gline           get a line from the LST file
+ *                                     to translate for the RST file
+ *             char    ib[NINPUT]      REL file text line
+ *             int     pass            linker pass number
+ *             int     pflag           print linker command file flag
+ *             FILE    *rfp            The file handle to the current
+ *                                     output RST file
+ *             FILE    *sfp            The file handle sfp points to the
+ *                                     currently open file
+ *             FILE *  stdin           c_library
+ *             FILE *  stdout          c_library
+ *             FILE    *tfp            The file handle to the current
+ *                                     LST file being scanned
+ *             int     uflag           update listing flag
+ *
+ *     called functions:
+ *             FILE *  afile()         lkmain.c
+ *             int     fclose()        c_library
+ *             char *  fgets()         c_library
+ *             int     fprintf()       c_library
+ *             VOID    lkulist()       lklist.c
+ *             VOID    lkexit()        lkmain.c
+ *             int     strlen()        c_library
+ *
+ *     side effects:
+ *             The input stream is scanned.  The .rel files will be
+ *             opened and closed sequentially scanning each in turn.
+ */
+
+int
+as_getline()
+{
+       register int ftype;
+       register char *fid;
+
+loop:  if (pflag && cfp && cfp->f_type == F_STD)
+               fprintf(stdout, "ASlink >> ");
+
+       if (sfp == NULL || fgets(ib, sizeof ib, sfp) == NULL) {
+               if (sfp) {
+                       fclose(sfp);
+                       sfp = NULL;
+                       lkulist(0);
+               }
+               if (cfp == NULL) {
+                       cfp = filep;
+               } else {
+                       cfp = cfp->f_flp;
+               }
+               if (cfp) {
+                       ftype = cfp->f_type;
+                       fid = cfp->f_idp;
+                       if (ftype == F_STD) {
+                               sfp = stdin;
+                       } else
+                       if (ftype == F_LNK) {
+                               sfp = afile(fid, "lnk", 0);
+                       } else
+                       if (ftype == F_REL) {
+                               sfp = afile(fid, "rel", 0);
+                               /* if a .cdb file exists then copy it over */
+                               if (dflag && sfp && dfp && pass == 0) {
+                                   FILE *xfp = afile(fid,"adb",0); //JCF: Nov 30, 2002
+                                   if (xfp) {
+                                       copyfile(dfp,xfp);
+                                       fclose(xfp);
+                                   }
+                               }
+                               if (uflag && pass != 0) {
+                                SaveLinkedFilePath(fid); //Save the linked path for aomf51
+                                if ((tfp = afile(fid, "lst", 0)) != NULL) {
+                                 if ((rfp = afile(fid, "rst", 1)) == NULL) {
+                                       fclose(tfp);
+                                       tfp = NULL;
+                                 }
+                                }
+                               }
+                               gline = 1;
+                       } else {
+                               fprintf(stderr, "Invalid file type\n");
+                               lkexit(1);
+                       }
+                       if (sfp == NULL) {
+                               lkexit(1);
+                       }
+                       goto loop;
+               } else {
+                       filep = NULL;
+                       return(0);
+               }
+       }
+       chop_crlf(ib);
+       return (1);
+}
+
+/*)Function    int     more()
+ *
+ *     The function more() scans the input text line
+ *     skipping white space (SPACES and TABS) and returns a (0)
+ *     if the end of the line or a comment delimeter (;) is found,
+ *     or a (1) if their are additional characters in the line.
+ *
+ *     local variables:
+ *             int     c               next character from
+ *                                     the input text line
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             char    getnb()         lklex.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             use of getnb() and unget() updates the global pointer ip
+ *             the position in the current input text line
+ */
+
+int
+more()
+{
+       register int c;
+
+       c = getnb();
+       unget(c);
+       return( (c == '\0' || c == ';') ? 0 : 1 );
+}
+
+/*)Function    char    endline()
+ *
+ *     The function endline() scans the input text line
+ *     skipping white space (SPACES and TABS) and returns the next
+ *     character or a (0) if the end of the line is found or a
+ *     comment delimiter (;) is found.
+ *
+ *     local variables:
+ *             int     c               next character from
+ *                                     the input text line
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             char    getnb()         lklex.c
+ *
+ *     side effects:
+ *             Use of getnb() updates the global pointer ip the
+ *             position in the current input text line.
+ */
+
+char
+endline()
+{
+       register int c;
+
+       c = getnb();
+       return( (c == '\0' || c == ';') ? 0 : c );
+}
+
+/*)Function    VOID    chop_crlf(str)
+ *
+ *             char    *str            string to chop
+ *
+ *     The function chop_crlf() removes trailing LF or CR/LF from
+ *     str, if present.
+ *
+ *     local variables:
+ *             int     i               string length
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+
+VOID
+chop_crlf(str)
+char *str;
+{
+       register int i;
+
+       i = strlen(str);
+       if (i >= 1 && str[i-1] == '\n') str[i-1] = 0;
+       if (i >= 2 && str[i-2] == '\r') str[i-2] = 0;
+}