OSDN Git Service

Clean up cpu file parsing, pass context consistently instead of the
authordevans <devans>
Wed, 12 Aug 2009 22:33:36 +0000 (22:33 +0000)
committerdevans <devans>
Wed, 12 Aug 2009 22:33:36 +0000 (22:33 +0000)
old "errtxt" argument.
NOTE: ACU == "All Callers Updated".
* attr.scm (-parse-simple-attribute): Renamed from
parse-simple-attribute, ACU.
(-attr-parse): Change errtxt argument to context, ACU.
(-attr-read): Ditto.
(atlist-parse): Ditto.  Put context arg first.
(attr-parse): Use parse-error instead of context-error.
* enum.scm (parse-enum-vals): Change errtxt argument to context, ACU.
(-enum-parse-prefix, -enum-parse, -enum-read): Ditto.
* hardware.scm (-keyword-parse): Renamed from keyword-parse.
`context' arg is now a <context> object.  ACU.
(-keyword-read): `context' arg is now a <context> object.  ACU.
(-hw-parse-indices): Change errtxt argument to context, ACU.
(-hw-parse-values, -hw-parse-handlers): Ditto.
(-hw-parse-getter, -hw-parse-setter, -hw-parse, -hw-read): Ditto.
(-hw-validate-layout, -hw-create-getter-from-layout,
-hw-create-setter-from-layout): Ditto.
(<hw-register>:parse!, <hw-pc>:parse!): Ditto.
(<hw-memory>:parse!, <hw-immediate>:parse!): Ditto.
(<hw-address>:parse!): Ditto.
* ifield.scm (-ifield-parse, ifield-read): Ditto.
(-ifld-parse-follows, -ifld-parse-encode-decode): Ditto.
(-ifld-parse-encode, -ifld-parse-decode): Ditto.
(-multi-ifield-parse, -multi-ifield-read): Ditto.
* insn.scm (-insn-parse, -insn-read): Ditto.
(parse-syntax): Ditto.  Put context arg first.
(-parse-insn-format-symbol): Change errtxt argument to context, ACU.
(-parse-insn-format-ifield-spec, -parse-insn-format-list): Ditto.
(-parse-insn-format): Ditto.
* mach.scm (-arch-parse-alignment, -arch-parse-machs): Ditto.
(-arch-parse-isas): Ditto.
(-isa-read): Add context arg, ACU.
(-cpu-parse, -cpu-read, -mach-read): Ditto.
* minsn.scm (-minsn-parse-expansion): Change errtxt argument to
context, ACU.
(-minsn-parse, -minsn-read, -minsn-compute-iflds): Ditto.
(minsn-make-alias): Ditto.
* mode.scm (-mode-parse): Ditto.
(parse-mode-name): Ditto.  Put context arg first.
* model.scm (-prefetch-parse, -retire-parse, -pipeline-parse): Change
errtxt argument to context, ACU.
(-unit-parse, -model-parse, -model-read): Ditto.
* operand.scm (-operand-parse-getter): Use parse-error instead of
context-error.
(-operand-parse-setter): Ditto.
(-operand-parse): Change errtxt argument to context, ACU.
(-operand-read, -derived-operand-parse, -derived-operand-read): Ditto.
(-anyof-operand-parse, -anyof-operand-read): Ditto.
* read.scm (reader-error): Delete.  Use parse-error instead.
(parse-error): Change errtxt argument to context, ACU.  Split args
argument into expr and maybe-help-text.
(-reader-process-expanded-1!): Reorganize.
* rtl.scm (-subr-read): Change errtxt argument to context, ACU.
* types.scm (parse-type): Ditto.
* utils-cgen.scm (single-location->simple-string): New function.
(<context>): Replace members file,lineno with location.
(make-prefix-context): Renamed from context-make-prefix, ACU.
(make-current-context): New function.
(context-append, context-append-name): New functions.
(context-make-reader): Delete.
(parse-name): Change errtxt argument to context, ACU.
Put context arg first.
(parse-comment): Ditto.
(parse-number): Change errtxt argument to context, ACU.
(arg-list-validate-name, arg-list-check-no-args,
arg-list-symbol-arg): Ditto.

* read.scm (-cmd-if): Don't assume test is a list.

* html.scm (get-insn-properties): Delete errtxt, unused.

23 files changed:
cgen/ChangeLog
cgen/attr.scm
cgen/enum.scm
cgen/hardware.scm
cgen/html.scm
cgen/ifield.scm
cgen/insn.scm
cgen/mach.scm
cgen/minsn.scm
cgen/mode.scm
cgen/model.scm
cgen/opc-itab.scm
cgen/operand.scm
cgen/read.scm
cgen/rtl-c.scm
cgen/rtl-traverse.scm
cgen/rtl.scm
cgen/sem-frags.scm
cgen/semantics.scm
cgen/sid.scm
cgen/sim.scm
cgen/types.scm
cgen/utils-cgen.scm

index c18e38a..6c48ad2 100644 (file)
@@ -1,3 +1,78 @@
+2009-08-12  Doug Evans  <dje@sebabeach.org>
+
+       Clean up cpu file parsing, pass context consistently instead of the
+       old "errtxt" argument.
+       NOTE: ACU == "All Callers Updated".
+       * attr.scm (-parse-simple-attribute): Renamed from
+       parse-simple-attribute, ACU.
+       (-attr-parse): Change errtxt argument to context, ACU.
+       (-attr-read): Ditto.
+       (atlist-parse): Ditto.  Put context arg first.
+       (attr-parse): Use parse-error instead of context-error.
+       * enum.scm (parse-enum-vals): Change errtxt argument to context, ACU.
+       (-enum-parse-prefix, -enum-parse, -enum-read): Ditto.
+       * hardware.scm (-keyword-parse): Renamed from keyword-parse.
+       `context' arg is now a <context> object.  ACU.
+       (-keyword-read): `context' arg is now a <context> object.  ACU.
+       (-hw-parse-indices): Change errtxt argument to context, ACU.
+       (-hw-parse-values, -hw-parse-handlers): Ditto.
+       (-hw-parse-getter, -hw-parse-setter, -hw-parse, -hw-read): Ditto.
+       (-hw-validate-layout, -hw-create-getter-from-layout,
+       -hw-create-setter-from-layout): Ditto.
+       (<hw-register>:parse!, <hw-pc>:parse!): Ditto.
+       (<hw-memory>:parse!, <hw-immediate>:parse!): Ditto.
+       (<hw-address>:parse!): Ditto.
+       * ifield.scm (-ifield-parse, ifield-read): Ditto.
+       (-ifld-parse-follows, -ifld-parse-encode-decode): Ditto.
+       (-ifld-parse-encode, -ifld-parse-decode): Ditto.
+       (-multi-ifield-parse, -multi-ifield-read): Ditto.
+       * insn.scm (-insn-parse, -insn-read): Ditto.
+       (parse-syntax): Ditto.  Put context arg first.
+       (-parse-insn-format-symbol): Change errtxt argument to context, ACU.
+       (-parse-insn-format-ifield-spec, -parse-insn-format-list): Ditto.
+       (-parse-insn-format): Ditto.
+       * mach.scm (-arch-parse-alignment, -arch-parse-machs): Ditto.
+       (-arch-parse-isas): Ditto.
+       (-isa-read): Add context arg, ACU.
+       (-cpu-parse, -cpu-read, -mach-read): Ditto.
+       * minsn.scm (-minsn-parse-expansion): Change errtxt argument to
+       context, ACU.
+       (-minsn-parse, -minsn-read, -minsn-compute-iflds): Ditto.
+       (minsn-make-alias): Ditto.
+       * mode.scm (-mode-parse): Ditto.
+       (parse-mode-name): Ditto.  Put context arg first.
+       * model.scm (-prefetch-parse, -retire-parse, -pipeline-parse): Change
+       errtxt argument to context, ACU.
+       (-unit-parse, -model-parse, -model-read): Ditto.
+       * operand.scm (-operand-parse-getter): Use parse-error instead of
+       context-error.
+       (-operand-parse-setter): Ditto.
+       (-operand-parse): Change errtxt argument to context, ACU.
+       (-operand-read, -derived-operand-parse, -derived-operand-read): Ditto.
+       (-anyof-operand-parse, -anyof-operand-read): Ditto.
+       * read.scm (reader-error): Delete.  Use parse-error instead.
+       (parse-error): Change errtxt argument to context, ACU.  Split args
+       argument into expr and maybe-help-text.
+       (-reader-process-expanded-1!): Reorganize.
+       * rtl.scm (-subr-read): Change errtxt argument to context, ACU.
+       * types.scm (parse-type): Ditto.
+       * utils-cgen.scm (single-location->simple-string): New function.
+       (<context>): Replace members file,lineno with location.
+       (make-prefix-context): Renamed from context-make-prefix, ACU.
+       (make-current-context): New function.
+       (context-append, context-append-name): New functions.
+       (context-make-reader): Delete.
+       (parse-name): Change errtxt argument to context, ACU.
+       Put context arg first.
+       (parse-comment): Ditto.
+       (parse-number): Change errtxt argument to context, ACU.
+       (arg-list-validate-name, arg-list-check-no-args,
+       arg-list-symbol-arg): Ditto.
+
+       * read.scm (-cmd-if): Don't assume test is a list.
+
+       * html.scm (get-insn-properties): Delete errtxt, unused.
+
 2009-08-11  Doug Evans  <dje@sebabeach.org>
 
        * doc/rtl.texi (hardware types): Add pc.
index ca2fd5e..1d9db65 100644 (file)
 
 (define (enum-attr-make name value) (cons name value))
 
-(define (parse-simple-attribute right-type? message)
-  (lambda (self errtxt val)
+;;; Return a procedure to parse an attribute.
+;;; RIGHT-TYPE? is a procedure that verifies the value is the right type.
+;;; MESSAGE is printed if there is an error.
+
+(define (-parse-simple-attribute right-type? message)
+  (lambda (self context val)
     (if (and (not (null? val))
             (right-type? (car val))
             (null? (cdr val)))
        (cons (obj:name self) (car val))
-       (parse-error errtxt message (cons (obj:name self) val))))
+       (parse-error context message (cons (obj:name self) val))))
 )
 
 ; A boolean attribute's value is either #t or #f.
 
 (method-make!
  <boolean-attribute> 'parse-value
- (parse-simple-attribute boolean? "boolean attribute not one of #f/#t")
+ (-parse-simple-attribute boolean? "boolean attribute not one of #f/#t")
 )
 
 (method-make!
  <string-attribute> 'parse-value
- (parse-simple-attribute string? "invalid argument to string attribute"))
+ (-parse-simple-attribute string? "invalid argument to string attribute"))
 
 ; A bitset attribute's value is a comma separated list of elements.
 ; We don't validate the values.  In the case of the MACH attribute,
 
 (method-make!
  <bitset-attribute> 'parse-value
- (parse-simple-attribute (lambda (x) (or (symbol? x) (string? x)))
-                        "improper bitset attribute")
+ (-parse-simple-attribute (lambda (x) (or (symbol? x) (string? x)))
+                         "improper bitset attribute")
 )
 
 ; An integer attribute's value is a number
 
 (method-make!
  <integer-attribute> 'parse-value
- (parse-simple-attribute (lambda (x) (or (number? x) (symbol? x)))
-                        "improper integer attribute")
+ (-parse-simple-attribute (lambda (x) (or (number? x) (symbol? x)))
+                         "improper integer attribute")
 )
 
 ; An enum attribute's value is a symbol representing that value.
 
 (method-make!
  <enum-attribute> 'parse-value
- (parse-simple-attribute (lambda (x) (or (symbol? x) (string? x)))
-                        "improper enum attribute")
+ (-parse-simple-attribute (lambda (x) (or (symbol? x) (string? x)))
+                         "improper enum attribute")
 )
 
 ; Parse a boolean attribute's value definition.
 
 (method-make!
  <boolean-attribute> 'parse-value-def
- (lambda (self errtxt values)
+ (lambda (self context values)
    (if (equal? values '(#f #t))
        values
-       (parse-error errtxt "boolean value list must be (#f #t)" values)))
+       (parse-error context "boolean value list must be (#f #t)" values)))
 )
 
 ; Ignore values for strings.  We can't do any error checking since
 
 (method-make!
  <string-attribute> 'parse-value-def
- (lambda (self errtxt values) #f)
+ (lambda (self context values) #f)
 )
 
 ; Parse a bitset attribute's value definition.
 
 (method-make!
  <bitset-attribute> 'parse-value-def
- (lambda (self errtxt values)
-   (parse-enum-vals errtxt "" values))
+ (lambda (self context values)
+   (parse-enum-vals context "" values))
 )
 
 ; Parse an integer attribute's value definition.
 
 (method-make!
  <integer-attribute> 'parse-value-def
- (lambda (self errtxt values)
+ (lambda (self context values)
    (if values
        (for-each (lambda (val)
                   (if (or (not (list? val))
                           (not (number? (car val))))
-                      (parse-error errtxt "invalid element in integer attribute list" val)))
+                      (parse-error context
+                                   "invalid element in integer attribute list"
+                                   val)))
                 values))
    values)
 )
 
 (method-make!
  <enum-attribute> 'parse-value-def
- (lambda (self errtxt values)
-   (parse-enum-vals errtxt "" values))
+ (lambda (self context values)
+   (parse-enum-vals context "" values))
 )
 
 ; Make an attribute list object from a list of name/value pairs.
 ; If DEFAULT is #f, use the first value.
 ; ??? Allowable values for integer attributes is wip.
 
-(define (-attr-parse errtxt type-class name comment attrs for default values)
+(define (-attr-parse context type-class name comment attrs for default values)
   (logit 2 "Processing attribute " name " ...\n")
-  (let* ((name (parse-name name errtxt))
-        (errtxt (stringsym-append errtxt ":" name))
+
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name))
         (result (new type-class))
-        (parsed-values (send result 'parse-value-def errtxt values)))
+        (parsed-values (send result 'parse-value-def context values)))
+
     (elm-xset! result 'name name)
-    (elm-xset! result 'comment (parse-comment comment errtxt))
-    (elm-xset! result 'attrs (atlist-parse attrs "" errtxt))
+    (elm-xset! result 'comment (parse-comment context comment))
+    (elm-xset! result 'attrs (atlist-parse context attrs ""))
     (elm-xset! result 'for for)
     ; Set the default.
     (case (class-name type-class)
       ((<boolean-attribute>)
        (if (and (not (memq default '(#f #t)))
                (not (rtx? default)))
-          (parse-error errtxt "invalid default" default))
+          (parse-error context "invalid default" default))
        (elm-xset! result 'default default))
       ((<string-attribute>)
        (let ((default (or default "")))
         (if (and (not (string? default))
                  (not (rtx? default)))
-            (parse-error errtxt "invalid default" default))
+            (parse-error context "invalid default" default))
         (elm-xset! result 'default default)))
       ((<integer-attribute>)
        (let ((default (if default default (if (null? values) 0 (car values)))))
         (if (and (not (integer? default))
                  (not (rtx? default)))
-            (parse-error errtxt "invalid default" default))
+            (parse-error context "invalid default" default))
         (elm-xset! result 'default default)))
       ((<bitset-attribute> <enum-attribute>)
        (let ((default (if default default (caar parsed-values))))
         (if (and (not (assq default parsed-values))
                  (not (rtx? default)))
-            (parse-error errtxt "invalid default" default))
+            (parse-error context "invalid default" default))
         (elm-xset! result 'default default))))
     (elm-xset! result 'values parsed-values)
+
     result)
 )
 
 ; Read an attribute description
 ; This is the main routine for analyzing attributes in the .cpu file.
-; ERRTXT is prepended to error messages to provide context.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
 ; -attr-parse is invoked to create the attribute object.
 
-(define (-attr-read errtxt . arg-list)
-  (let (; Current attribute elements:
+(define (-attr-read context . arg-list)
+  (let (
        (type-class 'not-set) ; attribute type
-       (name nil)
+       (name #f)
        (comment "")
        (attrs nil)
        (for #f) ; assume for everything
-       (default #f) ; indicates "not set"
-       (values #f) ; indicates "not set"
+       (default #f) ; #f indicates "not set"
+       (values #f) ; #f indicates "not set"
        )
+
     ; Loop over each element in ARG-LIST, recording what's found.
     (let loop ((arg-list arg-list))
       (if (null? arg-list)
                                        ((integer) <integer-attribute>)
                                        ((enum) <enum-attribute>)
                                        (else (parse-error
-                                              errtxt
+                                              context
                                               "invalid attribute type"
                                               (cadr arg))))))
              ((name) (set! name (cadr arg)))
              ((for) (set! for (cdr arg)))
              ((default) (set! default (cadr arg)))
              ((values) (set! values (cdr arg)))
-             (else (parse-error errtxt "invalid attribute arg" arg)))
+             (else (parse-error context "invalid attribute arg" arg)))
            (loop (cdr arg-list)))))
+
     ; Must have type now.
     (if (eq? type-class 'not-set)
-       (parse-error errtxt "type not specified"))
+       (parse-error context "type not specified") arg-list)
     ; Establish proper defaults now that we know the type.
     (case (class-name type-class)
       ((<boolean-attribute>)
           (set! values '(#f #t))))
       ((bitset-attribute>) ;; FIXME
        (if (eq? default #f)
-          (parse-error errtxt "bitset-attribute default not specified"))
+          (parse-error context "bitset-attribute default not specified"
+                       arg-list))
        (if (eq? values #f)
-          (parse-error errtxt "bitset-attribute values not specified")))
+          (parse-error context "bitset-attribute values not specified"
+                       arg-list)))
       ((integer-attribute>) ;; FIXME
        (if (eq? default #f)
           (set! default 0))
           (set! values #f))) ; really a nop, but for consistency
       ((enum-attribute>) ;; FIXME
        (if (eq? default #f)
-          (parse-error errtxt "enum-attribute default not specified"))
+          (parse-error context "enum-attribute default not specified"
+                       arg-list))
        (if (eq? values #f)
-          (parse-error errtxt "bitset-attribute values not specified")))
+          (parse-error context "bitset-attribute values not specified"
+                       arg-list)))
       )
+
     ; Now that we've identified the elements, build the object.
-    (-attr-parse errtxt type-class name comment attrs for default values)
-    )
+    (-attr-parse context type-class name comment attrs for default values))
 )
 
 ; Main routines for defining attributes in .cpu files.
 
 (define define-attr
   (lambda arg-list
-    (let ((a (apply -attr-read (cons "define-attr" arg-list))))
+    (let ((a (apply -attr-read (cons (make-current-context "define-attr")
+                                    arg-list))))
       (current-attr-add! a)
       a))
 )
 
 (define (attr-parse context attrs)
   (if (not (list? attrs))
-      (context-error context "improper attribute list" attrs))
+      (parse-error context "improper attribute list" attrs))
   (let ((alist nil))
     (for-each (lambda (elm)
                (cond ((symbol? elm)
                           (set! alist (acons (string->symbol (string-drop1 (symbol->string elm))) #f alist))
                           (set! alist (acons elm #t alist)))
                       (if (not (current-attr-lookup (caar alist)))
-                          (context-error context "unknown attribute" (caar alist))))
+                          (parse-error context "unknown attribute" (caar alist))))
                      ((and (list? elm) (pair? elm) (symbol? (car elm)))
                       (let ((a (current-attr-lookup (car elm))))
                         (if (not a)
-                            (context-error context "unknown attribute" elm))
+                            (parse-error context "unknown attribute" elm))
                         (set! alist (cons (send a 'parse-value
-                                                (context-prefix context);FIXME
-                                                (cdr elm)) alist))))
-                     (else (context-error context "improper attribute" elm))))
+                                                context (cdr elm))
+                                          alist))))
+                     (else (parse-error context "improper attribute" elm))))
              attrs)
     alist)
 )
 ; ATTRS is a list of attribute specs (e.g. (FOO !BAR (BAZ 3))).
 ; The result is an <attr-list> object.
 
-(define (atlist-parse attrs prefix errtxt)
-  (make <attr-list> prefix (attr-parse (context-make-prefix errtxt) attrs))
+(define (atlist-parse context attrs prefix)
+  (make <attr-list> prefix (attr-parse context attrs))
 )
 
 ; Return the source form of an atlist's values.
index e83c62a..f6d48d4 100644 (file)
@@ -46,7 +46,7 @@
 ; The result is the same list, except values are filled in where missing,
 ; and each symbol is prepended with `prefix'.
 
-(define (parse-enum-vals errtxt prefix vals)
+(define (parse-enum-vals context prefix vals)
   ; Scan the value list, building up RESULT as we go.
   ; Each element's value is 1+ the previous, unless there's an explicit value.
   (let loop ((result nil) (last -1) (remaining vals))
 
 ; Utility of -enum-parse to parse the prefix.
 
-(define (-enum-parse-prefix errtxt prefix)
+(define (-enum-parse-prefix context prefix)
   (if (symbol? prefix)
       (set! prefix (symbol->string prefix)))
 
   (if (not (string? prefix))
-      (parse-error errtxt "prefix is not a string" prefix))
+      (parse-error context "prefix is not a string" prefix))
 
   ; Prefix must not contain lowercase chars (enforced style rule, sue me).
   (if (any-true? (map char-lower-case? (string->list prefix)))
-      (parse-error errtxt "prefix must be uppercase" prefix))
+      (parse-error context "prefix must be uppercase" prefix))
 
   prefix
 )
 ; description in the .cpu file.
 ; All arguments are in raw (non-evaluated) form.
 
-(define (-enum-parse errtxt name comment attrs prefix vals)
+(define (-enum-parse context name comment attrs prefix vals)
   (logit 2 "Processing enum " name " ...\n")
 
-  (let* ((name (parse-name name errtxt))
-        (errtxt (stringsym-append errtxt " " name)))
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name)))
 
     (make <enum>
          name
-         (parse-comment comment errtxt)
-         (atlist-parse attrs "enum" errtxt)
-         (-enum-parse-prefix errtxt prefix)
-         (parse-enum-vals errtxt prefix vals)))
+         (parse-comment context comment)
+         (atlist-parse context attrs "enum")
+         (-enum-parse-prefix context prefix)
+         (parse-enum-vals context prefix vals)))
 )
 
 ; Read an enum description
 ; This is the main routine for analyzing enums in the .cpu file.
-; ERRTXT is prepended to error messages to provide context.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
 ; -enum-parse is invoked to create the `enum' object.
 
-(define (-enum-read errtxt . arg-list)
-  (let (; Current enum elements:
-       (name nil)    ; name of field
-       (comment "")  ; description of field
-       (attrs nil)   ; attributes
-       (prefix "")   ; prepended to each element's name
-       (values nil)  ; enum values
+(define (-enum-read context . arg-list)
+  (let (
+       (name #f)
+       (comment "")
+       (attrs nil)
+       (prefix "")
+       (values nil)
        )
+
     ; Loop over each element in ARG-LIST, recording what's found.
     (let loop ((arg-list arg-list))
       (if (null? arg-list)
              ((attrs) (set! attrs (cdr arg)))
              ((prefix) (set! prefix (cadr arg)))
              ((values) (set! values (cadr arg)))
-             (else (parse-error errtxt "invalid enum arg" arg)))
+             (else (parse-error context "invalid enum arg" arg)))
            (loop (cdr arg-list)))))
+
     ; Now that we've identified the elements, build the object.
-    (-enum-parse errtxt name comment attrs prefix values)
-    )
+    (-enum-parse context name comment attrs prefix values))
 )
 
 ; Define an enum object, name/value pair list version.
 
 (define define-enum
   (lambda arg-list
-    (let ((e (apply -enum-read (cons "define-enum" arg-list))))
+    (let ((e (apply -enum-read (cons (make-current-context "define-enum")
+                                    arg-list))))
       (current-enum-add! e)
       e))
 )
 ; Define an enum object, all arguments specified.
 
 (define (define-full-enum name comment attrs prefix vals)
-  (let ((e (-enum-parse "define-full-enum" name comment attrs prefix vals)))
+  (let ((e (-enum-parse (make-current-context "define-full-enum")
+                       name comment attrs prefix vals)))
     (current-enum-add! e)
     e)
 )
 ; Define an insn enum, all arguments specified.
 
 (define (define-full-insn-enum name comment attrs prefix fld vals)
-  (let* ((errtxt "define-full-insn-enum")
-        (atlist (atlist-parse attrs "insn_enum" errtxt))
+  (let* ((context (make-current-context "define-full-insn-enum"))
+        (atlist (atlist-parse context attrs "insn-enum"))
         (fld-obj (current-ifld-lookup fld)))
 
     (if (keep-isa-atlist? atlist #f)
        (begin
          (if (not fld-obj)
-             (parse-error errtxt "unknown insn field" fld))
+             (parse-error context "unknown insn field" fld))
          ; Create enum object and add it to the list of enums.
          (let ((e (make <insn-enum>
-                    (parse-name name errtxt)
-                    (parse-comment comment errtxt)
-                    (atlist-parse attrs "insn-enum" errtxt)
-                    (-enum-parse-prefix errtxt prefix)
+                    (parse-name context name)
+                    (parse-comment context comment)
+                    atlist
+                    (-enum-parse-prefix context prefix)
                     fld-obj
-                    (parse-enum-vals errtxt prefix vals))))
+                    (parse-enum-vals context prefix vals))))
            (current-enum-add! e)
            e))))
-  )
+)
 \f
 (define (enum-init!)
 
index e6b6fb0..d5b3711 100644 (file)
 ; that is left to the application.  Still, it might be preferable to impose
 ; some restrictions which can later be relaxed as necessary.
 
-(define (keyword-parse context name comment attrs mode print-name prefix values)
+(define (-keyword-parse context name comment attrs mode print-name prefix values)
   ; FIXME: parse values.
   (let ((result (make <keyword>
-                 (parse-name name context)
-                 (parse-comment comment context)
-                 (atlist-parse attrs "" context)
-                 (parse-mode-name mode (string-append context ": mode"))
-                 (parse-string (string-append context ": print-name") print-name)
-                 (parse-string (string-append context ": prefix") prefix)
+                 (parse-name context name)
+                 (parse-comment context comment)
+                 (atlist-parse context attrs "")
+                 (parse-mode-name (context-append context ": mode") mode)
+                 (parse-string (context-append context ": print-name")
+                               print-name)
+                 (parse-string (context-append context ": prefix")
+                               prefix)
                  values)))
     result)
 )
 ; Read a keyword description
 ; This is the main routine for analyzing a keyword description in the .cpu
 ; file.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
-; keyword-parse is invoked to create the <keyword> object.
+; -keyword-parse is invoked to create the <keyword> object.
 
 (define (-keyword-read context . arg-list)
-  (let ((name #f)
+  (let (
+       (name #f)
        (comment "")
        (attrs nil)
        (mode INT)
-       (print-name #f)
+       (print-name #f) ;; #f indicates "not set"
        (prefix "")
        (values nil)
        )
+
     ; Loop over each element in ARG-LIST, recording what's found.
     (let loop ((arg-list arg-list))
       (if (null? arg-list)
              ((values) (set! values (cdr arg)))
              (else (parse-error context "invalid hardware arg" arg)))
            (loop (cdr arg-list)))))
+
     ; Now that we've identified the elements, build the object.
-    (keyword-parse context name comment attrs mode
-                  (or print-name name)
-                  prefix values)
-    )
+    (-keyword-parse context name comment attrs mode
+                   (or print-name name)
+                   prefix values))
 )
 
 ; Define a keyword object, name/value pair list version.
 
 (define define-keyword
   (lambda arg-list
-    (let ((kw (apply -keyword-read (cons "define-keyword" arg-list))))
+    (let ((kw (apply -keyword-read (cons (make-current-context "define-keyword")
+                                        arg-list))))
       (if kw
          (begin
            (current-kw-add! kw)
   ; They're needed to output the table.
   ; ??? This isn't quite right as the container may contain multiple keyword
   ; instances.  To be fixed in time.
-  (keyword-parse context (obj:name container) (obj:comment container)
-                ; PRIVATE: keyword table is implicitly defined and made
-                ; "static" (in the C sense).
-                (cons 'PRIVATE (atlist-source-form (obj-atlist container)))
-                mode
-                (obj:name container) ; print-name
-                (car args) ; prefix
-                (cadr args)) ; value
+  (-keyword-parse context (obj:name container) (obj:comment container)
+                 ;; PRIVATE: keyword table is implicitly defined and made
+                 ;; "static" (in the C sense).
+                 (cons 'PRIVATE (atlist-source-form (obj-atlist container)))
+                 mode
+                 (obj:name container) ; print-name
+                 (car args) ; prefix
+                 (cadr args)) ; value
 )
 
 ; Parse an indices spec.
 ; Otherwise MODE is used.
 ; The syntax is: (keyword keyword-spec) - see <keyword> for details.
 
-(define (-hw-parse-indices errtxt indices container mode)
+(define (-hw-parse-indices context indices container mode)
   (if (null? indices)
       (make <hw-asm>
        (obj:name container) (obj:comment container) (obj-atlist container)
        mode)
       (begin
        (if (not (list? indices))
-           (parse-error errtxt "invalid indices spec" indices))
+           (parse-error context "invalid indices spec" indices))
        (case (car indices)
-         ((keyword) (-hw-parse-keyword errtxt (cdr indices) container mode))
+         ((keyword) (-hw-parse-keyword context (cdr indices) container mode))
          ((extern-keyword) (begin
                              (if (null? (cdr indices))
-                                 (parse-error errtxt "missing keyword name"
+                                 (parse-error context "missing keyword name"
                                               indices))
                              (let ((kw (current-kw-lookup (cadr indices))))
                                (if (not kw)
-                                   (parse-error errtxt "unknown keyword"
+                                   (parse-error context "unknown keyword"
                                                 indices))
                                kw)))
-         (else (parse-error errtxt "unknown indices type" (car indices))))))
+         (else (parse-error context "unknown indices type" (car indices))))))
 )
 
 ; Parse a values spec.
 ; Otherwise MODE is used.
 ; The syntax is: (keyword keyword-spec) - see <keyword> for details.
 
-(define (-hw-parse-values errtxt values container mode)
+(define (-hw-parse-values context values container mode)
   (if (null? values)
       (make <hw-asm>
        (obj:name container) (obj:comment container) (obj-atlist container)
        mode)
       (begin
        (if (not (list? values))
-           (parse-error errtxt "invalid values spec" values))
+           (parse-error context "invalid values spec" values))
        (case (car values)
-         ((keyword) (-hw-parse-keyword errtxt (cdr values) container mode))
+         ((keyword) (-hw-parse-keyword context (cdr values) container mode))
          ((extern-keyword) (begin
                              (if (null? (cdr values))
-                                 (parse-error errtxt "missing keyword name"
+                                 (parse-error context "missing keyword name"
                                               values))
                              (let ((kw (current-kw-lookup (cadr values))))
                                (if (not kw)
-                                   (parse-error errtxt "unknown keyword"
+                                   (parse-error context "unknown keyword"
                                                 values))
                                kw)))
-         (else (parse-error errtxt "unknown values type" (car values))))))
+         (else (parse-error context "unknown values type" (car values))))))
 )
 
 ; Parse a handlers spec.
 ; Each element is (name "string").
 
-(define (-hw-parse-handlers errtxt handlers)
-  (parse-handlers errtxt '(parse print) handlers)
+(define (-hw-parse-handlers context handlers)
+  (parse-handlers context '(parse print) handlers)
 )
 
 ; Parse a getter spec.
 ; Omit `index' for scalar objects.
 ; Externally they're specified as `get'.  Internally we use `getter'.
 
-(define (-hw-parse-getter errtxt getter scalar?)
+(define (-hw-parse-getter context getter scalar?)
   (if (null? getter)
       #f ; use default
       (let ((valid "((index) (expression))")
                (!= (length getter) 2)
                (not (and (list? (car getter))
                          (= (length (car getter)) (if scalar? 0 1)))))
-           (parse-error errtxt
+           (parse-error context
                         (string-append "invalid getter, should be "
                                        (if scalar? scalar-valid valid))
                         getter))
        (if (not (rtx? (cadr getter)))
-           (parse-error errtxt "invalid rtx expression" getter))
+           (parse-error context "invalid rtx expression" getter))
        getter))
 )
 
 ; Omit `index' for scalar objects.
 ; Externally they're specified as `set'.  Internally we use `setter'.
 
-(define (-hw-parse-setter errtxt setter scalar?)
+(define (-hw-parse-setter context setter scalar?)
   (if (null? setter)
       #f ; use default
       (let ((valid "((index newval) (expression))")
                (!= (length setter) 2)
                (not (and (list? (car setter))
                          (= (length (car setter)) (if scalar? 1 2)))))
-           (parse-error errtxt
+           (parse-error context
                         (string-append "invalid setter, should be "
                                        (if scalar? scalar-valid valid))
                         setter))
        (if (not (rtx? (cadr setter)))
-           (parse-error errtxt "invalid rtx expression" setter))
+           (parse-error context "invalid rtx expression" setter))
        setter))
 )
 
 ; ??? Might want to redo to handle hardware type specific specs more cleanly.
 ; E.g. <hw-immediate> shouldn't have to see get/set specs.
 
-(define (-hw-parse errtxt name comment attrs semantic-name type
+(define (-hw-parse context name comment attrs semantic-name type
                   indices values handlers get set layout)
   (logit 2 "Processing hardware element " name " ...\n")
 
   (if (null? type)
-      (parse-error errtxt "missing hardware type" name))
+      (parse-error context "missing hardware type" name))
 
-  ; Pick out name first 'cus we need it as a string(/symbol).
-  (let ((name (parse-name name "hardware"))
-       (class-name (assq-ref -hardware-types (car type)))
-       (atlist-obj (atlist-parse attrs "cgen_hw" errtxt)))
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name))
+        (class-name (assq-ref -hardware-types (car type)))
+        (atlist-obj (atlist-parse context attrs "cgen_hw")))
 
     (if (not class-name)
-       (parse-error errtxt "unknown hardware type" type))
+       (parse-error context "unknown hardware type" type))
 
     (if (keep-atlist? atlist-obj #f)
 
        (let ((result (new (class-lookup class-name))))
          (send result 'set-name! name)
-         (send result 'set-comment! (parse-comment comment errtxt))
+         (send result 'set-comment! (parse-comment context comment))
          (send result 'set-atlist! atlist-obj)
          (elm-xset! result 'sem-name semantic-name)
-         (send result 'parse! errtxt
+         (send result 'parse! context
                (cdr type) indices values handlers get set layout)
          ; If this is a virtual reg, get/set specs must be provided.
          (if (and (obj-has-attr? result 'VIRTUAL)
                   (not (and (hw-getter result) (hw-setter result))))
-             (parse-error errtxt "virtual reg requires get/set specs" name))
+             (parse-error context "virtual reg requires get/set specs" name))
          ; If get or set specs are specified, can't have CACHE-ADDR.
          (if (and (obj-has-attr? result 'CACHE-ADDR)
                   (or (hw-getter result) (hw-setter result)))
-             (parse-error errtxt "can't have CACHE-ADDR with get/set specs" name))
+             (parse-error context "can't have CACHE-ADDR with get/set specs"
+                          name))
          result)
 
        (begin
 ; Read a hardware description
 ; This is the main routine for analyzing a hardware description in the .cpu
 ; file.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
 ; -hw-parse is invoked to create the <hardware> object.
 
-(define (-hw-read errtxt . arg-list)
-  (let ((name nil)          ; name of hardware
+(define (-hw-read context . arg-list)
+  (let (
+       (name nil)
        (comment "")
        (attrs nil)
        (semantic-name nil) ; name used in semantics, default is `name'
        (set nil)
        (layout nil)
        )
+
     ; Loop over each element in ARG-LIST, recording what's found.
     (let loop ((arg-list arg-list))
       (if (null? arg-list)
              ((get) (set! get (cdr arg)))
              ((set) (set! set (cdr arg)))
              ((layout) (set! layout (cdr arg)))
-             (else (parse-error errtxt "invalid hardware arg" arg)))
+             (else (parse-error context "invalid hardware arg" arg)))
            (loop (cdr arg-list)))))
+
     ; Now that we've identified the elements, build the object.
-    (-hw-parse errtxt name comment attrs
+    (-hw-parse context name comment attrs
               (if (null? semantic-name) name semantic-name)
-              type indices values handlers get set layout)
-    )
+              type indices values handlers get set layout))
 )
 
 ; Define a hardware object, name/value pair list version.
 
 (define define-hardware
   (lambda arg-list
-    (let ((hw (apply -hw-read (cons "define-hardware" arg-list))))
+    (let ((hw (apply -hw-read (cons (make-current-context "define-hardware")
+                                   arg-list))))
       (if hw
          (current-hw-add! hw))
       hw))
 
 (define (define-full-hardware name comment attrs semantic-name type
                              indices values handlers get set layout)
-  (let ((hw (-hw-parse "define-full-hardware"
+  (let ((hw (-hw-parse (make-current-context "define-full-hardware")
                       name comment attrs semantic-name type
                       indices values handlers get set layout)))
     (if hw
 
 (define modify-hardware
   (lambda arg-list
-    (let ((errtxt "modify-hardware"))
+    (let ((context (make-current-context "modify-hardware")))
 
       ; FIXME: Experiment.  This implements the :name/value style by
       ; converting it to (name value).  In the end there shouldn't be two
       ; There's no requirement that the name be specified first.
       (let ((hw-spec (assq 'name arg-list)))
        (if (not hw-spec)
-           (parse-error errtxt "hardware name not specified"))
+           (parse-error context "hardware name not specified" arg-list))
 
-       (let ((hw (current-hw-lookup (arg-list-symbol-arg errtxt hw-spec))))
+       (let ((hw (current-hw-lookup (arg-list-symbol-arg context hw-spec))))
          (if (not hw)
-             (parse-error errtxt "undefined hardware element" hw-spec))
+             (parse-error context "undefined hardware element" hw-spec))
 
          ; Process the rest of the args now that we have the affected object.
          (let loop ((args arg-list))
                  (case (car arg-spec)
                    ((name) #f) ; ignore, already processed
                    ((add-attrs)
-                    (let ((atlist-obj (atlist-parse (cdr arg-spec)
-                                                    "cgen_hw" errtxt)))
+                    (let ((atlist-obj (atlist-parse context (cdr arg-spec)
+                                                    "cgen_hw")))
                       ; prepend attrs so new ones override existing ones
                       (obj-prepend-atlist! hw atlist-obj)))
                    (else
-                    (parse-error errtxt "invalid/unsupported option" (car arg-spec))))
+                    (parse-error context "invalid/unsupported option"
+                                 (car arg-spec))))
                  (loop (cdr args))))))))
 
     *UNSPECIFIED*)
 ; - (value length)
 ; - hardware-name
 
-(define (-hw-validate-layout errtxt layout width)
+(define (-hw-validate-layout context layout width)
   (if (not (list? layout))
-      (parse-error errtxt "layout is not a list" layout))
+      (parse-error context "layout is not a list" layout))
 
   (let loop ((layout layout) (shift 0))
     (if (null? layout)
        (begin
          ; Done.  Now see if number of bits in layout matches total width.
          (if (not (= shift width))
-             (parse-error errtxt (string-append
-                                  "insufficient number of bits (need "
-                                  (number->string width)
-                                  ")")
+             (parse-error context (string-append
+                                   "insufficient number of bits (need "
+                                   (number->string width)
+                                   ")")
                           shift)))
        ; Validate next entry.
        (let ((val (car layout)))
          (cond ((number? val)
                 (if (not (memq val '(0 1)))
-                    (parse-error errtxt
+                    (parse-error context
                                  "non 0/1 layout entry requires length"
                                  val))
                 (loop (cdr layout) (1+ shift)))
                         (not (pair? (cdr val)))
                         (not (number? (cadr val)))
                         (not (null? (cddr val))))
-                    (parse-error errtxt
+                    (parse-error context
                                  "syntax error in layout, expecting `(value length)'"
                                  val))
                 (loop (cdr layout) (+ shift (cadr val))))
                ((symbol? val)
                 (let ((hw (current-hw-lookup val)))
                   (if (not hw)
-                      (parse-error errtxt "unknown hardware element" val))
+                      (parse-error context "unknown hardware element" val))
                   (if (not (hw-scalar? hw))
-                      (parse-error errtxt "non-scalar hardware element" val))
+                      (parse-error context "non-scalar hardware element" val))
                   (loop (cdr layout)
                         (+ shift (hw-bits hw)))))
                (else
-                (parse-error errtxt "bad layout element" val))))))
+                (parse-error context "bad layout element" val))))))
+
   *UNSPECIFIED*
 )
 
 ;      (or SI (sll SI (zext SI (reg h-hw2)) 1)
 ;          (zext SI (reg h-hw3)))))
 
-(define (-hw-create-getter-from-layout errtxt layout width)
+(define (-hw-create-getter-from-layout context layout width)
   (let ((add-to-res (lambda (result mode-name val shift)
                      (if (null? result)
                          (rtx-make 'sll mode-name val shift)
 ;            (set (reg h-hw3) (and (srl val 0) 1))
 ;            ))
 
-(define (-hw-create-setter-from-layout errtxt layout width)
+(define (-hw-create-setter-from-layout context layout width)
   (let ((mode-name (obj:name (mode-find width 'UINT))))
     (let loop ((sets nil) (layout (reverse layout)) (shift 0))
       (if (null? layout)
 
 (method-make!
  <hw-register> 'parse!
- (lambda (self errtxt type indices values handlers getter setter layout)
+ (lambda (self context type indices values handlers getter setter layout)
    (if (or (null? type)
           (> (length type) 2))
-       (parse-error errtxt "invalid register spec" type))
+       (parse-error context "invalid register spec" type))
    (if (and (= (length type) 2)
            (or (not (list? (cadr type)))
                (> (length (cadr type)) 1)))
-       (parse-error errtxt "bad register dimension spec" type))
+       (parse-error context "bad register dimension spec" type))
 
    ; Must parse and set type before analyzing LAYOUT.
-   (elm-set! self 'type (parse-type errtxt type))
+   (elm-set! self 'type (parse-type context type))
 
    ; LAYOUT is a shorthand way of specifying getter/setter specs.
    ; For registers that are just a collection of other registers
    ; We don't override any provided get/set specs though.
    (if (not (null? layout))
        (let ((width (hw-bits self)))
-        (-hw-validate-layout errtxt layout width)
+        (-hw-validate-layout context layout width)
         (if (null? getter)
             (set! getter
-                  (-hw-create-getter-from-layout errtxt layout width)))
+                  (-hw-create-getter-from-layout context layout width)))
         (if (null? setter)
             (set! setter
-                  (-hw-create-setter-from-layout errtxt layout width)))
+                  (-hw-create-setter-from-layout context layout width)))
         ))
 
-   (elm-set! self 'indices (-hw-parse-indices errtxt indices self UINT))
-   (elm-set! self 'values (-hw-parse-values errtxt values self
+   (elm-set! self 'indices (-hw-parse-indices context indices self UINT))
+   (elm-set! self 'values (-hw-parse-values context values self
                                            (send (elm-get self 'type)
                                                  'get-mode)))
-   (elm-set! self 'handlers (-hw-parse-handlers errtxt handlers))
-   (elm-set! self 'get (-hw-parse-getter errtxt getter (hw-scalar? self)))
-   (elm-set! self 'set (-hw-parse-setter errtxt setter (hw-scalar? self)))
+   (elm-set! self 'handlers (-hw-parse-handlers context handlers))
+   (elm-set! self 'get (-hw-parse-getter context getter (hw-scalar? self)))
+   (elm-set! self 'set (-hw-parse-setter context setter (hw-scalar? self)))
    *UNSPECIFIED*)
 )
 
 
 (method-make!
  <hw-pc> 'parse!
- (lambda (self errtxt type indices values handlers getter setter layout)
+ (lambda (self context type indices values handlers getter setter layout)
    (if (not (null? type))
-       (elm-set! self 'type (parse-type errtxt type))
+       (elm-set! self 'type (parse-type context type))
        (elm-set! self 'type (make <scalar> (mode:lookup 'IAI))))
    (if (not (null? indices))
-       (parse-error errtxt "indices specified for pc" indices))
+       (parse-error context "indices specified for pc" indices))
    (if (not (null? values))
-       (parse-error errtxt "values specified for pc" values))
+       (parse-error context "values specified for pc" values))
    (if (not (null? layout))
-       (parse-error errtxt "layout specified for pc" values))
+       (parse-error context "layout specified for pc" values))
    ; The initial value of INDICES, VALUES is #f which is what we want.
-   (elm-set! self 'handlers (-hw-parse-handlers errtxt handlers))
-   (elm-set! self 'get (-hw-parse-getter errtxt getter (hw-scalar? self)))
-   (elm-set! self 'set (-hw-parse-setter errtxt setter (hw-scalar? self)))
+   (elm-set! self 'handlers (-hw-parse-handlers context handlers))
+   (elm-set! self 'get (-hw-parse-getter context getter (hw-scalar? self)))
+   (elm-set! self 'set (-hw-parse-setter context setter (hw-scalar? self)))
    *UNSPECIFIED*)
 )
 
 
 (method-make!
  <hw-memory> 'parse!
- (lambda (self errtxt type indices values handlers getter setter layout)
+ (lambda (self context type indices values handlers getter setter layout)
    (if (or (null? type)
           (> (length type) 2))
-       (parse-error errtxt "invalid memory spec" type))
+       (parse-error context "invalid memory spec" type))
    (if (and (= (length type) 2)
            (or (not (list? (cadr type)))
                (> (length (cadr type)) 1)))
-       (parse-error errtxt "bad memory dimension spec" type))
+       (parse-error context "bad memory dimension spec" type))
    (if (not (null? layout))
-       (parse-error errtxt "layout specified for memory" values))
-   (elm-set! self 'type (parse-type errtxt type))
+       (parse-error context "layout specified for memory" values))
+   (elm-set! self 'type (parse-type context type))
    ; Setting INDICES,VALUES here is mostly for experimentation at present.
-   (elm-set! self 'indices (-hw-parse-indices errtxt indices self AI))
-   (elm-set! self 'values (-hw-parse-values errtxt values self
+   (elm-set! self 'indices (-hw-parse-indices context indices self AI))
+   (elm-set! self 'values (-hw-parse-values context values self
                                            (send (elm-get self 'type)
                                                  'get-mode)))
-   (elm-set! self 'handlers (-hw-parse-handlers errtxt handlers))
-   (elm-set! self 'get (-hw-parse-getter errtxt getter (hw-scalar? self)))
-   (elm-set! self 'set (-hw-parse-setter errtxt setter (hw-scalar? self)))
+   (elm-set! self 'handlers (-hw-parse-handlers context handlers))
+   (elm-set! self 'get (-hw-parse-getter context getter (hw-scalar? self)))
+   (elm-set! self 'set (-hw-parse-setter context setter (hw-scalar? self)))
    *UNSPECIFIED*)
 )
 
 
 (method-make!
  <hw-immediate> 'parse!
- (lambda (self errtxt type indices values handlers getter setter layout)
+ (lambda (self context type indices values handlers getter setter layout)
    (if (not (= (length type) 1))
-       (parse-error errtxt "invalid immediate spec" type))
-   (elm-set! self 'type (parse-type errtxt type))
+       (parse-error context "invalid immediate spec" type))
+   (elm-set! self 'type (parse-type context type))
    ; An array of immediates may be useful some day, but not yet.
    (if (not (null? indices))
-       (parse-error errtxt "indices specified for immediate" indices))
+       (parse-error context "indices specified for immediate" indices))
    (if (not (null? layout))
-       (parse-error errtxt "layout specified for immediate" values))
-   (elm-set! self 'values (-hw-parse-values errtxt values self
+       (parse-error context "layout specified for immediate" values))
+   (elm-set! self 'values (-hw-parse-values context values self
                                            (send (elm-get self 'type)
                                                  'get-mode)))
-   (elm-set! self 'handlers (-hw-parse-handlers errtxt handlers))
+   (elm-set! self 'handlers (-hw-parse-handlers context handlers))
    (if (not (null? getter))
-       (parse-error errtxt "getter specified for immediate" getter))
+       (parse-error context "getter specified for immediate" getter))
    (if (not (null? setter))
-       (parse-error errtxt "setter specified for immediate" setter))
+       (parse-error context "setter specified for immediate" setter))
    *UNSPECIFIED*)
 )
 
 
 (method-make!
  <hw-address> 'parse!
- (lambda (self errtxt type indices values handlers getter setter layout)
+ (lambda (self context type indices values handlers getter setter layout)
    (if (not (null? type))
-       (parse-error errtxt "invalid address spec" type))
+       (parse-error context "invalid address spec" type))
    (elm-set! self 'type (make <scalar> AI))
    (if (not (null? indices))
-       (parse-error errtxt "indices specified for address" indices))
+       (parse-error context "indices specified for address" indices))
    (if (not (null? values))
-       (parse-error errtxt "values specified for address" values))
+       (parse-error context "values specified for address" values))
    (if (not (null? layout))
-       (parse-error errtxt "layout specified for address" values))
-   (elm-set! self 'values (-hw-parse-values errtxt values self
+       (parse-error context "layout specified for address" values))
+   (elm-set! self 'values (-hw-parse-values context values self
                                            (send (elm-get self 'type)
                                                  'get-mode)))
-   (elm-set! self 'handlers (-hw-parse-handlers errtxt handlers))
+   (elm-set! self 'handlers (-hw-parse-handlers context handlers))
    (if (not (null? getter))
-       (parse-error errtxt "getter specified for address" getter))
+       (parse-error context "getter specified for address" getter))
    (if (not (null? setter))
-       (parse-error errtxt "setter specified for address" setter))
+       (parse-error context "setter specified for address" setter))
    *UNSPECIFIED*)
 )
 
index 7984011..e2f7038 100644 (file)
@@ -682,9 +682,6 @@ See the input .cpu file(s) for copyright information.
   (let*
       ((context #f) ; ??? do we need a better context?
 
-       ; String for error messages.
-       (errtxt "semantic attribute computation for html")
-
        ; List of attributes computed from SEM-CODE-LIST.
        ; The first element is just a dummy so that append! always works.
        (sem-attrs (list #f))
index 14507eb..16616c1 100644 (file)
 ;
 ; FIXME: More error checking.
 
-(define (-ifield-parse errtxt name comment attrs
+(define (-ifield-parse context name comment attrs
                       word-offset word-length start flength follows
                       mode encode decode)
   (logit 2 "Processing ifield " name " ...\n")
 
-  (let* ((name (parse-name name errtxt))
-        (atlist (atlist-parse attrs "cgen_ifld" errtxt))
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name))
+        (atlist (atlist-parse context attrs "cgen_ifld"))
         (isas (bitset-attr->list (atlist-attr-value atlist 'ISA #f))))
 
     ; No longer ensure only one isa specified.
     ;(if (!= (length isas) 1)
-    ;  (parse-error errtxt "can only specify 1 isa" attrs))
+    ;  (parse-error context "can only specify 1 isa" attrs))
 
     (if (not (eq? (->bool word-offset)
                  (->bool word-length)))
-       (parse-error errtxt "either both or neither of word-offset,word-length can be specified"))
+       (parse-error context "either both or neither of word-offset,word-length can be specified"))
 
     (if (keep-isa-atlist? atlist #f)
 
        (let ((isa (current-isa-lookup (car isas)))
              (word-offset (and word-offset
-                               (parse-number errtxt word-offset '(0 . 256))))
+                               (parse-number context word-offset '(0 . 256))))
              (word-length (and word-length
-                               (parse-number errtxt word-length '(0 . 128))))
+                               (parse-number context word-length '(0 . 128))))
              ; ??? 0.127 for now
-             (start (parse-number errtxt start '(0 . 127)))
+             (start (parse-number context start '(0 . 127)))
              ; ??? 0.127 for now
-             (flength (parse-number errtxt flength '(0 . 127)))
+             (flength (parse-number context flength '(0 . 127)))
              (lsb0? (current-arch-insn-lsb0?))
-             (mode-obj (parse-mode-name mode errtxt))
-             (follows-obj (-ifld-parse-follows errtxt follows))
+             (mode-obj (parse-mode-name context mode))
+             (follows-obj (-ifld-parse-follows context follows))
              )
 
          ; Calculate the <bitrange> object.
            (let ((result
                   (make <ifield>
                         name
-                        (parse-comment comment errtxt)
+                        (parse-comment context comment)
                         atlist
                         mode-obj
                         bitrange
-                        (-ifld-parse-encode errtxt encode)
-                        (-ifld-parse-decode errtxt decode))))
+                        (-ifld-parse-encode context encode)
+                        (-ifld-parse-decode context decode))))
              (if follows-obj
                  (ifld-set-follows! result follows-obj))
              result)))
 
 ; Read an instruction field description.
 ; This is the main routine for analyzing instruction fields in the .cpu file.
-; ERRTXT is prepended to error messages to provide context.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
 ; -ifield-parse is invoked to create the <ifield> object.
 
-(define (-ifield-read errtxt . arg-list)
-  (let (; Current ifield elements:
-       (name nil)
+(define (-ifield-read context . arg-list)
+  (let (
+       (name #f)
        (comment "")
        (attrs nil)
        (word-offset #f)
        (encode #f)
        (decode #f)
        )
+
     ; Loop over each element in ARG-LIST, recording what's found.
     (let loop ((arg-list arg-list))
       (if (null? arg-list)
              ((follows) (set! follows (cadr arg)))
              ((encode) (set! encode (cdr arg)))
              ((decode) (set! decode (cdr arg)))
-             (else (parse-error errtxt "invalid ifield arg" arg)))
+             (else (parse-error context "invalid ifield arg" arg)))
            (loop (cdr arg-list)))))
 
     ; See if encode/decode were specified as "unspecified".
        (set! decode #f))
 
     ; Now that we've identified the elements, build the object.
-    (-ifield-parse errtxt name comment attrs
+    (-ifield-parse context name comment attrs
                   word-offset word-length start length- follows
-                  mode encode decode)
-    )
+                  mode encode decode))
 )
 
 ; Parse a `follows' spec.
 
-(define (-ifld-parse-follows errtxt follows)
+(define (-ifld-parse-follows context follows)
   (if follows
       (let ((follows-obj (current-op-lookup follows)))
        (if (not follows-obj)
-           (parse-error errtxt "unknown operand to follow" follows))
+           (parse-error context "unknown operand to follow" follows))
        follows-obj)
       #f)
 )
 
 ; Do common parts of <ifield> encode/decode processing.
 
-(define (-ifld-parse-encode-decode errtxt which value)
+(define (-ifld-parse-encode-decode context which value)
   (if value
       (begin
        (if (or (not (list? value))
                (not (list? (car value)))
                (not (= (length (car value)) 2))
                (not (list? (cadr value))))
-           (parse-error errtxt
+           (parse-error context
                         (string-append "bad ifield " which " spec")
                         value))
        (if (or (not (> (length (cadr value)) 2))
                (not (mode:lookup (cadr (cadr value)))))
-           (parse-error errtxt
+           (parse-error context
                         (string-append which " expression must have a mode")
                         value))))
   value
 
 ; Parse an <ifield> encode spec.
 
-(define (-ifld-parse-encode errtxt encode)
-  (-ifld-parse-encode-decode errtxt "encode" encode)
+(define (-ifld-parse-encode context encode)
+  (-ifld-parse-encode-decode context "encode" encode)
 )
 
 ; Parse an <ifield> decode spec.
 
-(define (-ifld-parse-decode errtxt decode)
-  (-ifld-parse-encode-decode errtxt "decode" decode)
+(define (-ifld-parse-decode context decode)
+  (-ifld-parse-encode-decode context "decode" decode)
 )
 
 ; Define an instruction field object, name/value pair list version.
 
 (define define-ifield
   (lambda arg-list
-    (let ((f (apply -ifield-read (cons "define-ifield" arg-list))))
+    (let ((f (apply -ifield-read (cons (make-current-context "define-ifield")
+                                      arg-list))))
       (if f
          (current-ifld-add! f))
       f))
 ; FIXME: Eventually this should be fixed to take *all* arguments.
 
 (define (define-full-ifield name comment attrs start length mode encode decode)
-  (let ((f (-ifield-parse "define-full-ifield" name comment attrs
+  (let ((f (-ifield-parse (make-current-context "define-full-ifield")
+                         name comment attrs
                          #f #f start length #f mode encode decode)))
     (if f
        (current-ifld-add! f))
@@ -861,39 +865,44 @@ Define an instruction multi-field, all arguments specified.
 ; All arguments are in raw (non-evaluated) form.
 ; The result is the parsed object or #f if object isn't for selected mach(s).
 
-(define (-multi-ifield-parse errtxt name comment attrs mode
+(define (-multi-ifield-parse context name comment attrs mode
                             subfields insert extract encode decode)
   (logit 2 "Processing multi-ifield element " name " ...\n")
 
   (if (null? subfields)
-      (parse-error errtxt "empty subfield list" subfields))
+      (parse-error context "empty subfield list" subfields))
 
-  (let* ((name (parse-name name errtxt))
-        (atlist (atlist-parse attrs "cgen_ifld" errtxt))
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name))
+        (atlist (atlist-parse context attrs "cgen_ifld"))
         (isas (bitset-attr->list (atlist-attr-value atlist 'ISA #f))))
 
     ; No longer ensure only one isa specified.
-    ; (if (!= (length isas) 1) 
-    ;     (parse-error errtxt "can only specify 1 isa" attrs))
+    ; (if (!= (length isas) 1)
+    ;     (parse-error context "can only specify 1 isa" attrs))
 
     (if (keep-isa-atlist? atlist #f)
+
        (begin
          (let ((result (new <multi-ifield>))
                (subfields (map (lambda (subfld)
                                  (let ((f (current-ifld-lookup subfld)))
                                    (if (not f)
-                                       (parse-error errtxt "unknown ifield" subfld))
+                                       (parse-error context "unknown ifield"
+                                                    subfld))
                                    f))
                                subfields)))
 
            (elm-xset! result 'name name)
-           (elm-xset! result 'comment (parse-comment comment errtxt))
-                                       ; multi-ifields are always VIRTUAL
+           (elm-xset! result 'comment (parse-comment context comment))
            (elm-xset! result 'attrs
-                      (atlist-parse (cons 'VIRTUAL attrs) "multi-ifield" errtxt))
-           (elm-xset! result 'mode (parse-mode-name mode errtxt))
-           (elm-xset! result 'encode (-ifld-parse-encode errtxt encode))
-           (elm-xset! result 'decode (-ifld-parse-encode errtxt decode))
+                      ;; multi-ifields are always VIRTUAL
+                      (atlist-parse context (cons 'VIRTUAL attrs)
+                                    "multi-ifield"))
+           (elm-xset! result 'mode (parse-mode-name context mode))
+           (elm-xset! result 'encode (-ifld-parse-encode context encode))
+           (elm-xset! result 'decode (-ifld-parse-encode context decode))
            (if insert
                (elm-xset! result 'insert insert)
                (elm-xset! result 'insert
@@ -904,14 +913,19 @@ Define an instruction multi-field, all arguments specified.
                           (-multi-ifield-make-default-extract name subfields)))
            (elm-xset! result 'subfields subfields)
            result))
+
        ; else don't keep isa
        #f))
 )
 
 ; Read an instruction multi-ifield.
+; This is the main routine for analyzing multi-ifields in the .cpu file.
+; CONTEXT is a <context> object for error messages.
+; ARG-LIST is an associative list of field name and field value.
+; -multi-ifield-parse is invoked to create the `multi-ifield' object.
 
-(define (-multi-ifield-read errtxt . arg-list)
-  (let (; Current multi-ifield elements:
+(define (-multi-ifield-read context . arg-list)
+  (let (
        (name nil)
        (comment "")
        (attrs nil)
@@ -922,6 +936,7 @@ Define an instruction multi-field, all arguments specified.
        (encode #f)
        (decode #f)
        )
+
     ; Loop over each element in ARG-LIST, recording what's found.
     (let loop ((arg-list arg-list))
       (if (null? arg-list)
@@ -938,19 +953,20 @@ Define an instruction multi-field, all arguments specified.
              ((extract) (set! extract (cadr arg)))
              ((encode) (set! encode (cdr arg)))
              ((decode) (set! decode (cdr arg)))
-             (else (parse-error errtxt "invalid ifield arg" arg)))
+             (else (parse-error context "invalid ifield arg" arg)))
            (loop (cdr arg-list)))))
+
     ; Now that we've identified the elements, build the object.
-    (-multi-ifield-parse errtxt name comment attrs mode subflds
-                        insert extract encode decode)
-    )
+    (-multi-ifield-parse context name comment attrs mode subflds
+                        insert extract encode decode))
 )
 
 ; Define an instruction multi-field object, name/value pair list version.
 
 (define define-multi-ifield
   (lambda arg-list
-    (let ((f (apply -multi-ifield-read (cons "define-multi-ifield" arg-list))))
+    (let ((f (apply -multi-ifield-read (cons (make-current-context "define-multi-ifield")
+                                            arg-list))))
       (if f
          (current-ifld-add! f))
       f))
@@ -960,7 +976,8 @@ Define an instruction multi-field, all arguments specified.
 ; FIXME: encode/decode arguments are missing.
 
 (define (define-full-multi-ifield name comment attrs mode subflds insert extract)
-  (let ((f (-multi-ifield-parse "define-full-multi-ifield" name comment attrs
+  (let ((f (-multi-ifield-parse (make-current-context "define-full-multi-ifield")
+                               name comment attrs
                                mode subflds insert extract #f #f)))
     (current-ifld-add! f)
     f)
@@ -995,7 +1012,6 @@ Define an instruction multi-field, all arguments specified.
              nil)
 )
 
-
 (method-make!
  <derived-ifield> 'needed-iflds
  (lambda (self)
@@ -1003,7 +1019,6 @@ Define an instruction multi-field, all arguments specified.
         (elm-get self 'subfields)))
 )
 
-
 (method-make!
  <derived-ifield> 'make!
  (lambda (self name comment attrs owner subfields)
index a034248..b889cc5 100644 (file)
 ; All arguments are in raw (non-evaluated) form.
 ; The result is the parsed object or #f if insn isn't for selected mach(s).
 
-(define (-insn-parse errtxt name comment attrs syntax fmt ifield-assertion
+(define (-insn-parse context name comment attrs syntax fmt ifield-assertion
                     semantics timing)
   (logit 2 "Processing insn " name " ...\n")
 
-  (let ((name (parse-name name errtxt))
-       (atlist-obj (atlist-parse attrs "cgen_insn" errtxt)))
+  ;; Pick out name first to augment the error context.
+  (let ((name (parse-name context name))
+       (context (context-append-name context name))
+       (atlist-obj (atlist-parse context attrs "cgen_insn")))
 
     (if (keep-atlist? atlist-obj #f)
 
              (semantics (if (not (null? semantics))
                             semantics
                             #f))
-             (format (-parse-insn-format (string-append errtxt " format")
+             (format (-parse-insn-format (context-append context " format")
                                          fmt))
-             (comment (parse-comment comment errtxt))
+             (comment (parse-comment context comment))
              ; If there are no semantics, mark this as an alias.
              ; ??? Not sure this makes sense for multi-insns.
              (atlist-obj (if semantics
                              atlist-obj
                              (atlist-cons (bool-attr-make 'ALIAS #t)
                                           atlist-obj)))
-             (syntax (parse-syntax syntax errtxt))
-             (timing (parse-insn-timing errtxt timing))
+             (syntax (parse-syntax context syntax))
+             (timing (parse-insn-timing context timing))
              )
 
          (if (anyof-operand-format? format)
 ; Read an instruction description.
 ; This is the main routine for analyzing instructions in the .cpu file.
 ; This is also used to create virtual insns by apps like simulators.
-; ERRTXT is prepended to error messages to provide context.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
 ; -insn-parse is invoked to create the <insn> object.
 
-(define (insn-read errtxt . arg-list)
-  (let ((name nil)
+(define (insn-read context . arg-list)
+  (let (
+       (name nil)
        (comment "")
        (attrs nil)
        (syntax nil)
        (semantics nil)
        (timing nil)
        )
+
     ; Loop over each element in ARG-LIST, recording what's found.
     (let loop ((arg-list arg-list))
       (if (null? arg-list)
              ((ifield-assertion) (set! ifield-assertion (cadr arg)))
              ((semantics) (set! semantics (cadr arg)))
              ((timing) (set! timing (cdr arg)))
-             (else (parse-error errtxt "invalid insn arg" arg)))
+             (else (parse-error context "invalid insn arg" arg)))
            (loop (cdr arg-list)))))
+
     ; Now that we've identified the elements, build the object.
-    (-insn-parse errtxt name comment attrs syntax fmt ifield-assertion
-                semantics timing)
-    )
+    (-insn-parse context name comment attrs syntax fmt ifield-assertion
+                semantics timing))
 )
 
 ; Define an instruction object, name/value pair list version.
 
 (define define-insn
   (lambda arg-list
-    (let ((i (apply insn-read (cons "define-insn" arg-list))))
+    (let ((i (apply insn-read (cons (make-current-context "define-insn")
+                                   arg-list))))
       (if i
          (current-insn-add! i))
       i))
 
 (define (define-full-insn name comment attrs syntax fmt ifield-assertion
          semantics timing)
-  (let ((i (-insn-parse "define-full-insn" name comment attrs
+  (let ((i (-insn-parse (make-current-context "define-full-insn")
+                       name comment attrs
                        syntax fmt ifield-assertion
                        semantics timing)))
     (if i
 ; in turn be a list of strings.
 ; ??? Not sure this extra flexibility is worth it yet.
 
-(define (parse-syntax syntax errtxt)
+(define (parse-syntax context syntax)
   (cond ((list? syntax)
-        (string-map (lambda (elm) (parse-syntax elm errtxt)) syntax))
+        (string-map (lambda (elm) (parse-syntax context elm)) syntax))
        ((or (string? syntax) (symbol? syntax))
         syntax)
-       (else (parse-error errtxt "improper syntax" syntax)))
+       (else (parse-error context "improper syntax" syntax)))
 )
 
 ; Subroutine of -parse-insn-format to parse a symbol ifield spec.
 
-(define (-parse-insn-format-symbol errtxt sym)
+(define (-parse-insn-format-symbol context sym)
   ;(debug-repl-env sym)
   (let ((op (current-op-lookup sym)))
     (if op
        (let ((e (ienum-lookup-val sym)))
          (if e
              (ifld-new-value (ienum:fld (cdr e)) (car e))
-             (parse-error errtxt "bad format element, expecting symbol to be operand or insn enum" sym)))))
+             (parse-error context "bad format element, expecting symbol to be operand or insn enum" sym)))))
 )
 
 ; Subroutine of -parse-insn-format to parse an (ifield-name value) ifield spec.
 ;
 ; ??? Error messages need improvement, but that's generally true of cgen.
 
-(define (-parse-insn-format-ifield-spec errtxt ifld ifld-spec)
+(define (-parse-insn-format-ifield-spec context ifld ifld-spec)
   (if (!= (length ifld-spec) 2)
-      (parse-error errtxt "bad ifield format, should be (ifield-name value)" ifld-spec))
+      (parse-error context "bad ifield format, should be (ifield-name value)" ifld-spec))
 
   (let ((value (cadr ifld-spec)))
     ; ??? This use to allow (ifield-name operand-name).  That's how
          ((symbol? value)
           (let ((e (enum-lookup-val value)))
             (if (not e)
-                (parse-error errtxt "symbolic ifield value not an enum" ifld-spec))
+                (parse-error context "symbolic ifield value not an enum" ifld-spec))
             (ifld-new-value ifld (car e))))
          (else
-          (parse-error errtxt "ifield value not an integer or enum" ifld-spec))))
+          (parse-error context "ifield value not an integer or enum" ifld-spec))))
 )
 
 ; Subroutine of -parse-insn-format to parse an
 ; ??? There is room for growth in the specification syntax here.
 ; Possibilities are (ifield-name|operand-name [options] [value]).
 
-(define (-parse-insn-format-list errtxt spec)
+(define (-parse-insn-format-list context spec)
   (let ((ifld (current-ifld-lookup (car spec))))
     (if ifld
-       (-parse-insn-format-ifield-spec errtxt ifld spec)
-       (parse-error errtxt "unknown ifield" spec)))
+       (-parse-insn-format-ifield-spec context ifld spec)
+       (parse-error context "unknown ifield" spec)))
 )
 
 ; Given an insn format field from a .cpu file, replace it with a list of
 ; It's called for each instruction, and is one of the more expensive routines
 ; in insn parsing.
 
-(define (-parse-insn-format errtxt fld-list)
+(define (-parse-insn-format context fld-list)
   (if (null? fld-list)
       nil ; field list unspecified
       (case (car fld-list)
                                 (string->symbol fld)
                                 fld)))
                      (cond ((symbol? f)
-                            (-parse-insn-format-symbol errtxt f))
+                            (-parse-insn-format-symbol context f))
                            ((and (list? f)
                                  ; ??? This use to allow <ifield> objects
                                  ; in the `car' position.  Checked for below.
                                  (symbol? (car f)))
-                            (-parse-insn-format-list errtxt f))
+                            (-parse-insn-format-list context f))
                            (else
                             (if (and (list? f)
                                      (ifield? (car f)))
-                                (parse-error errtxt "FIXME: <ifield> object in format spec"))
-                            (parse-error errtxt "bad format element, neither symbol nor ifield spec" f)))))
+                                (parse-error context "FIXME: <ifield> object in format spec" f))
+                            (parse-error context "bad format element, neither symbol nor ifield spec" f)))))
                  (cdr fld-list)))
        ((=) (begin
               (if (or (!= (length fld-list) 2)
                       (not (symbol? (cadr fld-list))))
-                  (parse-error errtxt
+                  (parse-error context
                                "bad `=' format spec, should be `(= insn-name)'"
                                fld-list))
               (let ((insn (current-insn-lookup (cadr fld-list))))
                 (if (not insn)
-                    (parse-error errtxt "unknown insn" (cadr fld-list)))
+                    (parse-error context "unknown insn" (cadr fld-list)))
                 (insn-iflds insn))))
        (else
-        (parse-error errtxt "format must begin with `+' or `='" fld-list))
+        (parse-error context "format must begin with `+' or `='" fld-list))
        ))
 )
 
index f3b5e95..6bddf13 100644 (file)
 
 ; Parse an alignment spec.
 
-(define (-arch-parse-alignment errtxt alignment)
+(define (-arch-parse-alignment context alignment)
   (if (memq alignment '(aligned unaligned forced))
       alignment
-      (parse-error errtxt "invalid alignment" alignment))
+      (parse-error context "invalid alignment" alignment))
 )
 
 ; Parse an arch mach spec.
 ; The value is a list of mach names or (mach-name sanitize-key) elements.
 ; The result is a list of (mach-name . sanitize-key) elements.
 
-(define (-arch-parse-machs errtxt machs)
+(define (-arch-parse-machs context machs)
   (for-each (lambda (m)
              (if (or (symbol? m)
                      (and (list? m) (= (length m) 2)
                           (symbol? (car m)) (symbol? (cadr m))))
                  #t ; ok
-                 (parse-error errtxt "bad arch mach spec" m)))
+                 (parse-error context "bad arch mach spec" m)))
            machs)
   (map (lambda (m)
         (if (symbol? m)
 ; The value is a list of isa names or (isa-name sanitize-key) elements.
 ; The result is a list of (isa-name . sanitize-key) elements.
 
-(define (-arch-parse-isas errtxt isas)
+(define (-arch-parse-isas context isas)
   (for-each (lambda (m)
              (if (or (symbol? m)
                      (and (list? m) (= (length m) 2)
                           (symbol? (car m)) (symbol? (cadr m))))
                  #t ; ok
-                 (parse-error errtxt "bad arch isa spec" m)))
+                 (parse-error context "bad arch isa spec" m)))
            isas)
   (map (lambda (m)
         (if (symbol? m)
                     machs isas)
   (logit 2 "Processing arch " name " ...\n")
   (make <arch-data>
-    (parse-name name context)
-    (parse-comment comment context)
-    (atlist-parse attrs "arch" context)
+    (parse-name context name)
+    (parse-comment context comment)
+    (atlist-parse context attrs "arch")
     (-arch-parse-alignment context default-alignment)
     (parse-boolean context insn-lsb0?)
     (-arch-parse-machs context machs)
                    setup-semantics decode-splits)
   (logit 2 "Processing isa " name " ...\n")
 
-  (let ((name (parse-name name context)))
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name)))
+
     (if (not (memq name (current-arch-isa-name-list)))
        (parse-error context "isa name is not present in `define-arch'" name))
 
     ; for builtin objects.
     (make <isa>
       name
-      (parse-comment comment context)
-      (atlist-parse attrs "isa" context)
-      (parse-number (string-append context
-                                  ": default-insn-word-bitsize")
+      (parse-comment context comment)
+      (atlist-parse context attrs "isa")
+      (parse-number (context-append context
+                                   ": default-insn-word-bitsize")
                    default-insn-word-bitsize '(8 . 128))
-      (parse-number (string-append context
-                                  ": default-insn-bitsize")
+      (parse-number (context-append context
+                                   ": default-insn-bitsize")
                    default-insn-bitsize '(8 . 128))
-      (parse-number (string-append context
-                                  ": base-insn-bitsize")
+      (parse-number (context-append context
+                                   ": base-insn-bitsize")
                    base-insn-bitsize '(8 . 128))
       decode-assist
       liw-insns
 ; Read an isa entry.
 ; ARG-LIST is an associative list of field name and field value.
 
-(define -isa-read
-  (lambda arg-list
-    (let ((context "isa-read")
-         ; <isa> object members and default values
-         (name #f)
-         (attrs nil)
-         (comment "")
-         (base-insn-bitsize #f)
-         (default-insn-bitsize #f)
-         (default-insn-word-bitsize #f)
-         (decode-assist nil)
-         (liw-insns 1)
-         ; FIXME: Hobbit computes the wrong symbol for `parallel-insns'
-         ; in the `case' expression below because there is a local var
-         ; of the same name ("__1" gets appended to the symbol name).
-         (parallel-insns- 1)
-         (condition nil)
-         (setup-semantics nil)
-         (decode-splits nil)
-         )
-      (let loop ((arg-list arg-list))
-       (if (null? arg-list)
-           nil
-           (let ((arg (car arg-list))
-                 (elm-name (caar arg-list)))
-             (case elm-name
-               ((name) (set! name (cadr arg)))
-               ((comment) (set! comment (cadr arg)))
-               ((attrs) (set! attrs (cdr arg)))
-               ((default-insn-word-bitsize)
-                (set! default-insn-word-bitsize (cadr arg)))
-               ((default-insn-bitsize) (set! default-insn-bitsize (cadr arg)))
-               ((base-insn-bitsize) (set! base-insn-bitsize (cadr arg)))
-               ((decode-assist) (set! decode-assist (cadr arg)))
-               ((liw-insns) (set! liw-insns (cadr arg)))
-               ((parallel-insns) (set! parallel-insns- (cadr arg)))
-               ((condition) (set! condition (cdr arg)))
-               ((setup-semantics) (set! setup-semantics (cadr arg)))
-               ((decode-splits) (set! decode-splits (cdr arg)))
-               ((insn-types) #t) ; ignore for now
-               ((frame) #t) ; ignore for now
-               (else (parse-error context "invalid isa arg" arg)))
-             (loop (cdr arg-list)))))
-      ; Now that we've identified the elements, build the object.
-      (-isa-parse context name comment attrs
-                 base-insn-bitsize
-                 (if default-insn-word-bitsize
-                     default-insn-word-bitsize
-                     base-insn-bitsize)
-                 (if default-insn-bitsize
-                     default-insn-bitsize
-                     base-insn-bitsize)
-                 decode-assist liw-insns parallel-insns- condition
-                 setup-semantics decode-splits)
-      )
-    )
+(define (-isa-read context . arg-list)
+  (let (
+       (name #f)
+       (attrs nil)
+       (comment "")
+       (base-insn-bitsize #f)
+       (default-insn-bitsize #f)
+       (default-insn-word-bitsize #f)
+       (decode-assist nil)
+       (liw-insns 1)
+       ;; FIXME: Hobbit computes the wrong symbol for `parallel-insns'
+       ;; in the `case' expression below because there is a local var
+       ;; of the same name ("__1" gets appended to the symbol name).
+       (parallel-insns- 1)
+       (condition nil)
+       (setup-semantics nil)
+       (decode-splits nil)
+       )
+
+    (let loop ((arg-list arg-list))
+      (if (null? arg-list)
+         nil
+         (let ((arg (car arg-list))
+               (elm-name (caar arg-list)))
+           (case elm-name
+             ((name) (set! name (cadr arg)))
+             ((comment) (set! comment (cadr arg)))
+             ((attrs) (set! attrs (cdr arg)))
+             ((default-insn-word-bitsize)
+              (set! default-insn-word-bitsize (cadr arg)))
+             ((default-insn-bitsize) (set! default-insn-bitsize (cadr arg)))
+             ((base-insn-bitsize) (set! base-insn-bitsize (cadr arg)))
+             ((decode-assist) (set! decode-assist (cadr arg)))
+             ((liw-insns) (set! liw-insns (cadr arg)))
+             ((parallel-insns) (set! parallel-insns- (cadr arg)))
+             ((condition) (set! condition (cdr arg)))
+             ((setup-semantics) (set! setup-semantics (cadr arg)))
+             ((decode-splits) (set! decode-splits (cdr arg)))
+             ((insn-types) #t) ; ignore for now
+             ((frame) #t) ; ignore for now
+             (else (parse-error context "invalid isa arg" arg)))
+           (loop (cdr arg-list)))))
+
+    ;; Now that we've identified the elements, build the object.
+    (-isa-parse context name comment attrs
+               base-insn-bitsize
+               (if default-insn-word-bitsize
+                   default-insn-word-bitsize
+                   base-insn-bitsize)
+               (if default-insn-bitsize
+                   default-insn-bitsize
+                   base-insn-bitsize)
+               decode-assist liw-insns parallel-insns- condition
+               setup-semantics decode-splits))
 )
 
 ; Define a <isa> object, name/value pair list version.
 
 (define define-isa
   (lambda arg-list
-    (let ((i (apply -isa-read arg-list)))
+    (let ((i (apply -isa-read (cons (make-current-context "define-isa")
+                                   arg-list))))
       (if i
          (current-isa-add! i))
       i))
 
 (define modify-isa
   (lambda arg-list
-    (let ((errtxt "modify-isa")
+    (let ((context (make-current-context "modify-isa"))
          (isa-spec (assq 'name arg-list)))
       (if (not isa-spec)
-         (parse-error errtxt "isa name not specified"))
+         (parse-error context "isa name not specified"))
 
-      (let ((isa (current-isa-lookup (arg-list-symbol-arg errtxt isa-spec))))
+      (let ((isa (current-isa-lookup (arg-list-symbol-arg context isa-spec))))
        (if (not isa)
-           (parse-error errtxt "undefined isa" isa-spec))
+           (parse-error context "undefined isa" isa-spec))
 
        (let loop ((args arg-list))
          (if (null? args)
                (case (car arg-spec)
                  ((name) #f) ; ignore, already processed
                  ((add-decode-split)
-                  (-isa-add-decode-split! errtxt isa (cdr arg-spec)))
+                  (-isa-add-decode-split! context isa (cdr arg-spec)))
                  (else
-                  (parse-error errtxt "invalid/unsupported option" (car arg-spec))))
+                  (parse-error context "invalid/unsupported option" (car arg-spec))))
                (loop (cdr args)))))))
 
     *UNSPECIFIED*)
 ; description in the .cpu file.
 ; All arguments are in raw (non-evaluated) form.
 
-(define (-cpu-parse name comment attrs
+(define (-cpu-parse context name comment attrs
                    endian insn-endian data-endian float-endian
                    word-bitsize insn-chunk-bitsize file-transform parallel-insns)
   (logit 2 "Processing cpu family " name " ...\n")
-  ; Pick out name first 'cus we need it as a string(/symbol).
-  (let* ((name (parse-name name "cpu"))
-        (errtxt (stringsym-append "cpu " name)))
+
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name)))
+
     (if (keep-cpu? name)
        (make <cpu>
              name
-             (parse-comment comment errtxt)
-             (atlist-parse attrs "cpu" errtxt)
+             (parse-comment context comment)
+             (atlist-parse context attrs "cpu")
              endian insn-endian data-endian float-endian
              word-bitsize
              insn-chunk-bitsize
 
 ; Read a cpu family description
 ; This is the main routine for analyzing a cpu description in the .cpu file.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
 ; -cpu-parse is invoked to create the <cpu> object.
 
-(define -cpu-read
-  (lambda arg-list
-    (let ((errtxt "cpu-read")
-         ; <cpu> object members and default values
-         (name nil)
-         (comment nil)
-         (attrs nil)
-         (endian #f)
-         (insn-endian #f)
-         (data-endian #f)
-         (float-endian #f)
-         (word-bitsize #f)
-         (insn-chunk-bitsize 0)
-         (file-transform "")
-         ; FIXME: Hobbit computes the wrong symbol for `parallel-insns'
-         ; in the `case' expression below because there is a local var
-         ; of the same name ("__1" gets appended to the symbol name).
-         (parallel-insns- #f)
-         )
-      ; Loop over each element in ARG-LIST, recording what's found.
-      (let loop ((arg-list arg-list))
-       (if (null? arg-list)
-           nil
-           (let ((arg (car arg-list))
-                 (elm-name (caar arg-list)))
-             (case elm-name
-               ((name) (set! name (cadr arg)))
-               ((comment) (set! comment (cadr arg)))
-               ((attrs) (set! attrs (cdr arg)))
-               ((endian) (set! endian (cadr arg)))
-               ((insn-endian) (set! insn-endian (cadr arg)))
-               ((data-endian) (set! data-endian (cadr arg)))
-               ((float-endian) (set! float-endian (cadr arg)))
-               ((word-bitsize) (set! word-bitsize (cadr arg)))
-               ((insn-chunk-bitsize) (set! insn-chunk-bitsize (cadr arg)))
-               ((file-transform) (set! file-transform (cadr arg)))
-               ((parallel-insns) (set! parallel-insns- (cadr arg)))
-               (else (parse-error errtxt "invalid cpu arg" arg)))
-             (loop (cdr arg-list)))))
-      ; Now that we've identified the elements, build the object.
-      (-cpu-parse name comment attrs
-                 endian insn-endian data-endian float-endian
-                 word-bitsize insn-chunk-bitsize file-transform parallel-insns-)
-      )
-    )
+(define (-cpu-read context . arg-list)
+  (let (
+       (name nil)
+       (comment nil)
+       (attrs nil)
+       (endian #f)
+       (insn-endian #f)
+       (data-endian #f)
+       (float-endian #f)
+       (word-bitsize #f)
+       (insn-chunk-bitsize 0)
+       (file-transform "")
+       ;; FIXME: Hobbit computes the wrong symbol for `parallel-insns'
+       ;; in the `case' expression below because there is a local var
+       ;; of the same name ("__1" gets appended to the symbol name).
+       (parallel-insns- #f)
+       )
+
+    ;; Loop over each element in ARG-LIST, recording what's found.
+    (let loop ((arg-list arg-list))
+      (if (null? arg-list)
+         nil
+         (let ((arg (car arg-list))
+               (elm-name (caar arg-list)))
+           (case elm-name
+             ((name) (set! name (cadr arg)))
+             ((comment) (set! comment (cadr arg)))
+             ((attrs) (set! attrs (cdr arg)))
+             ((endian) (set! endian (cadr arg)))
+             ((insn-endian) (set! insn-endian (cadr arg)))
+             ((data-endian) (set! data-endian (cadr arg)))
+             ((float-endian) (set! float-endian (cadr arg)))
+             ((word-bitsize) (set! word-bitsize (cadr arg)))
+             ((insn-chunk-bitsize) (set! insn-chunk-bitsize (cadr arg)))
+             ((file-transform) (set! file-transform (cadr arg)))
+             ((parallel-insns) (set! parallel-insns- (cadr arg)))
+             (else (parse-error context "invalid cpu arg" arg)))
+           (loop (cdr arg-list)))))
+
+    ;; Now that we've identified the elements, build the object.
+    (-cpu-parse context name comment attrs
+               endian insn-endian data-endian float-endian
+               word-bitsize insn-chunk-bitsize file-transform parallel-insns-))
 )
 
 ; Define a cpu family object, name/value pair list version.
 
 (define define-cpu
   (lambda arg-list
-    (let ((c (apply -cpu-read arg-list)))
+    (let ((c (apply -cpu-read (cons (make-current-context "define-cpu")
+                                   arg-list))))
       (if c
          (begin
            (current-cpu-add! c)
 (define (-mach-parse context name comment attrs cpu bfd-name isas)
   (logit 2 "Processing mach " name " ...\n")
 
-  (let ((name (parse-name name context)))
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name)))
+
     (if (not (list? isas))
        (parse-error context "isa spec not a list" isas))
     (let ((cpu-obj (current-cpu-lookup cpu))
          (parse-error context "unknown isa in" isas))
       (if (not (string? bfd-name))
          (parse-error context "bfd-name not a string" bfd-name))
+
       (if (keep-mach? (list name))
+
          (make <mach>
                name
-               (parse-comment comment context)
-               (atlist-parse attrs "mach" context)
+               (parse-comment context comment)
+               (atlist-parse context attrs "mach")
                cpu-obj
                bfd-name
                isa-list)
+
          (begin
            (logit 2 "Ignoring " name ".\n")
            #f)))) ; mach is not to be kept
 )
 
 ; Read a mach entry.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
 
-(define -mach-read
-  (lambda arg-list
-    (let ((context "mach-read")
-         (name nil)
-         (attrs nil)
-         (comment nil)
-         (cpu nil)
-         (bfd-name #f)
-         (isas #f)
-         )
-      (let loop ((arg-list arg-list))
-       (if (null? arg-list)
-           nil
-           (let ((arg (car arg-list))
-                 (elm-name (caar arg-list)))
-             (case elm-name
-               ((name) (set! name (cadr arg)))
-               ((comment) (set! comment (cadr arg)))
-               ((attrs) (set! attrs (cdr arg)))
-               ((cpu) (set! cpu (cadr arg)))
-               ((bfd-name) (set! bfd-name (cadr arg)))
-               ((isas) (set! isas (cdr arg)))
-               (else (parse-error context "invalid mach arg" arg)))
-             (loop (cdr arg-list)))))
-      ; Now that we've identified the elements, build the object.
-      (-mach-parse context name comment attrs cpu
-                  ; Default bfd-name is same as object's name.
-                  (if bfd-name bfd-name (symbol->string name))
-                  ; Default isa is the first one.
-                  (if isas isas (list (obj:name (car (current-isa-list))))))
-      )
-    )
+(define (-mach-read context . arg-list)
+  (let (
+       (name nil)
+       (attrs nil)
+       (comment nil)
+       (cpu nil)
+       (bfd-name #f)
+       (isas #f)
+       )
+
+    (let loop ((arg-list arg-list))
+      (if (null? arg-list)
+         nil
+         (let ((arg (car arg-list))
+               (elm-name (caar arg-list)))
+           (case elm-name
+             ((name) (set! name (cadr arg)))
+             ((comment) (set! comment (cadr arg)))
+             ((attrs) (set! attrs (cdr arg)))
+             ((cpu) (set! cpu (cadr arg)))
+             ((bfd-name) (set! bfd-name (cadr arg)))
+             ((isas) (set! isas (cdr arg)))
+             (else (parse-error context "invalid mach arg" arg)))
+           (loop (cdr arg-list)))))
+
+    ;; Now that we've identified the elements, build the object.
+    (-mach-parse context name comment attrs cpu
+                ;; Default bfd-name is same as object's name.
+                (if bfd-name bfd-name (symbol->string name))
+                ;; Default isa is the first one.
+                (if isas isas (list (obj:name (car (current-isa-list)))))))
 )
 
 ; Define a <mach> object, name/value pair list version.
 
 (define define-mach
   (lambda arg-list
-    (let ((m (apply -mach-read arg-list)))
+    (let ((m (apply -mach-read (cons (make-current-context "define-mach")
+                                    arg-list))))
       (if m
          (current-mach-add! m))
       m))
index 17ad60e..3244015 100644 (file)
 ; Parse a macro-insn expansion description.
 ; ??? At present we only support unconditional simple expansion.
 
-(define (-minsn-parse-expansion errtxt expn)
+(define (-minsn-parse-expansion context expn)
   (if (not (form? expn))
-      (parse-error errtxt "invalid macro expansion" expn))
+      (parse-error context "invalid macro expansion" expn))
   (if (not (eq? 'emit (car expn)))
-      (parse-error errtxt "invalid macro expansion, must be `(emit ...)'" expn))
+      (parse-error context "invalid macro expansion, must be `(emit ...)'" expn))
   expn
 )
 \f
 ; All arguments are in raw (non-evaluated) form.
 ; The result is the parsed object or #f if object isn't for selected mach(s).
 
-(define (-minsn-parse errtxt name comment attrs syntax expansions)
+(define (-minsn-parse context name comment attrs syntax expansions)
   (logit 2 "Processing macro-insn " name " ...\n")
 
   (if (not (list? expansions))
-      (parse-error errtxt "invalid macro expansion list" expansions))
+      (parse-error context "invalid macro expansion list" expansions))
 
-  (let ((name (parse-name name errtxt))
-       (atlist-obj (atlist-parse attrs "cgen_minsn" errtxt)))
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name))
+        (atlist-obj (atlist-parse context attrs "cgen_minsn")))
 
     (if (keep-atlist? atlist-obj #f)
 
        (let ((result (make <macro-insn>
                        name
-                       (parse-comment comment errtxt)
+                       (parse-comment context comment)
                        atlist-obj
-                       (parse-syntax syntax errtxt)
-                       (map (lambda (e) (-minsn-parse-expansion errtxt e))
+                       (parse-syntax context syntax)
+                       (map (lambda (e) (-minsn-parse-expansion context e))
                             expansions))))
          result)
 
 
 ; Read a macro-insn description
 ; This is the main routine for analyzing macro-insns in the .cpu file.
-; ERRTXT is prepended to error messages to provide context.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
 ; -minsn-parse is invoked to create the `macro-insn' object.
 
-(define (-minsn-read errtxt . arg-list)
-  (let (; Current macro-insn elements:
+(define (-minsn-read context . arg-list)
+  (let (
        (name nil)
        (comment "")
        (attrs nil)
        (syntax "")
        (expansions nil)
        )
+
     ; Loop over each element in ARG-LIST, recording what's found.
     (let loop ((arg-list arg-list))
       (if (null? arg-list)
              ((attrs) (set! attrs (cdr arg)))
              ((syntax) (set! syntax (cadr arg)))
              ((expansions) (set! expansions (cdr arg)))
-             (else (parse-error errtxt "invalid macro-insn arg" arg)))
+             (else (parse-error context "invalid macro-insn arg" arg)))
            (loop (cdr arg-list)))))
+
     ; Now that we've identified the elements, build the object.
-    (-minsn-parse errtxt name comment attrs syntax expansions)
-    )
+    (-minsn-parse context name comment attrs syntax expansions))
 )
 
 ; Define a macro-insn object, name/value pair list version.
   (lambda arg-list
     (if (eq? APPLICATION 'SIMULATOR)
        #f ; don't waste time if simulator
-       (let ((m (apply -minsn-read (cons "define-minsn" arg-list))))
+       (let ((m (apply -minsn-read (cons (make-current-context "define-minsn")
+                                         arg-list))))
          (if m
              (current-minsn-add! m))
          m)))
 (define (define-full-minsn name comment attrs syntax expansion)
   (if (eq? APPLICATION 'SIMULATOR)
       #f ; don't waste time if simulator
-      (let ((m (-minsn-parse "define-full-minsn" name comment
+      (let ((m (-minsn-parse (make-current-context "define-full-minsn")
+                            name comment
                             (cons 'ALIAS attrs)
                             syntax (list expansion))))
        (if m
 ; This involves making a copy of REAL-INSN's ifield list and assigning
 ; known quantities to operands that have fixed values in the macro-insn.
 
-(define (minsn-compute-iflds errtxt minsn-iflds real-insn)
+(define (-minsn-compute-iflds context minsn-iflds real-insn)
   (let* ((iflds (list-copy (insn-iflds real-insn)))
         ; List of "free variables", i.e. operands.
         (ifld-ops (find ifld-operand? iflds))
                       (ifld-pair (object-memq f-name iflds)))
                  ;(logit 3 "Processing ifield " f-name " ...\n")
                  (if (not ifld-pair)
-                     (parse-error errtxt "unknown operand" f))
+                     (parse-error context "unknown operand" f))
                  ; Ensure `f' is an operand.
                  (if (not (memq f-name ifld-names))
-                     (parse-error errtxt "not an operand" f))
+                     (parse-error context "not an operand" f))
                  (if (pair? f)
                      (set-car! ifld-pair (ifld-new-value (car ifld-pair) (cadr f))))
                  (delq! f-name ifld-names)))
              minsn-iflds)
     (if (not (equal? ifld-names '(#f)))
-       (parse-error errtxt "incomplete operand list, missing: " (cdr ifld-names)))
+       (parse-error context "incomplete operand list, missing: " (cdr ifld-names)))
     iflds)
 )
 
 ; Create an aliased real insn from an alias macro-insn.
 
-(define (minsn-make-alias errtxt minsn)
+(define (minsn-make-alias context minsn)
   (if (or (not (has-attr? minsn 'ALIAS))
          ; Must emit exactly one real insn.
          (not (eq? 'emit (caar (minsn-expansions minsn)))))
-      (parse-error errtxt "not an alias macro-insn" minsn))
+      (parse-error context "not an alias macro-insn" minsn))
 
   (let* ((expn (car (minsn-expansions minsn)))
         (alias-of (current-insn-lookup (cadr expn))))
 
     (if (not alias-of)
-       (parse-error errtxt "unknown real insn in expansion" minsn))
+       (parse-error context "unknown real insn in expansion" minsn))
 
     (let ((i (make <insn>
                   (obj:name minsn)
                   (obj:comment minsn)
                   (obj-atlist minsn)
                   (minsn-syntax minsn)
-                  (minsn-compute-iflds (string-append errtxt
-                                                      ": " (obj:str-name minsn))
-                                       (cddr expn) alias-of)
+                  (-minsn-compute-iflds (context-append context
+                                                        (string-append ": " (obj:str-name minsn)))
+                                        (cddr expn) alias-of)
                   #f ; ifield-assertion
                   #f ; semantics
                   #f ; timing
index ee15dc5..b39c0e9 100644 (file)
 ; This is the main routine for building a mode object.
 ; All arguments are in raw (non-evaluated) form.
 
-(define (-mode-parse errtxt name comment attrs class bits bytes
-                   non-mode-c-type printf-type sem-mode ptr-to host?)
+(define (-mode-parse context name comment attrs class bits bytes
+                    non-mode-c-type printf-type sem-mode ptr-to host?)
   (logit 2 "Processing mode " name " ...\n")
-  (let* ((name (parse-name name errtxt))
-        (errtxt (stringsym-append errtxt " " name))
-        (result (make <mode>
-                      name
-                      (parse-comment comment errtxt)
-                      (atlist-parse attrs "mode" errtxt)
-                      class bits bytes non-mode-c-type printf-type
-                      sem-mode ptr-to host?)))
-    result)
+
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name)))
+
+    (make <mode>
+      name
+      (parse-comment context comment)
+      (atlist-parse context attrs "mode")
+      class bits bytes non-mode-c-type printf-type
+      sem-mode ptr-to host?))
 )
 
 ; ??? At present there is no define-mode that takes an associative list
 
 (define (define-full-mode name comment attrs class bits bytes
          non-mode-c-type printf-type sem-mode ptr-to host?)
-  (let ((m (-mode-parse "define-full-mode" name comment attrs
+  (let ((m (-mode-parse (make-current-context "define-full-mode")
+                       name comment attrs
                        class bits bytes
                        non-mode-c-type printf-type sem-mode ptr-to host?)))
     ; Add it to the list of insn modes.
 )
 
 ; Parse MODE-NAME and return the mode object.
+; CONTEXT is a <context> object for error messages.
 ; An error is signalled if MODE isn't valid.
 
-(define (parse-mode-name mode-name errtxt)
+(define (parse-mode-name context mode-name)
   (let ((m (mode:lookup mode-name)))
-    (if (not m) (parse-error errtxt "not a valid mode" mode-name))
+    (if (not m)
+       (parse-error context "not a valid mode" mode-name))
     m)
 )
 
index c1712cb..c6512c4 100644 (file)
 \f
 ; Parse a `prefetch' spec.
 
-(define (-prefetch-parse errtxt expr)
+(define (-prefetch-parse context expr)
   nil
 )
 
 ; Parse a `retire' spec.
 
-(define (-retire-parse errtxt expr)
+(define (-retire-parse context expr)
   nil
 )
 
 ; ??? Perhaps we should also use name/value pairs here, but that's an
 ; unnecessary complication at this point in time.
 
-(define (-pipeline-parse errtxt model-name spec) ; name comments attrs elements)
+(define (-pipeline-parse context model-name spec) ; name comments attrs elements)
   (if (not (= (length spec) 4))
-      (parse-error errtxt "pipeline spec not `name comment attrs elements'" spec))
+      (parse-error context "pipeline spec not `name comment attrs elements'" spec))
   (apply make (cons <pipeline> spec))
 )
 
 ; ??? Perhaps we should also use name/value pairs here, but that's an
 ; unnecessary complication at this point in time.
 
-(define (-unit-parse errtxt model-name spec) ; name comments attrs elements)
+(define (-unit-parse context model-name spec) ; name comments attrs elements)
   (if (not (= (length spec) 9))
-      (parse-error errtxt "unit spec not `name comment attrs issue done state inputs outputs profile'" spec))
+      (parse-error context "unit spec not `name comment attrs issue done state inputs outputs profile'" spec))
   (apply make (append (cons <unit> spec) (list model-name)))
 )
 \f
 ; description in the .cpu file.
 ; All arguments are in raw (non-evaluated) form.
 
-(define (-model-parse errtxt name comment attrs mach-name prefetch retire pipelines state units)
+(define (-model-parse context name comment attrs mach-name prefetch retire pipelines state units)
   (logit 2 "Processing model " name " ...\n")
-  (let ((name (parse-name name errtxt))
-       ; FIXME: switch to `context' like in cver.
-       (errtxt (stringsym-append errtxt " " name))
-       (mach (current-mach-lookup mach-name)))
+
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name))
+        (mach (current-mach-lookup mach-name)))
+
     (if (null? units)
-       (parse-error errtxt "there must be at least one function unit" name))
+       (parse-error context "there must be at least one function unit" name))
+
     (if mach ; is `mach' being "kept"?
        (let ((model-obj
               (make <model>
                     name
-                    (parse-comment comment errtxt)
-                    (atlist-parse attrs "cpu" errtxt)
+                    (parse-comment context comment)
+                    (atlist-parse context attrs "cpu")
                     mach
-                    (-prefetch-parse errtxt prefetch)
-                    (-retire-parse errtxt retire)
-                    (map (lambda (p) (-pipeline-parse errtxt name p)) pipelines)
+                    (-prefetch-parse context prefetch)
+                    (-retire-parse context retire)
+                    (map (lambda (p) (-pipeline-parse context name p)) pipelines)
                     state
-                    (map (lambda (u) (-unit-parse errtxt name u)) units))))
+                    (map (lambda (u) (-unit-parse context name u)) units))))
          model-obj)
+
        (begin
          ; MACH wasn't found, ignore this model.
          (logit 2 "Nonexistant mach " mach-name ", ignoring " name ".\n")
 
 ; Read a model description.
 ; This is the main routine for analyzing models in the .cpu file.
-; ERRTXT is prepended to error messages to provide context.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
 ; -model-parse is invoked to create the `model' object.
 
-(define (-model-read errtxt . arg-list)
-  (let (; Current mach elements:
+(define (-model-read context . arg-list)
+  (let (
        (name nil)      ; name of model
        (comment nil)   ; description of model
        (attrs nil)     ; attributes
        (state nil)     ; list of (name mode) pairs to record state
        (units nil)     ; list of function units
        )
+
     (let loop ((arg-list arg-list))
       (if (null? arg-list)
          nil
              ((pipeline) (set! pipelines (cons (cdr arg) pipelines)))
              ((state) (set! state (cdr arg)))
              ((unit) (set! units (cons (cdr arg) units)))
-             (else (parse-error errtxt "invalid model arg" arg)))
+             (else (parse-error context "invalid model arg" arg)))
            (loop (cdr arg-list)))))
+
     ; Now that we've identified the elements, build the object.
-    (-model-parse errtxt name comment attrs mach prefetch retire pipelines state units)
-    )
+    (-model-parse context name comment attrs mach prefetch retire pipelines state units))
 )
 
 ; Define a cpu model object, name/value pair list version.
 
 (define define-model
   (lambda arg-list
-    (let ((m (apply -model-read (cons "define-model" arg-list))))
+    (let ((m (apply -model-read (cons (make-current-context "define-model")
+                                     arg-list))))
       (if m
          (current-model-add! m))
       m))
 ; are returned as (model1), i.e. an empty unit list.
 
 (define (parse-insn-timing context insn-timing-desc)
-  (logit 3 "  parse-insn-timing: context= " context ", desc= " insn-timing-desc "\n")
+  (logit 3 "  parse-insn-timing: context= " (context-prefix context)
+        ", desc= " insn-timing-desc "\n")
   (map (lambda (model-timing-desc)
         (let* ((model-name (car model-timing-desc))
                (model (current-model-lookup model-name)))
index f652f35..d5758f0 100644 (file)
 ; Values >= 128 are 128 + the index into the operand table.
 
 (define (compute-syntax strip-mnemonic? strip-mnem-operands? syntax op-macro)
-  (let ((context "syntax computation")
+  (let ((context (make-prefix-context "syntax computation"))
        (syntax (if strip-mnemonic?
                    (strip-mnemonic strip-mnem-operands? syntax)
                    syntax)))
@@ -548,7 +548,8 @@ static unsigned int dis_hash_insn (const char *, CGEN_INSN_INT);
   (logit 2 "Generating macro-instruction table ...\n")
   (let* ((minsn-list (map (lambda (minsn)
                            (if (has-attr? minsn 'ALIAS)
-                               (minsn-make-alias "gen-macro-insn-table" minsn)
+                               (minsn-make-alias (make-prefix-context "gen-macro-insn-table")
+                                                 minsn)
                                minsn))
                          (current-minsn-list)))
         (all-attrs (current-insn-attr-list))
index d56ffce..56345ff 100644 (file)
  <pc> 'make!
  (lambda (self)
    (send-next self 'make! 'pc "program counter"
-             (atlist-parse '(SEM-ONLY) "cgen_operand" "make! of pc")
+             (atlist-parse (make-prefix-context "make! of pc")
+                           '(SEM-ONLY) "cgen_operand")
              'h-pc
              'DFLT
              (make <hw-index> 'anonymous
                (!= (length getter) 2)
                (not (and (list? (car getter))
                          (= (length (car getter)) rank))))
-           (context-error context
-                          (string-append "invalid getter, should be "
-                                         (-operand-g/setter-syntax rank #f))
-                          getter))
+           (parse-error context
+                        (string-append "invalid getter, should be "
+                                       (-operand-g/setter-syntax rank #f))
+                        getter))
        (if (not (rtx? (cadr getter)))
-           (context-error context "invalid rtx expression" getter))
+           (parse-error context "invalid rtx expression" getter))
        getter))
 )
 
                (!= (length setter) 2)
                (not (and (list? (car setter))
                          (= (+ 1 (length (car setter)) rank)))))
-           (context-error context
-                          (string-append "invalid setter, should be "
-                                         (-operand-g/setter-syntax rank #t))
-                          setter))
+           (parse-error context
+                        (string-append "invalid setter, should be "
+                                       (-operand-g/setter-syntax rank #t))
+                        setter))
        (if (not (rtx? (cadr setter)))
-           (context-error context "invalid rtx expression" setter))
+           (parse-error context "invalid rtx expression" setter))
        setter))
 )
 
 ; ??? This only takes insn fields as the index.  May need another proc (or an
 ; enhancement of this one) that takes other kinds of indices.
 
-(define (-operand-parse errtxt name comment attrs hw mode ifld handlers getter setter)
+(define (-operand-parse context name comment attrs hw mode ifld handlers getter setter)
   (logit 2 "Processing operand " name " ...\n")
 
-  (let ((name (parse-name name errtxt))
-       (atlist-obj (atlist-parse attrs "cgen_operand" errtxt)))
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name))
+        (atlist-obj (atlist-parse context attrs "cgen_operand")))
 
     (if (keep-atlist? atlist-obj #f)
 
        (let ((hw-objs (current-hw-sem-lookup hw))
-             (mode-obj (parse-mode-name mode errtxt))
+             (mode-obj (parse-mode-name context mode))
              (ifld-val (if (integer? ifld)
                            ifld
-                           (current-ifld-lookup ifld)))
-             ; FIXME: quick hack
-             (context (context-make-reader errtxt)))
+                           (current-ifld-lookup ifld))))
 
          (if (not mode-obj)
-             (parse-error errtxt "unknown mode" mode))
+             (parse-error context "unknown mode" mode))
          (if (not ifld-val)
-             (parse-error errtxt "unknown insn field" ifld))
+             (parse-error context "unknown insn field" ifld))
          ; Disallow some obviously invalid numeric indices.
          (if (and (integer? ifld-val)
                   (< ifld-val 0))
-             (parse-error errtxt "invalid integer index" ifld-val))
+             (parse-error context "invalid integer index" ifld-val))
          ; Don't validate HW until we know whether this operand will be kept
          ; or not.  If not, HW may have been discarded too.
          (if (null? hw-objs)
-             (parse-error errtxt "unknown hardware element" hw))
+             (parse-error context "unknown hardware element" hw))
 
          ; At this point IFLD-VAL is either an integer or an <ifield> object.
          ; Since we can't look up the hardware element at this time
                                'ifield 'UINT ifld-val)))))
            (make <operand>
              name
-             (parse-comment comment errtxt)
+             (parse-comment context comment)
              ; Copy FLD's attributes so one needn't duplicate attrs like
              ; PCREL-ADDR, etc.  An operand inherits the attributes of
              ; its field.  They are overridable of course, which is why we use
              hw   ; note that this is the hw's name, not an object
              mode ; ditto, this is a name, not an object
              hw-index
-             (parse-handlers errtxt '(parse print) handlers)
+             (parse-handlers context '(parse print) handlers)
              (-operand-parse-getter context getter (if scalar? 0 1))
              (-operand-parse-setter context setter (if scalar? 0 1))
              )))
 
 ; Read an operand description.
 ; This is the main routine for analyzing operands in the .cpu file.
-; ERRTXT is prepended to error messages to provide context.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
 ; -operand-parse is invoked to create the <operand> object.
 
-(define (-operand-read errtxt . arg-list)
-  (let (; Current operand elements:
+(define (-operand-read context . arg-list)
+  (let (
        (name nil)
        (comment nil)
        (attrs nil)
        (getter nil)
        (setter nil)
        )
+
     (let loop ((arg-list arg-list))
       (if (null? arg-list)
          nil
              ((handlers) (set! handlers (cdr arg)))
              ((getter) (set! getter (cdr arg)))
              ((setter) (set! setter (cdr arg)))
-             (else (parse-error errtxt "invalid operand arg" arg)))
+             (else (parse-error context "invalid operand arg" arg)))
            (loop (cdr arg-list)))))
+
     ; Now that we've identified the elements, build the object.
-    (-operand-parse errtxt name comment attrs type mode index handlers
-                   getter setter)
-    )
+    (-operand-parse context name comment attrs type mode index handlers
+                   getter setter))
 )
 
 ; Define an operand object, name/value pair list version.
 
 (define define-operand
   (lambda arg-list
-    (let ((op (apply -operand-read (cons "define-operand" arg-list))))
+    (let ((op (apply -operand-read (cons (make-current-context "define-operand")
+                                        arg-list))))
       (if op
          (current-op-add! op))
       op))
 ; Define an operand object, all arguments specified.
 
 (define (define-full-operand name comment attrs type mode index handlers getter setter)
-  (let ((op (-operand-parse "define-full-operand" name comment attrs
+  (let ((op (-operand-parse (make-current-context "define-full-operand")
+                           name comment attrs
                            type mode index handlers getter setter)))
     (if op
        (current-op-add! op))
 (define (-derived-parse-encoding context operand-name encoding)
   (if (or (null? encoding)
          (not (list? encoding)))
-      (context-error context "encoding not a list" encoding))
+      (parse-error context "encoding not a list" encoding))
   (if (not (eq? (car encoding) '+))
-      (context-error context "encoding must begin with `+'" encoding))
+      (parse-error context "encoding must begin with `+'" encoding))
 
   ; ??? Calling -parse-insn-format is a quick hack.
   ; It's an internal routine of some other file.
-  (let ((iflds (-parse-insn-format "anyof encoding" encoding)))
+  (let ((iflds (-parse-insn-format context encoding)))
     (make <derived-ifield>
          operand-name
          'derived-ifield ; (string-append "<derived-ifield> for " operand-name)
 ; ??? Currently no support for handlers(,???) found in normal operands.
 ; Later, when necessary.
 
-(define (-derived-operand-parse errtxt name comment attrs mode
+(define (-derived-operand-parse context name comment attrs mode
                                args syntax
                                base-ifield encoding ifield-assertion
                                getter setter)
   (logit 2 "Processing derived operand " name " ...\n")
 
-  (let ((name (parse-name name errtxt))
-       (atlist-obj (atlist-parse attrs "cgen_operand" errtxt)))
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name))
+        (atlist-obj (atlist-parse context attrs "cgen_operand")))
 
     (if (keep-atlist? atlist-obj #f)
 
-       (let* ((mode-obj (parse-mode-name mode errtxt))
-             ; FIXME: quick hack
-             (context (context-make-reader errtxt))
-             (parsed-encoding (-derived-parse-encoding context name encoding))
-             )
+       (let ((mode-obj (parse-mode-name context mode))
+             (parsed-encoding (-derived-parse-encoding context name encoding)))
+
          (if (not mode-obj)
-             (parse-error errtxt "unknown mode" mode))
+             (parse-error context "unknown mode" mode))
 
          (let ((result
                 (make <derived-operand>
                       name
-                      (parse-comment comment errtxt)
+                      (parse-comment context comment)
                       atlist-obj
                       mode-obj
                       (map (lambda (a)
                              (if (not (symbol? a))
-                                 (parse-error errtxt "arg not a symbol" a))
+                                 (parse-error context "arg not a symbol" a))
                              (let ((op (current-op-lookup a)))
                                (if (not op)
-                                   (parse-error errtxt "not an operand" a))
+                                   (parse-error context "not an operand" a))
                                op))
                            args)
                       syntax
 
 ; Read a derived operand description.
 ; This is the main routine for analyzing derived operands in the .cpu file.
-; ERRTXT is prepended to error messages to provide context.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
 ; -derived-operand-parse is invoked to create the <derived-operand> object.
 
-(define (-derived-operand-read errtxt . arg-list)
-  (let (; Current derived-operand elements:
+(define (-derived-operand-read context . arg-list)
+  (let (
        (name nil)
        (comment nil)
        (attrs nil)
        (getter nil)
        (setter nil)
        )
+
     (let loop ((arg-list arg-list))
       (if (null? arg-list)
          nil
              ((ifield-assertion) (set! ifield-assertion (cadr arg)))
              ((getter) (set! getter (cadr arg)))
              ((setter) (set! setter (cadr arg)))
-             (else (parse-error errtxt "invalid derived-operand arg" arg)))
+             (else (parse-error context "invalid derived-operand arg" arg)))
            (loop (cdr arg-list)))))
+
     ; Now that we've identified the elements, build the object.
-    (-derived-operand-parse errtxt name comment attrs mode args
+    (-derived-operand-parse context name comment attrs mode args
                            syntax base-ifield encoding ifield-assertion
-                           getter setter)
-    )
+                           getter setter))
 )
 
 ; Define a derived operand object, name/value pair list version.
 (define define-derived-operand
   (lambda arg-list
     (let ((op (apply -derived-operand-read
-                    (cons "define-derived-operand" arg-list))))
+                    (cons (make-current-context "define-derived-operand")
+                          arg-list))))
       (if op
          (current-op-add! op))
       op))
 ; ??? Not supported (yet).
 ;
 ;(define (define-full-derived-operand name comment attrs mode ...)
-;  (let ((op (-derived-operand-parse "define-full-derived-operand"
+;  (let ((op (-derived-operand-parse (make-current-context "define-full-derived-operand")
 ;                                  name comment attrs
 ;                                  mode ...)))
 ;    (if op
 
 (define (-anyof-parse-choice context choice)
   (if (not (symbol? choice))
-      (context-error context "anyof choice not a symbol" choice))
+      (parse-error context "anyof choice not a symbol" choice))
   (let ((op (current-op-lookup choice)))
     (if (not (derived-operand? op))
-       (context-error context "anyof choice not a derived-operand" choice))
+       (parse-error context "anyof choice not a derived-operand" choice))
     op)
 )
 
 ; ??? Currently no support for handlers(,???) found in normal operands.
 ; Later, when necessary.
 
-(define (-anyof-operand-parse errtxt name comment attrs mode
+(define (-anyof-operand-parse context name comment attrs mode
                              base-ifield choices)
   (logit 2 "Processing anyof operand " name " ...\n")
 
-  (let ((name (parse-name name errtxt))
-       (atlist-obj (atlist-parse attrs "cgen_operand" errtxt)))
+  ;; Pick out name first to augment the error context.
+  (let* ((name (parse-name context name))
+        (context (context-append-name context name))
+        (atlist-obj (atlist-parse context attrs "cgen_operand")))
 
     (if (keep-atlist? atlist-obj #f)
 
-       (let ((mode-obj (parse-mode-name mode errtxt))
-             ; FIXME: quick hack
-             (context (context-make-reader errtxt)))
+       (let ((mode-obj (parse-mode-name context mode)))
          (if (not mode-obj)
-             (parse-error errtxt "unknown mode" mode))
+             (parse-error context "unknown mode" mode))
 
          (make <anyof-operand>
                name
-               (parse-comment comment errtxt)
+               (parse-comment context comment)
                atlist-obj
                mode
                base-ifield
 
 ; Read an anyof operand description.
 ; This is the main routine for analyzing anyof operands in the .cpu file.
-; ERRTXT is prepended to error messages to provide context.
+; CONTEXT is a <context> object for error messages.
 ; ARG-LIST is an associative list of field name and field value.
 ; -anyof-operand-parse is invoked to create the <anyof-operand> object.
 
-(define (-anyof-operand-read errtxt . arg-list)
-  (let (; Current operand elements:
+(define (-anyof-operand-read context . arg-list)
+  (let (
        (name nil)
        (comment nil)
        (attrs nil)
        (base-ifield nil)
        (choices nil)
        )
+
     (let loop ((arg-list arg-list))
       (if (null? arg-list)
          nil
              ((mode) (set! mode (cadr arg)))
              ((base-ifield) (set! base-ifield (cadr arg)))
              ((choices) (set! choices (cdr arg)))
-             (else (parse-error errtxt "invalid anyof-operand arg" arg)))
+             (else (parse-error context "invalid anyof-operand arg" arg)))
            (loop (cdr arg-list)))))
+
     ; Now that we've identified the elements, build the object.
-    (-anyof-operand-parse errtxt name comment attrs mode base-ifield choices)
-    )
+    (-anyof-operand-parse context name comment attrs mode base-ifield choices))
 )
 
 ; Define an anyof operand object, name/value pair list version.
 (define define-anyof-operand
   (lambda arg-list
     (let ((op (apply -anyof-operand-read
-                    (cons "define-anyof-operand" arg-list))))
+                    (cons (make-current-context "define-anyof-operand")
+                          arg-list))))
       (if op
          (current-op-add! op))
       op))
index 5890e0a..1311f97 100644 (file)
                        ":")))
 )
 
-; Signal an error while reading a .cpu file.
-
-(define (reader-error msg expr help-text)
-  (let* ((loc (current-reader-location))
+;;; Signal a parse error while reading a .cpu file.
+;;; If CONTEXT is #f, use a default context of the current reader location
+;;; and an empty prefix.
+;;; If MAYBE-HELP-TEXT is specified, elide the last trailing \n.
+;;; Multiple lines of help text need embedded newlines, and should be no longer
+;;; than 79 characters.
+
+(define (parse-error context message expr . maybe-help-text)
+  (if (not context)
+      (set! context (make <context> (current-reader-location) #f)))
+  (let* ((loc (context-location context))
         (top-sloc (location-top loc))
-        (errmsg
-         (string-append (single-location->string top-sloc)
-                        ": "
-                        msg
-                        ":\n"
-                        (if (string=? help-text "")
-                            ""
-                            (string-append help-text "\n")))))
-    (error (simple-format #f "While reading description:\n~A ~A\nReference chain:\n~A"
-                         errmsg expr (location->string loc))))
-)
-
-; Signal a parse error while reading a .cpu file.
-; FIXME: Add expr arg and change args to optional help text.
-
-(define (parse-error errtxt message . args)
-  (cond ((null? args)
-        (reader-error (string-append errtxt ": " message ":") "" ""))
-       ((= (length args) 1)
-        (reader-error (string-append errtxt ": " message ":") (car args) ""))
-       (else
-        (reader-error (string-append errtxt ": " message ":") args "")))
+        (prefix (context-prefix context)))
+    (error
+     (simple-format
+      #f
+      "While reading description:\n~A: ~A:\n  ~S\nReference chain:\n~A~A"
+      (single-location->simple-string top-sloc)
+      (if prefix
+         (string-append prefix ": " message)
+         message)
+      expr
+      (location->string loc)
+      (if (null? maybe-help-text)
+         ""
+         (string-append "\n" (car maybe-help-text))))))
 )
 
 ; Return the current source location.
 ; Process a macro-expanded entry.
 
 (define (-reader-process-expanded-1! entry)
-  ;; Set the current source location for better diagnostics.
-  ;; Access with current-reader-location.
-  (reader-set-location! CURRENT-READER (location-property entry))
+  (let ((location (location-property entry)))
+
+    ;; Set the current source location for better diagnostics.
+    ;; Access with current-reader-location.
+    (reader-set-location! CURRENT-READER location)
 
-  (if (reader-trace-commands? CURRENT-READER)
-      (let ((loc (location-property entry)))
+    (if (reader-trace-commands? CURRENT-READER)
        (message "Processing command:\n  @ "
-                (if loc (location->string loc) "location unknown")
+                (if location (location->string location) "location unknown")
                 "\n"
-                (with-output-to-string (lambda () (pretty-print entry))))))
-
-  (let ((command (-reader-lookup-command (car entry))))
-    (if command
-       (let* ((handler (command-handler command))
-              (arg-spec (command-arg-spec command))
-              (num-args (num-args arg-spec)))
-         (if (cdr num-args)
-             ; Variable number of trailing arguments.
-             (if (< (length (cdr entry)) (car num-args))
-                 (reader-error (string-append "Incorrect number of arguments to "
-                                              (symbol->string (car entry))
-                                              ", expecting at least "
-                                              (number->string (car num-args)))
-                               entry
-                               (command-help command))
-                 (apply handler (cdr entry)))
-             ; Fixed number of arguments.
-             (if (!= (length (cdr entry)) (car num-args))
-                 (reader-error (string-append "Incorrect number of arguments to "
-                                              (symbol->string (car entry))
-                                              ", expecting "
-                                              (number->string (car num-args)))
-                               entry
-                               (command-help command))
-                 (apply handler (cdr entry)))))
-       (reader-error "unknown entry type" entry "")))
+                (with-output-to-string (lambda () (pretty-print entry)))))
+
+    (let ((command (-reader-lookup-command (car entry)))
+         (context (make-current-context #f)))
+
+      (if command
+
+         (let* ((handler (command-handler command))
+                (arg-spec (command-arg-spec command))
+                (num-args (num-args arg-spec)))
+           (if (cdr num-args)
+               ;; Variable number of trailing arguments.
+               (if (< (length (cdr entry)) (car num-args))
+                   (parse-error context
+                                (string-append "Incorrect number of arguments to "
+                                               (symbol->string (car entry))
+                                               ", expecting at least "
+                                               (number->string (car num-args)))
+                                entry
+                                (command-help command))
+                   (apply handler (cdr entry)))
+               ;; Fixed number of arguments.
+               (if (!= (length (cdr entry)) (car num-args))
+                   (parse-error context
+                                (string-append "Incorrect number of arguments to "
+                                               (symbol->string (car entry))
+                                               ", expecting "
+                                               (number->string (car num-args)))
+                                entry
+                                (command-help command))
+                   (apply handler (cdr entry)))))
+
+         (parse-error context "unknown entry type" entry))))
 
   *UNSPECIFIED*
 )
 
 (define (-reader-process! entry loc)
   (if (not (form? entry))
-      (reader-error "improperly formed entry" entry ""))
+      (parse-error loc "improperly formed entry" entry))
 
   ; First do macro expansion, but not if define-pmacro of course.
   ; ??? Singling out define-pmacro this way seems a bit odd.  The way to look
@@ -918,13 +924,15 @@ Define a preprocessor-style macro.
 
 (define (-cmd-if test then . else)
   (if (> (length else) 1)
-      (reader-error "wrong number of arguments to `if'"
-                   (cons 'if (cons test (cons then else)))
-                   ""))
-  ; FIXME: Assumes TEST is a non-null-list.
+      (parse-error #f
+                  "wrong number of arguments to `if'"
+                  (cons 'if (cons test (cons then else)))))
   ; ??? rtx-eval test
-  (if (not (memq (car test) '(keep-isa? keep-mach? application-is?)))
-      (reader-error "only (if (keep-mach?|keep-isa?|application-is? ...) ...) are currently supported" test ""))
+  (if (or (not (pair? test))
+         (not (memq (car test) '(keep-isa? keep-mach? application-is?))))
+      (parse-error #f
+                  "only (if (keep-mach?|keep-isa?|application-is? ...) ...) are currently supported"
+                  test))
   (case (car test)
     ((keep-isa?)
      (if (keep-isa? (cadr test))
@@ -1053,7 +1061,9 @@ Define a preprocessor-style macro.
 (define (option-arg args)
   (if (and (pair? args) (pair? (cdr args)))
       (cadr args)
-      (parse-error "option processing" "missing argument to" (car args)))
+      (parse-error (make-prefix-context "option processing")
+                  "missing argument to"
+                  (car args)))
 )
 
 ; List of common arguments.
index b9c2bc4..23a35bd 100644 (file)
                        (string-upcase (gen-c-symbol val))) ; yes, upcase
                       ((string? val) val)
                       (else
-                       (parse-error "case:" "bad case" val)))
+                       (parse-error (make-prefix-context "case:")
+                                    "bad case" val)))
                 " : ")
 )
 
index 0189120..41155bf 100644 (file)
 ; Cover-fn to context-error for signalling an error during rtx traversal.
 
 (define (-rtx-traverse-error tstate errmsg expr op-num)
-;  (parse-error context (string-append errmsg ", operand number "
-;                                    (number->string op-num))
-;             (rtx-dump expr))
+;  (parse-error (tstate-context context)
+;               (string-append errmsg ", operand number "
+;                              (number->string op-num))
+;               (rtx-dump expr))
   (context-error (tstate-context tstate)
                 (string-append errmsg ", operand #" (number->string op-num))
                 (rtx-strdump expr))
 )
 
 (define (-rtx-traverse-attrs val mode expr op-num tstate appstuff)
-;  (cons val ; (atlist-source-form (atlist-parse val "" "with-attr"))
+;  (cons val ; (atlist-source-form (atlist-parse (make-prefix-context "with-attr") val ""))
 ;      tstate)
   #f
 )
index bdc06b2..302d5d1 100644 (file)
 (define (hw estate mode-name hw-name index-arg selector)
   ; Enforce some rules to keep things in line with the current design.
   (if (not (symbol? mode-name))
-      (parse-error "hw" "invalid mode name" mode-name))
+      (parse-error (estate-context estate) "invalid mode name" mode-name))
   (if (not (symbol? hw-name))
-      (parse-error "hw" "invalid hw name" hw-name))
+      (parse-error (estate-context estate) "invalid hw name" hw-name))
   (if (not (or (number? index-arg)
               (rtx? index-arg)))
-      (parse-error "hw" "invalid index" index-arg))
+      (parse-error (estate-context estate) "invalid index" index-arg))
   (if (not (or (number? selector)
               (rtx? selector)))
-      (parse-error "hw" "invalid selector" selector))
+      (parse-error (estate-context estate) "invalid selector" selector))
 
   (let ((hw (current-hw-sem-lookup-1 hw-name)))
     (if (not hw)
-       (parse-error "hw" "invalid hardware element" hw-name))
+       (parse-error (estate-context estate) "invalid hardware element" hw-name))
 
     (let* ((mode (if (eq? mode-name 'DFLT) (hw-mode hw) (mode:lookup mode-name)))
           (hw-name-with-mode (symbol-append hw-name '- (obj:name mode)))
           (result (new <operand>))) ; ??? lookup-for-new?
 
       (if (not mode)
-         (parse-error "hw" "invalid mode" mode-name))
+         (parse-error (estate-context estate) "invalid mode" mode-name))
 
       ; Record the selector.
       (elm-xset! result 'selector selector)
                                  (rtx-constant-value index-arg))
                            (make <hw-index> 'anonymous 'rtx DFLT
                                  (-rtx-closure-make estate index-arg))))
-                      (else (parse-error "hw" "invalid index" index-arg))))
+                      (else (parse-error (estate-context estate)
+                                         "invalid index" index-arg))))
 
       (if (not (hw-mode-ok? hw (obj:name mode) (elm-xget result 'index)))
-         (parse-error "hw" "invalid mode for hardware" mode-name))
+         (parse-error (estate-context estate)
+                      "invalid mode for hardware" mode-name))
 
       (elm-xset! result 'hw-name hw-name)
       (elm-xset! result 'type hw)
 ; Subroutines.
 ; ??? Not sure this should live here.
 
-(define (-subr-read errtxt . arg-list)
+(define (-subr-read context . arg-list)
   #f
 )
 
index 42abf92..4399434 100644 (file)
                      (make <sfrag>
                        'x-header
                        "header fragment for insns without one"
-                       (atlist-parse '(VIRTUAL) "" "semantic frag computation")
+                       (atlist-parse (make-prefix-context "semantic frag computation")
+                                     '(VIRTUAL) "")
                        nil ; users
                        nil ; user ordinals
                        (insn-sfmt (current-insn-lookup 'x-before))
                      (make <sfrag>
                        'x-trailer
                        "trailer fragment for insns without one"
-                       (atlist-parse '(VIRTUAL) "" "semantic frag computation")
+                       (atlist-parse (make-prefix-context "semantic frag computation")
+                                     '(VIRTUAL) "")
                        nil ; users
                        nil ; user ordinals
                        (insn-sfmt (current-insn-lookup 'x-before))
index da127d3..94fcbb9 100644 (file)
                (append! op-list (list try))
                (cadr try))))
 
-       (parse-error "FIXME" "unknown reg" expr)))
+       (parse-error (tstate-context tstate) "unknown reg" expr)))
 )
 
 ; Subroutine of semantic-compile:process-expr!, to simplify it.
        (indx-sel (rtx-mem-index-sel expr)))
 
     (if (memq mode '(DFLT VOID))
-       (parse-error "FIXME" "memory must have explicit mode" expr))
+       (parse-error (tstate-context tstate)
+                    "memory must have explicit mode" expr))
 
     (let* ((try (list 'mem #f mode 'h-memory indx-sel))
           (existing-op (-rtx-find-op try op-list)))
         (f (current-ifld-lookup f-name)))
 
     (if (not f)
-       (parse-error "FIXME" "unknown ifield" f-name))
+       (parse-error (tstate-context tstate) "unknown ifield" f-name))
 
     (let* ((mode (obj:name (ifld-mode f)))
           (try (list '-op- #f mode f-name #f))
 (define (-build-index-of-operand! expr tstate op-list)
   (if (not (and (rtx? (rtx-index-of-value expr))
                (rtx-kind? 'operand (rtx-index-of-value expr))))
-      (parse-error "FIXME" "only `(index-of operand)' is currently supported"
+      (parse-error (tstate-context tstate)
+                  "only `(index-of operand)' is currently supported"
                   expr))
 
   (let ((op (rtx-operand-obj (rtx-index-of-value expr))))
     (let ((indx (op:index op)))
       (if (not (eq? (hw-index:type indx) 'ifield))
-         (parse-error "FIXME" "only ifield indices are currently supported"
+         (parse-error (tstate-context tstate)
+                      "only ifield indices are currently supported"
                       expr))
       (let* ((f (hw-index:value indx))
             (f-name (obj:name f)))
   (assert (rtx? sem-code))
 
   (let*
-      ; String for error messages.
-      ((errtxt "semantic compilation")
-
+      (
        ; These record the result of traversing SEM-CODE.
        ; They're lists of (type object mode name [args ...]).
        ; TYPE is one of: -op- reg mem.
                     (cond ((number? regno) #t)
                           ((form? regno)
                            (rtx-traverse-operands rtx-obj expr tstate appstuff))
-                          (else (parse-error errtxt
+                          (else (parse-error (tstate-context tstate)
                                              "invalid register number"
                                              regno)))
                     (-build-reg-operand! expr tstate
            ; Instruction fields.
            ((ifield) (let ((ref-type (-rtx-ref-type parent-expr op-pos)))
                        (if (not (eq? ref-type 'use))
-                           (parse-error errtxt "can't set an `ifield'" expr))
+                           (parse-error (tstate-context tstate)
+                                        "can't set an `ifield'" expr))
                        (-build-ifield-operand! expr tstate in-ops)))
 
            ; Hardware indices.
            ; For constants, this is the constant.
            ((index-of) (let ((ref-type (-rtx-ref-type parent-expr op-pos)))
                          (if (not (eq? ref-type 'use))
-                             (parse-error errtxt "can't set an `index-of'" expr))
+                             (parse-error (tstate-context tstate)
+                                          "can't set an `index-of'" expr))
                          (-build-index-of-operand! expr tstate in-ops)))
 
            ; Machine generate the SKIP-CTI attribute.
                 "End of operands.\n"))
 
        (csem-make compiled-expr sorted-ins sorted-outs
-                  (atlist-parse sem-attrs "" "semantic attributes")))))
+                  (atlist-parse context sem-attrs "")))))
 )
 \f
 ; Traverse SEM-CODE, computing attributes derivable from it.
   (assert (rtx? sem-code))
 
   (let*
-      ; String for error messages.
-      ((errtxt "semantic attribute computation")
-
+      (
        ; List of attributes computed from SEM-CODE.
        ; The first element is just a dummy so that append! always works.
        (sem-attrs (list #f))
     (let
        ; Drop dummy first arg.
        ((sem-attrs (cdr sem-attrs)))
-      (atlist-parse sem-attrs "" "semantic attributes")))
+      (atlist-parse context sem-attrs "")))
 )
index 609246f..89add88 100644 (file)
                                          ";\n")
                           ""))
                      (else
-                      (parse-error "insn function unit spec"
+                      (parse-error (make-prefix-context "insn function unit spec")
                                    "invalid spec" arg))))
                  overrides)
       ; Create bitmask indicating which args were referenced.
 
 (define (-create-virtual-insns! isa)
   (let ((isa-name (obj:name isa))
-       (context "virtual insns")
+       (context (make-prefix-context "virtual insns"))
        ;; Record as a pair so -virtual-insn-add! can update it.
        (ordinal (cons #f -1)))
 
index f92f443..99eeef9 100644 (file)
                                          ";\n")
                           ""))
                      (else
-                      (parse-error "insn function unit spec"
+                      (parse-error (make-prefix-context "insn function unit spec")
                                    "invalid spec" arg))))
                  overrides)
       ; Create bitmask indicating which args were referenced.
@@ -1909,7 +1909,7 @@ struct scache {
 
 (define (-create-virtual-insns!)
   (let ((all (all-isas-attr-value))
-       (context "virtual insns")
+       (context (make-prefix-context "virtual insns"))
        ;; Record as a pair so -virtual-insn-add! can update it.
        (ordinal (cons #f -1)))
 
index e7bc807..221545c 100644 (file)
 ; TYPE-SPEC is: (mode [(dimensions ...)])
 ;           or: ((mode bits) [(dimensions ...)])
 
-(define (parse-type errtxt type-spec)
+(define (parse-type context type-spec)
   ; Preliminary error checking.
   (let ((expected
         ", expected (mode [(dimensions)]) or ((mode bits) [(dimensions)])"))
     (if (not (list? type-spec))
-       (parse-error errtxt (string-append "invalid type spec" expected)
+       (parse-error context (string-append "invalid type spec" expected)
                     type-spec))
     (let ((len (length type-spec)))
       (if (or (< len 1)
              (> len 2))
-         (parse-error errtxt (string-append "invalid type spec" expected)
+         (parse-error context (string-append "invalid type spec" expected)
                       type-spec))
       ; Validate the mode spec.
       (cond ((symbol? (car type-spec))
            ((list? (car type-spec))
             (begin
               (if (not (= (length (car type-spec)) 2))
-                  (parse-error errtxt
+                  (parse-error context
                                (string-append "invalid mode in type spec"
                                               expected)
                                type-spec))
               (if (not (symbol? (caar type-spec)))
-                  (parse-error errtxt
+                  (parse-error context
                                (string-append "invalid mode in type spec"
                                               expected)
                                type-spec))
               (if (not (integer? (cadar type-spec)))
-                  (parse-error errtxt
+                  (parse-error context
                                (string-append "invalid #bits in type spec"
                                               expected)
                                type-spec))
               ))
             (else
-             (parse-error errtxt
+             (parse-error context
                           (string-append "invalid mode in type spec" expected)
                           type-spec)))
       ; Validate the dimension list if present.
          (if (or (not (list? (cadr type-spec)))
                  (not (all-true? (map non-negative-integer?
                                       (cadr type-spec)))))
-             (parse-error errtxt
+             (parse-error context
                           (string-append "invalid dimension spec in type spec"
                                          expected)
                           type-spec)))
        (dims (if (> (length type-spec) 1) (cadr type-spec) nil)))
 
     ; Look up the mode and create the mode object.
-    (let* ((base-mode (parse-mode-name mode errtxt))
+    (let* ((base-mode (parse-mode-name context mode))
           (mode-obj
            (cond ((eq? mode 'INT)
                   (mode-make-int bits))
                   (mode-make-uint bits))
                  (else
                   (if (and bits (!= bits (mode:bits base-mode)))
-                      (parse-error errtxt "wrong number of bits for mode"
+                      (parse-error context "wrong number of bits for mode"
                                    bits))
                   base-mode))))
 
index 64651b2..7ad784c 100644 (file)
 ;;; Return a single-location in a readable form.
 
 (define (single-location->string sloc)
+  ;; +1: numbers are recorded origin-0
   (string-append (single-location-file sloc)
                 ":"
-                ;; +1: numbers are recorded origin-0
-                (number->string (+ (single-location-line sloc)
-                                   1))
+                (number->string (+ (single-location-line sloc) 1))
                 ":"
-                (number->string (+ (single-location-column sloc)
-                                   1))
-                (if (single-location-end? sloc) "(end)" "")
-                )
+                (number->string (+ (single-location-column sloc) 1))
+                (if (single-location-end? sloc) "(end)" ""))
+)
+
+;;; Same as single-location->string, except omit any directory info in
+;;; the file name.
+
+(define (single-location->simple-string sloc)
+  ;; +1: numbers are recorded origin-0
+  (string-append (basename (single-location-file sloc))
+                ":"
+                (number->string (+ (single-location-line sloc) 1))
+                ":"
+                (number->string (+ (single-location-column sloc) 1))
+                (if (single-location-end? sloc) "(end)" ""))
 )
 
 ;;; Return a location in a readable form.
 \f
 ; Parsing utilities
 
-; Parsing context, used to give better error messages.
+;;; A parsing/processing context, used to give better error messages.
+;;; LOCATION must be an object created with make-location.
 
 (define <context>
   (class-make '<context> nil
              '(
-               ; Name of file containing object being processed.
-               (file . #f)
-               ; Line number in the file.
-               (lineno . #f)
-               ; Error message prefix
-               (prefix . "")
+               ;; Location of the object being processed,
+               ;; or #f if unknown (or there is none).
+               (location . #f)
+               ;; Error message prefix or #f if there is none.
+               (prefix . #f)
                )
              nil)
 )
 
 ; Accessors.
 
-(define-getters <context> context (file lineno prefix))
+(define-getters <context> context (location prefix))
 
 ; Create a <context> object that is just a prefix.
 
-(define (context-make-prefix prefix)
-  (make <context> #f #f prefix)
+(define (make-prefix-context prefix)
+  (make <context> #f prefix)
+)
+
+; Create a <context> object that (current-reader-location) with PREFIX.
+
+(define (make-current-context prefix)
+  (make <context> (current-reader-location) prefix)
+)
+
+; Create a new context from CONTEXT with TEXT appended to the prefix.
+
+(define (context-append context text)
+  (make <context> (context-location context)
+       (string-append (context-prefix context) text))
 )
 
-; Create a <context> object for the reader.
-; This sets file,lineno from (current-input-port).
+; Create a new context from CONTEXT with NAME appended to the prefix.
 
-(define (context-make-reader prefix)
-  (make <context>
-    (or (port-filename (current-input-port))
-       "<input>")
-    (port-line (current-input-port))
-    prefix)
+(define (context-append-name context name)
+  (context-append context (stringsym-append ":" name))
 )
 
 ; Call this to issue an error message.
 ; ARG is the value that had the error if there is one.
 
 (define (context-error context errmsg . arg)
-  (cond ((and context (context-file context))
+  (cond ((and context (context-location context))
         (let ((msg (string-append
-                    (context-file context) ":"
-                    (number->string (context-lineno context)) ": "
+                    "@ "
+                    (location->string (context-location context))
+                    ": "
                     (context-prefix context) ": "
                     errmsg ": ")))
           (apply error (cons msg arg))))
 ; together.  Each element can in turn be a list of symbols, and so on.
 ; This supports symbol concatenation in the description file without having
 ; to using string-append or some such.
-; FIXME: Isn't the plan to move ERRTXT to the 1st arg?
 
-(define (parse-name name errtxt)
+(define (parse-name context name)
   (string->symbol
    (let parse ((name name))
      (cond
       ((list? name) (string-map parse name))
       ((symbol? name) (symbol->string name))
       ((string? name) name)
-      (else (parse-error errtxt "improper name" name)))))
+      (else (parse-error context "improper name" name)))))
 )
 
 ; Parse an object comment.
 ; COMMENT is either a string or a list of strings, each element of which may
 ; in turn be a list of strings.
-; FIXME: Isn't the plan to move ERRTXT to the 1st arg?
 
-(define (parse-comment comment errtxt)
+(define (parse-comment context comment)
   (cond ((list? comment)
-        (string-map (lambda (elm) (parse-comment elm errtxt)) comment))
+        (string-map (lambda (elm) (parse-comment context elm)) comment))
        ((or (string? comment) (symbol? comment))
         (->string comment))
-       (else (parse-error errtxt "improper comment" comment)))
+       (else (parse-error context "improper comment" comment)))
 )
 
 ; Parse a symbol.
 ; Parse a number.
 ; VALID-VALUES is a list of numbers and (min . max) pairs.
 
-(define (parse-number errtxt value . valid-values)
+(define (parse-number context value . valid-values)
   (if (not (number? value))
-      (parse-error errtxt "not a number" value))
+      (parse-error context "not a number" value))
   (if (any-true? (map (lambda (test)
                        (if (pair? test)
                            (and (>= value (car test))
                            (= value test)))
                      valid-values))
       value
-      (parse-error errtxt "invalid number" value valid-values))
+      (parse-error context "invalid number" value valid-values))
 )
 
 ; Parse a boolean value
 ; This is done by each of the argument validation routines so the caller
 ; doesn't need to make two calls.
 
-(define (arg-list-validate-name errtxt arg-spec)
+(define (arg-list-validate-name context arg-spec)
   (if (null? arg-spec)
-      (parse-error errtxt "empty argument spec"))
+      (parse-error context "empty argument spec" arg-spec))
   (if (not (symbol? (car arg-spec)))
-      (parse-error errtxt "argument name not a symbol" arg-spec))
+      (parse-error context "argument name not a symbol" arg-spec))
   *UNSPECIFIED*
 )
 
 ; Signal a parse error if an argument was specified with a value.
 ; ARG-SPEC is (name value).
 
-(define (arg-list-check-no-args errtxt arg-spec)
-  (arg-list-validate-name errtxt arg-spec)
+(define (arg-list-check-no-args context arg-spec)
+  (arg-list-validate-name context arg-spec)
   (if (not (null? (cdr arg-spec)))
-      (parse-error errtxt (string-append (car arg-spec)
-                                        " takes zero arguments")))
+      (parse-error context (string-append (car arg-spec)
+                                         " takes zero arguments")))
   *UNSPECIFIED*
 )
 
 ; Validate and return a symbol argument.
 ; ARG-SPEC is (name value).
 
-(define (arg-list-symbol-arg errtxt arg-spec)
-  (arg-list-validate-name errtxt arg-spec)
+(define (arg-list-symbol-arg context arg-spec)
+  (arg-list-validate-name context arg-spec)
   (if (or (!= (length (cdr arg-spec)) 1)
          (not (symbol? (cadr arg-spec))))
-      (parse-error errtxt (string-append (car arg-spec)
-                                        ": argument not a symbol")))
+      (parse-error context (string-append (car arg-spec)
+                                         ": argument not a symbol")))
   (cadr arg-spec)
 )
 \f
                  ((operand) (set! entry (current-op-lookup entry-name)))
                  ((insn) (set! entry (current-insn-lookup entry-name)))
                  ((macro-insn) (set! entry (current-minsn-lookup entry-name)))
-                 (else (parse-error "sanitize" "unknown entry type" entry-type)))
+                 (else (parse-error (make-prefix-context "sanitize")
+                                    "unknown entry type" entry-type)))
 
                ; ENTRY is #f in the case where the element was discarded
                ; because its mach wasn't selected.  But in the case where
                        ))
 
                    (if (and (eq? APPLICATION 'OPCODES) (keep-all?))
-                       (parse-error "sanitize"
+                       (parse-error (make-prefix-context "sanitize")
                                     (string-append "unknown " entry-type)
                                     entry-name)))))
            entry-names)