CN1399737A - 便于组件选择的软件开发系统 - Google Patents

便于组件选择的软件开发系统 Download PDF

Info

Publication number
CN1399737A
CN1399737A CN 00816143 CN00816143A CN1399737A CN 1399737 A CN1399737 A CN 1399737A CN 00816143 CN00816143 CN 00816143 CN 00816143 A CN00816143 A CN 00816143A CN 1399737 A CN1399737 A CN 1399737A
Authority
CN
China
Prior art keywords
places
software development
development system
appurtenant
file
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Pending
Application number
CN 00816143
Other languages
English (en)
Inventor
F·科亨
M·A·波姆贝特
R·D·卢辛斯基
T·A·路易斯
M·S·桑杜斯基
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Phoenix Technologies Ltd
Original Assignee
Phoenix Technologies Ltd
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Priority claimed from US09/404,298 external-priority patent/US6487713B1/en
Application filed by Phoenix Technologies Ltd filed Critical Phoenix Technologies Ltd
Publication of CN1399737A publication Critical patent/CN1399737A/zh
Pending legal-status Critical Current

Links

Images

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F8/00Arrangements for software engineering
    • G06F8/30Creation or generation of source code
    • G06F8/34Graphical or visual programming
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F8/00Arrangements for software engineering
    • G06F8/70Software maintenance or management
    • G06F8/71Version control; Configuration management

Landscapes

  • Engineering & Computer Science (AREA)
  • Software Systems (AREA)
  • General Engineering & Computer Science (AREA)
  • Theoretical Computer Science (AREA)
  • Physics & Mathematics (AREA)
  • General Physics & Mathematics (AREA)
  • Computer Security & Cryptography (AREA)
  • Stored Programmes (AREA)

Abstract

一个软件开发系统从源代码单元的核心库中开发一个产品,该核心库被归类到具有一个或者多个特征的组件中。配置器基于一个指定的平台类型和源代码单元开发配置状态数据。一个图形用户界面依据该配置状态数据显示该产品的可视化和逻辑表示,它包括任何未解决的从属物的可视指示。一个产品生成例程然后依据该配置状态数据从源代码单元中生成该产品。

Description

便于组件选择的软件开发系统
本发明的背景技术
1.发明领域/概述
本发明通常涉及用于开发和集成一个软件产品的方法和系统,它通过定制和组合源代码库并且集成它们以形成该软件产品。更特别和说明性地,本发明涉及一种用于为一台个人计算机(PC)保持和重复使用一个基本输入/输出系统(Basic Input/Output System,BIOS)的核心组件的软件系统,它简化了BIOS配置,并且为可扩展而且可维护的核心库提供允许快速产品开发、增强、和修改的结构。
2.背景及技术现状
一个BIOS产品是当一台PC被启动或者“引导”时执行的一段软件代码,而且稍后当该PC运行时被调用以提供各种服务。一个用于BIOS产品的开发系统必须支持所有可以被安装在任何类型PC上的外围设备,这些PC可以从一种低端的基本PC到一种最新的、高度定制的、高端服务器或者便携式产品。在下面将描述构造一个BIOS的各个方面,以说明应当提供用于保持和使用一个核心BIOS软件组件库的软件系统的性能。
希望为一台特定机器构造一个BIOS的一个用户从这样一个组件库中选取核心BIOS软件组件以支持安装在那台机器上的外围设备。每个软件组件都可以包含一个或多个特征,而且可以通过为来自于该可用特征集合的特征增加或者删除代码、以及通过为这个代码指定可选参数(“选项”)值,来进行配置。用户可能希望为由该用户定制制造的、以及不能从该BIOS供应厂商得到的外围设备增加特定的BIOS代码。
可配置的特征被实现为在核心BIOS组件库中的单独代码,在该代码中具有通过名称以及通过目录/子目录或者由库名寻址其它代码组件的外部引用和定义,以便只有当它被正确地配置和寻址时用于每个特征的代码能够被链接到最终产品里。现有技术是将用于一个调用、命名、以及寻址的未被选择的可选特征代码替换为一个仅仅返回到它的调用者的存根例程。另一个可能性是间接地通过一个指针引用该可选特征,如果该特征被删除了,则该指针能够被设置为空;然而,这需要每个调用者检验该指针是否有效。理想地,当该组件被构造时应当从该代码中删除调用一个可选特征的代码,以实现节省由该程序占用的执行时间和存储容量。
现有技术将一个软件组件的可选参数(在下文中被称作“选项”)定义为显现常数,例如“BUFFER SIZE EQU 256”。当定义一个显现常数时该显现常数的名称(BUFFER SIZE)和它表示的值(256)是相关联的。例如,当源代码被编译时,每个对一个显现常数名称的引用,诸如一个数组的长度或者一个变量值,被替换为相关的常量值。这允许每个选项被赋予一个描述性的名称,并且使得通过改变一个定义来改变在所有被引用位置的选项值成为可能。诸如这样的选项,一般通过手工定义或者修改一个“inc1ude(包含)”文件来进行设置或者调整。然后该“包含”文件通过引用被合并到其它源代码文件里。这容易遗漏一个包含有对一个选项名称引用的文件,或是容易混淆在不同系统组件中具有相同名称的选项。
核心BIOS组件库的生产者和销售者需要对在市场中变得可用的新设备快速做出响应。一个行之有效的方法是复制用于一个类似现有设备的代码,并且仅仅在必要处修改它以支持该新设备。原始代码可能已经支持现在也可用于该新设备的几个可配置特征。从另一个核心组件中复制代码导致在同一个库中的两个组件不仅具有相同的特征,而且具有引用它们的相同外部名称。这个非单值性能够在编译和链接时导致进一步的混乱。
用户可以销售包括有一种老设备或一种新设备的机器。因此用户可以构造一个既包括一个支持旧设备的旧软件组件又包括一个支持新设备的新组件的BIOS,其中该新组件通过修改该旧组件生成并且具有相同的外部名称。该BIOS将包含附加代码以截取对在旧和新组件中的每个程序的调用。然后用户将为每个所截取的程序增加判定代码以判定在新组件还是在旧组件中的程序应当被调用。这导致一个BIOS包含两个具有相同外部名称的组件以及用于每个所截取调用的判定代码,其中每个所截取的调用必须没有被截取地调用具有相同名称的两个程序中的一个。两个软件组件将不得不被分别地编译和链接以便使得在每个组件中相同的外部名称不会冲突。它们也将不得不和调用它们的判定代码一起被链接。
假定旧的组件、和通过修改该旧组件生成并具有相同外部名称的新组件都具有一个名为INIT的初始化特征。如上所述的附加判定代码必须代替该INIT程序被调用,所以它能够确定是在旧的或是新的组件中的INIT程序应当被调用。现有技术要求对INIT的每个调用将间接地通过一个指针表进行,以便使该指针能够变成截取、或是钩住每个这样的调用。在整个BIOS中所有对INIT的调用都将以这样的方式被截取或者钩住。截取这种调用的能力对于调试目的来说是同样重要的。
核心BIOS组件库的生产者通过快速地发布该库的新版本,对在市场中变得可用的新设备作出响应。在保持和增强该库的过程中,他们可以修改某些接口以增加功能或者修正程序错误。具有一个现有BIOS的用户将希望包括该新功能和程序错误修正以及最近支持的设备。用户必须检验对已经改变了的现有接口的调用仍然是兼容的,而且快速地识别出现在是不兼容的而且必须被改变的那些接口。现有技术通过匹配参数的数目、每个参数的类型、以及值的范围来验证接口。
用于一个特定设备的BIOS代码通常包含当PC启动时所执行的初始化代码,以及当调用时提供服务的支持代码。在该支持代码中可能没有对初始化代码的引用,或者反之亦然,这将导致这两段代码被包含在该BIOS构造之内;然而,该支持代码显然取决于该初始化代码。现有技术需要人工干预以确保这两段代码都被包含在该构造之内。
最后为一致性检测源代码模块的传统方式是:编译和/或汇编这些分离的源代码文件,以识别和校正所有的错误并且重复这个过程;链接目标代码文件,以识别和校正所有的错误并且重复这两个过程;以及最后,结合这些分别链接的系统单元到一个内链接的映象中,以识别和校正所有的错误,并且重复地和递归地重复所有这三个过程直到不再发现错误为止。尽管那样,也可能从用于在不同源文件集合中表示不同事物的同一名称、在两个非常相似的源文件集合中错误集合的选择、或是不能被编译器和汇编器检测到的版本不相容性中产生不适当的链接。所有这些问题集合起来会使得软件系统的开发和集成比它理想上应当花费的时间更加费时。
因此,本发明的基本目的是实现一个软件开发系统,它能够在任何汇编、编译、或是链接之前识别和帮助一个人校正上述的错误类型;它允许一个人简单地查看和选择组件、特征、以及变化,而且不考虑相应的源代码被存储在哪里;它允许一个人在全局上指定这个产品是一个“服务器”或者一个“便携式”,并且由此实现完全不同的系统配置;而且,它通过选择几个组件变化中的适当一个、调整并且控制选项的值和范围、根据源代码从属物自动选择所需的系统组件,来解决以上提及的问题。
本发明的简要概述
简要地来说,而且根据这些及其它目的和优点,本发明被体现在一个软件开发系统中,该系统为了使用那个库生成软件产品的目的管理一个源代码库。本发明从一个源代码文件系统中收集许多信息,其中该文件系统被构造为便于和允许系统设计员支持这个收集。所收集的信息具有各种用处,其中一个是配置正被开发的产品。产品配置包含选择将要被集成到最终产品映象中的源代码库部分。为正生成产品的类型,以及为了满足代码从属物,通过引入子程序自动进行配置以构造一个完整和相关的产品。向系统设计员呈现对源代码的一个查看,其中该源代码将应用和被构造到正开发的产品中,而且他或她被赋予由本发明支持的简化了的定制性能。所提供的定制技术在该产品的使用期中通过升级和维持是可维护的。
该产品配置进入产品构造过程,由此允许编译和对象创建利用所获得的产品知识。配置数据借助于在添加到该代码树上的动态生成文件中所定义的等式,被传递到编译过程中。为了尺寸优化或是为了流程控制,预处理器宏进行扩展以利用这些等式。例如,取决于在所生成文件中提供的一个等式值,一个可选的程序调用能够在内部或者外部被编译。这个等式的值基于该程序调用是否为产品配置的一部分。该产品配置确定要编译到最终产品映象里的特定文件。在这个发明的最佳实施例中,基于该产品配置,动态地生成Unix风格的Makefi1es。这个过程代替搜索对象库的使用;所有生成的对象库都是加载库。
本发明也通过编译过程传递信息到这个发明的一个产品链接器。这个产品链接器能够支持附加的定制支持、资源优化、执行位置管理、以及超过正常地址链接的产品验证。
作为这个发明的一部分,源代码文件被放置在一个目录分级结构中。不同的子目录可以对应于不同的软件“组件”。在该目录分级结构中,每个“组件”,不论它是一个真实的软件组件或是一个表示支持一个特定硬件设备所需要软件的“硬件组件”,都可以由保存在较低级子目录中的一个或多个“特征”进一步定义,以便使一个或多个特征可以包含每个组件,而且还可以有保存在更低级子目录中的“子特征”。一个或多个源代码文件可以驻留在每个特征子目录中。每个组件以及每个特征由一个信息文件进一步进行描述,其中该信息文件被放置在它的定义了一个特征将用于何种类型平台(服务器、笔记本等)、它被分配给什么类等的相应子目录中。
在本发明的最佳实施例中,源代码文件调用特定的预处理器宏来定义每个外部程序并且把它分类为公共的(可在组件之间调用)或者私有的(仅仅可由在一个组件内的双亲或者同胞调用)。对这样一个外部程序的每个调用也由一个特定的宏例程产生,而且包含这样一个调用的每个源文件声明该程序正被一个对另一个特定宏例程的调用公开地或者私有地引用。这些特定的宏例程可以和其它的事物一起传递程序修订号和程序类命名。特定的宏也被用于定义公共的和私有的“包含”文件以及声明对它们的引用。此外,特定的宏可以被用来生成一个列表、定义形成这样一个列表以及从各个源代码组件中得到的入口、以及为该列表入口指定分类条件。
扫描该组件信息文件和特征信息文件,并且把它们的内容存储在一个特定的数据库内。这些文件可以将一个组件或者特征关联到一个特定的类,并且可以指定一个组件适合或者必需的平台类型(台式、便携式、服务器、等)。也扫描分配给每个特征的源代码文件,而且与特定宏有关的参数、诸如类和版本号也与每个特征的目录地址一起被输入到该数据库中。然后这个数据库保持该源代码库的一个完整说明,包含可用的组件、每个组件提供的特征、特征被一起分类以便使它们以后可以被链接到一起的方式、以及选择组件和特征用于包含到一个特定的平台类型(便携式、服务器等)中的规则。用于每个特征的信息包含必须被编译以提供每个特征的源文件、到每个特征的外部接口、依据外部定义的子程序和选项的每个特征的从属物、以及防止在不同类内的相同名称而导致混淆和交叉链接的类分配。
一旦使用本发明的一个系统设计员已经指定了一种平台类型以后,为指定用于这样一个平台的一个配置所必需的最少信息就从该数据库中提取出来,它包含指定的平台类型所需要的所有组件和所有特征。这个平台规范标识一个基本的源代码文件集合,其中这些文件必须被编译和链接以提供期望的系统配置。来自于本发明的宏参数中的信息对于将每个程序调用和选项关联到它的适当定义来说是绰绰有余的。
本发明在它将每个程序调用和它的定义相关联并且标识所有遗漏的程序这一点上,以一个链接器的方式进行作用;然而,这个测试“链接”过程在编译或者汇编和链接和使用可以从在该库内找到的所有特定宏的参数中获得的全部信息之前很久就发生了。这允许本发明使用不同于仅仅匹配程序名称和参数数量的、以及除此之外的条件,将一个程序调用和它的定义相关联,并且允许标识和表示正使用一个不兼容接口、诸如不兼容版本程序的程序调用,并且通过类命名区分程序调用。
本发明在编译或者汇编之前快速地标识在当前配置内的问题和错误,并且提供了一个可视界面,设计员能够通过该界面选择和编辑源代码文件来快速地定位和修正问题。同一个可视界面也允许设计员利用一个鼠标按纽的点击增加或删除组件和特征,并且允许增加或者越权源文件选择以按要求调整配置。
一旦设计员已经选择了一个正确的配置,他或她就可以指导本发明构造所配置的产品。然后本发明编译或者汇编仅仅那些由该配置数据所指定的源文件;并且分别地链接每个特征以解决在该组件内的私有外部引用,转换类命名到特定地址中以解决在公共外部引用中的非单值性,并且由此为每个组件产生一个链接的可执行文件。最后,调用一个特定产品组件链接器作为一个第二级链接器,它能够将分离的组件可执行文件一起链接到最后集成的产品里。每个公共的程序调用用它引用的公共程序的地址进行修正。由本发明中的列表宏定义的列表被收集、分类和保存在它们被定义的代码段中。
该产品组件链接器由与该宏有关的数据控制和指导,而且在该最佳实施例中,这些数据在由该组件链接器读取然后删除的特定代码段中被传递给该组件链接器。在该最佳实施例中,各个选项的确定以及在程序调用和程序入口点之间的链接也由自动产生的、传递信息到每个源代码文件里的特定“包含”文件控制,以允许每个宏重新定义、重定向、或者甚至完全忽略任何给定的程序调用语句,以控制每个选项的范围,以及允许设计员通过该可视界面调整选项值。在一个较少RAM环境中进行的程序调用也可以通过宏实现,其中宏自动地使用一个寄存器用于存储返回地址,并且自动地在ROM代码中提供伪堆栈和寄存器控制的返回跳转以截取程序“返回”指令。
在附图和随后对最佳实施例的详细说明中,本发明的其它目的、特征、和优点会是显然的。在附加到这个说明书、并且形成这个说明书一部分的权利要求中详细地指出了表示本发明新颖性的特征。
附图简要描述
图1显示了根据本发明示教设计的一个程序开发系统100的一个概述方框图,它强调在各个软件单元之间的关系;
图2显示了该可视用户界面系统的概述,列出了用户可执行的功能,而且还列出了显示功能;
图3是一个显示了执行用户启动命令的例程的方框图;
图4是数据库更新例程的一个方框图;
图5A是一个说明了修改一个文件、更新数据库、确定一个修订了的产品配置、以及向用户或者系统设计员显示该最新修订的配置的过程的流程图;
图5B是一个说明了生成一个最终产品过程的流程图,包含扫描所有文件、更新该数据库、修订该配置(如果必要的话)、向系统设计员显示任何配置修订、以及构造该成品;
图6是数据库访问例程的一个框图;
图7是配置器例程的一个框图;
图8是一个说明了该产品生成程序的概述的流程图;
图9A是为每个特征生成“feature.inc”文件的构造筹备例程的一个流程图;
图9B是生成组件makefiles并且调用在图9A中的例程以生成该“feature.inc”文件的构造筹备例程的一个流程图;
图10一个是当执行产品和组件makefiles时由生成工具执行的步骤的流程图,其导致源代码选择、修改、编译、汇编、链接、以及由产品组件链接器进行的最后组件链接;
图11是一个说明了该程序开发系统100的概述的流程图,其强调了本发明的数据流方面;
图12说明了该组件源代码库(在图11中的1200)的内容的一个概要;
图13举例说明了占用图11中所示的组件源代码库1200的、一个典型的IBM PC兼容汇编语言源代码文件1300的内容;
图14举例说明了占用如图11中所示的组件源代码库1200的、一个典型组件信息文件“component.inf”1400的内容;
图15举例说明了一个可以被放置在组件信息文件中的东西的实例;
图16举例说明了占用如图11中所示的组件源代码库1200的、一个典型特征信息文件“feature.inf”1600的内容;
图17举例说明了一个可以被放置在特征信息文件中的东西的实例;
图18举例说明了如图11中所示的组件数据库1800的内容的一个概要;
图19举例说明了如图11中所示的配置状态数据1900的内容的一个概要;
图20举例说明了如图19所示的数据部分的一个概要,它被选择和输入到如图8和图34所示的产品生成例程900中,以管理该成品的构造;
图21举例说明了一个被包含在如图11所示的产品配置数据文件“platform.cfg”2100中的产品配置命令的示范性集合;
图22举例说明了可以被放置在这个“platform.cfg”文件中的东西的概要;
图23举例说明了一个示范性特征包含文件“feature.inc”2300(图11)的内容,这些内容由产品生成例程900(图11)自动地产生,而且更特别地,由构造特征包含文件例程950(图9A和图35)产生;
图24举例说明了由产品生成例程800(图8和图34)自动产生的、以及更特别地由组件构造筹备例程900(图9B和图34)自动产生的一个示范性组件生成文件2400(图11)的内容;
图25举例说明了由产品生成例程800(图8和图34)自动产生的一个示范性产品生成文件2500(图11)的内容;
图26是也如图4所示的数据库更新例程400的一个方框图;
图27是一个揭示了如图26中所示的特征和组件文件扫描例程2700(由在图4、11、和26中的步骤调用)的细节的方框图;
图28是如图11中所示、也如图7所示的配置器程序2800的一个方框图;
图29是配置器程序2800(图28)的初始激活例程2900部分的一个方框图;
图30是配置器程序2800(图28)的产品配置例程3000部分的一个方框图;
图31是在配置器程序3000(图28)的产品配置例程3000(图30)内的解决外部引用例程3100的一个方框图;
图32举例说明了基于RAM的产品配置数据1900(图11)的内部结构,也如图19中所示;
图33A显示了本发明的图形用户界面的一个系统设计员视图;它包含一个项目的一个逻辑视图和特定文件的窗口视图;
图33B举例说明了在该用户界面中如何向系统设计员揭示错误;
图33C举例说明了系统设计员如何打开、删除、或者越权一个源代码文件,或是如何从图形用户界面中获悉它的属性;
图33D举例说明了系统设计员如何利用该图形用户界面打开和选择或者取消选择一个组件;
图33E举例说明了一个系统设计员如何使用该图形用户界面调整一个选项;
图33F举例说明了图标以及它们在该图形用户界面中表示什么;
图34是产品生成例程800(图11)的一个概述方框图,也如图8所示;
图35是一个构造特征包含文件例程950的方框图,也如图9A中所示;
图36显示了产品组件链接器例程3600(图11)的一个方框图概述;
图37显示了列表生成和管理过程3700的一个方框图概述;
图38显示了一个举例说明通过系统100的控制信息流程来指导软件开发过程的方框图;
图39显示了一个举例说明非易失性RAM的分配和管理的方框图;
图40显示了一个举例说明字符串分配和管理的方框图;
图41显示了一个举例说明了本发明中的公共、私有、和“ShieldPrivates”从属物访问特征的方框图;以及
图42显示了一个举例说明了使用产品组件链接器3600来定制从一个表格中取得的单一项目的方框图。
本发明的详细说明
本发明的最佳实施例为在一个IBM兼容的PC ROM代码映象软件开发环境中使用而进行优化,在该软件开发环境中一个代码共享库由许多供应厂商使用,以开发用于具有各种不同处理器、总线、和外围设备的便携式、台式、和服务器的ROM BIOS代码映象。本发明使用传统未修改的汇编器、编译器、和链接器、以及一个标准UNIX风格的生成工具进行开发。此外,开发了一个特定的产品组件链接器3600(图36)以供本发明使用。组件链接器3600在许多方面是一个用于组合分别编译和链接的*.exe文件到单个集成的、适用于ROM存储的代码映像里的传统链接器。在下面会指出它不同于一种用于这个目的的传统工具的方式。
本发明者考虑到本发明对所有类型的嵌入式系统以及通常的软件开发都具有适用性,它超过了ROM BIOS映象的开发。在它的更一般特征中,本发明适用于其中软件组件和特征需要被管理、选择、和改变以满足特定客户的特定要求的任何软件开发环境。
由于传统的编译器、汇编器、和链接器在本发明的最佳实施例中使用而不需要任何特定文件预处理器,以及由于使本发明的某些步骤(在它的最佳实施例中)从在这样的编译器和汇编器内执行是所期望的和方便的和有效的,所以需要某些改变这些标准组件的性能的方法。因此,本发明的最佳实施例考虑在传统编程命令诸如“CALL”或者“PROC”或者“INCLUDE”等将正常出现的许多点处,插入专门定义的宏到该源代码中。这些特定的宏将在继本发明更一般概述说明之后、在这个说明书的结尾处,进行完全详细的描述。但是,也有可能利用预处理器或者利用修改的编译器和汇编器,它们能够实现本发明的功能而不需要也不使用某些或者所有这种特定宏。实际上,通过简单地使一个预处理器或者编译器和汇编器以实质上与本发明使它们对代替这些命令的宏作出响应相同的方式,对诸如“CALL”和“PROC”和“INCLUDE”之类的命令做出响应,源代码文件的作者不用必须使用特定宏,就能够获得在本发明最佳实施例中通过使用特定宏所获得的结果。本发明包含属于其范围内的、在设计中的这种变化。
此外,本发明的最佳实施例把控制产品组件链接器的数据放置到由特定宏定义和生成的特定代码段中,这是一种尤其在IBM PC环境中适用的技术,在该环境中分段也被大量用于其它目的。同样,能够容易地提供其它等效的方法,用于,例如在该过程中一个非常早的阶段,从许多源代码文件中收集这个数据(诸如列表的定义和内容),以及用于传递这个数据到组件链接器或者它的等效体借此实现本发明的目的。
在图1中显示了作为本发明最佳实施例的程序开发系统100的一个概述。图1强调形成该系统一部分的主要软件例程,以及它们彼此如何互相调用和互相关联。
系统100的核心处是一个集成的开发环境102,它包含一个用户界面200,其功能在图2中进行阐述。用户界面本身显示在图33A到33F中。参考图33A,向设计员呈现一个其中他或者她可以查看一个源代码库的一个逻辑的(如图所示)或者目录-子目录视图的第一窗口(在左侧)。一个“逻辑视图”是被组织的代码库的一个用户视图,而且首先按类、然后按组件、然后按特征、然后按子特征等的次序分级地显示该代码库的组件和特征,其中每个单独的源代码文件都和一个相应的组件、特征和子特征相关联。
如图33A所示,该逻辑视图包含一个根节点3308,它被显示为Platform-Desktop-IA32。在该根节点3308下面的第一级是一系列组件,诸如FDisk 3310、Inte1371ab(PIIX4)3314、POST服务3306等。在每一个组件下面的级别中,可能有一个或多个特征。例如,在图33A中,该Post服务组件3306包含若干个特征,诸如DecompressManager 3304、Memory Manager 3307、以及POST Dispatcher 3309。除了直接位于一个组件下面的级别之外,一个特征还可以在一个更低级别中被视为一个子特征,它是一个父特征的子特征。在图33A中,LZINT特征3311是Decompress Manager特征3304的一个子特征。
在下文中,术语“对象”一般将要被用于表示一个“组件”、“特征”、或者“子特征”。(在这个专利中,术语“对象”的这个特殊使用不要和在面向对象编程领域中分配给术语“对象”的完全不同的意思相混淆)。然而,具有由类(注意在图33A中用于组件3306的类命名“post”3321以及用于特征Decompress Manager 3304的“decompmgr”3323)细分的代码“逻辑视图”并不仅仅是一个用户视图。在源代码文件中,当对外部名称,诸如包含文件、程序、以及选项引用时,类命名可以替换在传统软件开发系统中使用的这些精确的目录/子目录地址,因此,程序员不必精确地考虑一个外部程序或者一个包含文件驻留的位置-仅仅需要考虑包含该外部程序的源代码文件被分配给的哪个类。
图2列出了由用户界面200执行的主要功能和提供的视图。设计员能够使用键盘或者鼠标202来修改一个文件或者目录302(图3);从一个有效的配置306中构造产品;通过迫使它们进入或者移出该构造来定制特征304;指定除来自于该组件源代码库的代码之外或者代替该代码的定制代码(文件越权)304;以及定制或者改变选项值304。作为这些变化的结果,更新的用户视图204,然后通过以下方式显示组件和特征树(在图33A的左侧):利用清楚地标记为在该构造内部(粗体)或者外部(模糊)的组件和特征(图33A);利用清楚地标记出设计员已经迫使它们进入(标记为一个复选)或者移出(标记为一个“禁止”斜线圆圈)该构造的地方的组件和特征,来越权该缺省的配置(图33D);利用显示的原始源文件加上定制3332以及清楚标记的越权文件(图33C);利用分别列出并且可收缩到一个图标中的从属物3325、3327(图33B);利用可查看的界面声明3329(图33B)、选项声明3336(图33E);以及利用清楚显示的特征/文件错误和警告3318、3320、3322、3324、以及3325(图33B)。
用户界面200允许设计员通过一个命令执行器例程300发布命令,该例程的一个概述视图在图3中显示。在图3以及随后的所有相似图中,任何越权了包含有例程300的组件的大矩形边界的矩形,包含一个或多个到该例程的入口点-一个或多个可以由该设计员或者一个调用例程发布的命令。
如果设计员希望更新或者修改一个源代码文件、或者移动一个文件到一个新目录里、或者改变该系统的目录结构,则设计员使用如图33A所示的用户界面这样做。例如,为了修订一个源代码文件,设计员使用鼠标和指针点击文件名称3326(图33C),并且选择“Open”。该文件出现在一个可编辑窗口(图33A的右半部)中,在其中设计员可以检查和选择性地修改该源代码文件(图5A中的步骤502)。当设计员完成时,设计员以传统的方式关闭该窗口并且“saves(保存)”任何修改。然后自动地调用命令执行器300来执行在图3以及以流程图形式在图5A中显示的步骤,它起始于302。首先,在图3、4、和5A中的步骤402处,假定文件已经被改变了,则调用数据库更新例程400(图4)来扫描该文件(在图4中的步骤404、406、和408)。例程400从源-代码-驻留的特定宏中以及在组件和特征信息文件中找到的命令中收集信息(在图4和图27中的步骤2700),其中该组件和特征信息文件定义了每个源代码文件的内部名称、入口点、以及出口,如图18中的1826到1830所示(源库数据库1800)。所收集的信息包含:分配给每个程序调用的“类(class)”,用于区别例如“TIMER”类程序和“DMA”类程序,从而使相同的程序名称不会被混淆(例如,“TIMER.RESET”不能和“DMA.RESET”混淆);版本号,诸如“3.2”,用于以后检查不兼容的版本;以及类似信息。所有这些信息由数据访问例程600写API例程602(图6)存储在数据库1800中(图6和18)。
接下来,在RAM中保持配置状态数据1900(图19和32)的配置器例程700(图7)在入口704处被调用,以使用数据库1800来更新产品配置状态数据1900,然后通过重新确定要包含什么对象(组件和特征)、要排除什么对象、要创建什么对象、用具有什么缺省值的设计员选项,取决于已经选定的平台类型(服务器、台式机等)需要满足什么从属物(选项、对函数的调用、文件包含等)等,来配置3000(图30)将要被构造的产品。最后,在步骤204(图3、5A及7中),调用例程UI UPDATE VIEW(图2)来重新生成在图33A左侧窗口内的软件系统逻辑视图,以和该设计员共享该系统的新状态,并且允许设计员改变缺省的对象选择(参见图33D中的菜单3334)或者调整选项值(参见图33E中的菜单3338)。以这种快速和不突出的方式,由该设计员做出的全部变化都被很快地和精确地记录下来,据此重新配置将要被构造的产品,而且向设计员立即呈现所有这个活动的结果。
如果设计员做了某些事情,例如由于一个不能被满足的从属物、诸如在库内缺少一个“调用(call)”语句能够被链接到的任何外部程序(这能够,例如简单地由一个程序名称的拼写错误引起),可能导致了在一个传统系统中的最后链接器失败,则如图33B所示,小的“X”将出现在导致该故障的项旁边。然后,设计员通过简单地经由所显示的树向下点击,可以很快地发现,例如引起该问题的特定“从属物”(例如,在图33B中的3324处,在类“pic”中的子程序名“SendEOI”,被显示为“pic.SendEOI”)。一个“find(查找)”工具允许包含这个引用的文件被快速地查找、打开、校正、和关闭,利用该系统再次被自动地更新和校正以反映该校正(于是“X”将消失)。
下面参考图3和5B,当到了构造最终产品的时候时,由用户界面200响应于一个用户键盘/鼠标命令202调用在命令执行器例程300中的“完整产品构造”入口306。再一次,调用数据库更新例程400(在图4中)、入口402,以执行对整个库:源代码文件、组件信息文件、和特征信息文件的一个扫描。简要地参考图15和17,“component.inf”和“feature.inf”组件和特征信息文件包含定义了选项值的构造命令(例如,行1528),而且还包含形式规则以在逻辑上确定一个特定对象(组件或者特征)何时被选择(例如,在图15中的行1514、1516、和1518)。这些文件还提供了用于相应的组件及/或特征的类命名(例如行1504)。这样一个类命名被自动地应用于在被保存在同一子目录中的任何源代码文件内的程序和标记,其中该子目录具有一个“component.inf”或者“feature.inf”文件包含这样一个类命名。这允许,例如对指定一个类就好象它是一个“路径”一样(“类路径”命名,诸如“TIMER.RESET”,其中“TIMER”是类而“RESET”是程序名称)的程序的外部调用,可以被恰当地查找和链接起来而不用单独调用源代码文件,其中单独调用源代码文件必须指定通过该源代码库树到被调用的程序源代码文件的实际路径。这个类命名也确定这些对象如何在库内容的用户“逻辑”视图而不是“目录/子目录”视图中被组织起来(图33A)。因为从属物总是就它们的类被指定,所以除了用于确定哪个子例程或者程序调用链接到哪个源代码文件中的哪个子例程或者程序的类之外,每当满足了依据一个从属物的任何类型外部引用时,该类命名也确定其它相似的链接。因此,相同的函数和程序名称、及其它名称(例如,包含文件名称)可以在分配给不同类的特征和对象中使用,而不会导致任何混淆或者错误链接。而且类命名允许查找包含文件和程序而不用考虑它们实际上被存储在该组件源代码库文件目录树中的哪个地方。例如,在汇编或者编译之前,自动地产生和插入包含文件路径(或者地址)而无需用户干涉或者知道该包含文件实际上被存储在哪儿。
接下来,更新数据库1800(图6)(在图4、5B、和6中的步骤602)。然后,再次调用配置器700以修订产品配置状态数据(步骤706);而且如果做出了任何改变,则调用例程UI UPDATE VIEW 204(图2)以更新用户的视图;而且如果出现了任何红色的“X”(图33B),则取消产品构造。
注意,在图7中,配置器用从一个文件“p1atform.cfg”中检索到的产品配置数据2100开始一个配置过程。参考图22,这个产品配置文件指定诸如PLATFORMTYPE 2201(服务器、台式机等,以及具体结构)、系统选项值2202、将要被包含或者不包含的特征2212、要被包含的附加文件2215、要被替换的文件2216(越权)、选项值2218-2220等之类的东西。所有这些信息都来自于用户界面,而且所有信息都在用户的指示下生成。通过向设计员询问简单问题以确定平台类型、系统结构、及其它这种基本东西,一个简单的问题询问例程(没有显示)能够被用于生成一个新的配置。每当设计员再次通过与用户界面相互作用、履行他或者她的选择权以越权缺少的对象选择和选项值时,就积累包含在这个文件中的剩余数据。(当然,这个文件也可以被人工地编辑;利用人工一次一个地执行在图1右侧所显示的例程,可以运行整个程序开发系统而不需要该用户界面;但是,本发明的大部分功能性在于该交互式的用户界面。)
接下来,配置器700进入数据库1800,并且利用该数据库包含的所有数据:从源代码文件扫描中获得的数据、以及尤其是程序员已经提供给特定宏调用语句的参数(诸如从每种类型的宏中获得的类、名称、版本号等等)、以及从占据与相应的类和特征源代码文件相同的子目录的特定类及特征文件中收集的数据,来载入它自己。所有这些信息组合起来被称为产品配置状态数据1900。如图19所示,这个数据包含组件名称1902、1904、1906,组件1908的描述,特征名称1910和1912,以及与每个特征有关的信息诸如类1914、文件1916、定义1917以及引用1919等。这是管理该用户显示的属性信息。注意,每个对象(特征或者组件)的“in(内部)”状态1922、1926和“out(外部)”状态1924、1928由在该配置状态数据中的一个标志位或者数字清楚地标记(如在图19中由X的存在或者不存在来表示)出来。
程序控制接下来继续一个对在图8中显示的产品生成例程800(在图3和5B中的步骤800)的调用。通过调用配置器700以提供所有活动(或者选择的)组件的一个列表,产品生成例程从步骤802开始。产品生成例程800最终将检索如图19所示的所有选择(或者被标记了“X”)的信息。这些选择的信息在图20的2000处显示。
下面返回到如图8所示的产品生成例程800,在步骤900,产品生成例程为每个分离的组件调用组件构造筹备例程900,如图9B所示。这个例程,在步骤902处,调用配置器700和它的RAM配置状态数据2100以便为该组件提供源代码文件和文件从属物信息。接下来,在步骤950,调用该构造筹备特征包含文件例程(图9A)以遍历该组件的每一个特征子目录。在步骤952,再次调用配置器700,这次是为了获得有关一个特定特征的信息。在步骤954,如果存在有任何信息的话,则将提供的信息与在该特征的“feature.inc”文件内找到的已有信息进行比较。如果该信息已经改变了(步骤956),则产生和写入一个新的“feature.inc”文件2300。接下来,在步骤960,如果有更多的特征,则重复这个过程直到在步骤962所有的特征都已经被检查过了为止。然后,程序控制返回到步骤904,在那儿该组件信息与任何已有的组件makefile内容进行比较。在步骤906,如果有任何的变化,则在步骤908生成一个新的组件makefile 2400(图24),由它管理该组件的恰当编译及/或汇编并且链接该组件以及它的所有特征到一个“*.obj”目标文件里。以这样的方式重复地调用该构造筹备组件makefile例程900,其为每个已经被选择用于包含在成品中的组件调用一次。
通过在下面的简要说明,“feature.inc”文件和实际上定义了每个特征的源代码文件一起被放置在每个特征子目录中。每一个特征源代码文件都包含命令“INCLUDE feature.inc”。这导致编译器或者汇编器为该特征插入一个特征的“feature.inc”文件到所有这些源代码文件中,在那儿它们可以执行这样的任务,诸如将类引用改变为文件路径引用、定义选项、以及设置如果程序调用调用了未经选择的组件的话,则导致从源代码中删除该程序调用(例如参见图23,其中值TRUE被分配给“D-TIMER-DELAY”,以导致一个对“TIMER DELAY”函数的子例程调用被包含在一个源代码中),或者例如,用一个具体的组件名称进行标记(要求链接到一个调用语句的程序驻留在所指定组件的一个特征内)。同样地,一个程序入口点能够被标记为“override(越权)”,以使其优于在某些其它源代码文件中的一个相同程序名称被选中。通过自动产生“feature.inc”文件的机制,所有这样的用户选项机制能够由系统设计员从图形用户界面中进行调整,而不需要编辑或者改变源代码文件本身。这用最少的工作,给予了系统设计员对成品配置的空前控制。
在所有组件都已经被处理了之后,程序控制返回到产品生成例程(图8),步骤908,在那儿生成一个产品makefile 2500。这个产品makefile 2500包含指示将计算机的焦点切换到各个组件子目录、然后使计算机执行在每个这种子目录内找到的组件makefiles 2400,借此为每个对象构造一个对象代码模块。然后,它调用产品组件链接器3600,把所有这些组件对象代码文件1104一起链接到成品1106里(图111)。
接下来,在图8中的步骤1000,在刚刚描述的组件和产品makefiles2400和2500的控制下调用一个标准的Unix“make(生成)”工具来构造该产品。这个过程在图10中被省略了。在步骤1002,从主要的makefile中读取一条选择了一个组件的子目录(步骤1006)的命令。由产品makefile 2500管理的生成(make)工具然后调用它本身来处理在那个组件子目录内找到的组件makefile 2400,该makefile 2400执行步骤1008到1016。在步骤1008,从组件makefile 2400中读取一条要求编译1010、汇编1012、或者链接1014一个特征源代码文件的命令,并且重复地继续这个过程直到所有命令都已经被执行了为止(步骤1016),由此产生一个构造产品组件文件1104,它同时还包含特定程序段,该程序段包含将由产品组件链接器3600稍后使用以便将一个或多个分开链接的可执行目标代码文件拼凑到一个完成的、统一的产品中的“修正”数据,(其它特定的程序段可以包含列表元件等)。在1018处,生成(make)工具,检测在产品makefile 2500中的更多命令,继续从这个文件2500中读取命令,选择附加的组件子目录,并且调用它本身来执行在与每个附加组件有关的makefile中找到的组件生成命令,正如刚才阐述的那样,直到最后所有的组件源代码文件都已经被编译或者汇编和链接了为止。
在步骤1004,该生成(make)工具最后到达产品组件链接器指令处(在图25中的2528和2530),它导致产品组件链接器3600,利用地址修正以便使所有类和名称引用被替换为绝对的映象地址,组合所有要被合并到单个代码映象中的、分别链接的组件可执行文件,为并入到一个基于ROM的成品1106作准备。
参考图2,有若干条可用的其它用户命令。在入口304处,设计员通过调用配置器700迫使一个特征进入或者移出以改变产品配置,而且这些变化被反映在和存储在项目配置数据文件2100“project.cfg”内。选项值可以以这种相同的方式进行改变,而且指定的用于包含在一个成品制造内的文件可以被由设计员指定的其它文件越权和替换。
另一个选项是在入口308处的快速产品构造或者单个组件或者单个文件构造,它绕过了树扫描和配置器步骤402和706。当源代码库树以前不曾被处理过时,使用新的源代码树入口312,由此使得不必要执行诸如在图9A和9B中的步骤956和904,这些步骤检查已有的特定文件是否需要被校准(因为很可能没有这样的文件存在)。步骤402要求对整个树的一个扫描(图4)。然后使用到配置器700中的配置产品入口702,它在步骤604要求访问在数据库1800中的数据(图6),然后在步骤3000中配置该产品(细节参见图30)。在步骤204(图2),为设计员产生一个报告,而且产品配置状态数据1900被写出到磁盘存储器中。
趋于这个说明书的末尾处,十分详细地描述了这些宏。这里概括地描述了它们的功能。
程序开发系统100在解决引用和声明之间的从属物中是有用的。程序开发系统100一种能够解决这些从属物的方法是利用宏。例如,在存在有两个具有相同名称的例程、而且这个共同指定的例程正被引用的情况中,宏能够被用来解决从属物。当两个或更多相同组件在一个系统中被使用、且每个组件都具有相同的例程名称时,就能够发生这样一种情况。
为了克服这个问题,使用了用于分支转移代码执行的宏EXTJMP和EXTCALL。在该文件中这些宏必须通过一个PUBEXT公共外部声明宏放在前面。EXTJMP和EXTCALL是用于从在一个组件中的一个例程分支转移到在另一个组件中的例程的宏。两个宏都产生修正数据,被指定用于产品组件链接器(并且被放置到如图38所示的外部段3802中),其中该产品组件链接器列出了EXTJMP或者EXTCALL宏的地址以及将被分支转移到的那个例程的名称(类加上程序名称)。该修正数据被保存在驻留在外部段3802中的中间库内,而且实际上执行该修正数据的产品组件链接器3600能够从该外部段中访问该中间库。由一个EXTJMP或者EXTCALL宏产生的名称和类可以是缺省的名称和类;如果由PUBEXT声明的调用或者跳转具有一个替换的名称和类,则它可以是一个替换的名称和类;或者如果由PUBEXT声明的调用或者跳转是可选的,则该调用或者跳转可以被完全删除,并且不产生修正数据。作为“feature.inc”文件一部分被传递进来的一个数据切换,由产品生成(make)工具基于缺省的程序是否存在而计算出来,在缺省的名称及类和其它两个选项之间切换宏。这样,如果缺省目标不存在的话,就能够获得一个可选的调用目标,或者如果该缺省目标不存在的话,就能够自动地删除该调用或者跳转。
PUBEXT、EXTCALL、和EXTJMP宏全部都能够用名称指定一个组件。然后,如果两个组件包含相同的程序名称,则由EXTJMP和EXTCALL宏产生的修正数据将包含一个组件名称命名,然后产品组件链接器3600将仅仅链接那个调用或者跳转到一个驻留在该指定组件内的程序。以这种方式,就能够解决上述讨论到的名称非单值性。
一个PUBLIC_PROC宏指示在一个组件内的一个程序的位置。这个宏可以接受的参数之一是关键字INTERCEPT,它被添加到由这个程序产生的“修正”数据中。每个公共程序宏都产生修正数据,它包含该程序的名称(类加上名称)、加上它在该目标代码内的绝对地址,而且这个修正数据也标识包含该程序的那个组件。这个修正数据被放置到公共段3804里,从该段3804中它能够由实际上修正该数据的产品组件链接器3600进行访问。
如果关键字INTERCEPT存在于一个给定程序的修正数据中,而且如果有具有相同名称(名称加上类)的其它程序,则产品组件链接器3600将把所有的程序调用(由它们在外部段3802中的修正数据标识的)链接到由该INTERCEPT程序指定的程序,而不是其它相同命名的程序,例如,被分配给了相同类以及可能具有相同组件名称的程序。
以下是宏和系统开发、以及能如何使用宏和能够如何设计系统的更一般讨论。这不是与本发明最佳实施例完全一致的,尤其是并不总是假定该“修正”步骤由一个产品组件链接器执行。当然,修正数据可以以某种中间库的形式被存储下来,而且代码的修正能够以其它方式完成。(利用图11的详细说明再次开始对最佳实施例的描述,它从下面的某些段落开始。)
一个PUBLIC_PROC宏可用于声明一个调度例程。该调度例程是一个起到一个分配器作用的例程,用于分支转移到两个不同的例程。该例程的名称和地址将被保存为修正数据。这个修正数据也被保存在中间库中。在产生最后的二进制映象之前,构造工具删除由这些宏产生的修正数据。
在EXTCALL和EXTJMP宏中除了指定例程名称的自变量之外,在这些宏中的另一个自变量指定用于解决该特定分支转移的组件库名称。用于解决该特定分支转移的组件库名称能够由设计员通过用户界面200指定。设计员能够从用户界面中获取信息以确定哪些组件库能够被指定。做为选择,一个自动化工具(一个向导)能够分析其中找到了公用例程的组件,并且在这些组件之间用一个调度例程为每个公用例程产生一个源代码模板。这个向导将自动搜索公用例程并且简化用于调度例程的编码,而且还提供一种在这些组件之间自动进行调试的方法。
象如每个分支转移的地址、要分支转移到的例程名称、以及该调度例程的名称和地址那样,有关该指定组件库的信息被保存为在中间库中的修正数据,这些数据在产生最后的二进制映象之前被构造工具删除。二进制链接器使用保存在中间库中的所有修正数据,用来自于正确组件库的正确例程的地址来修正该分支转移指令,由此解决了从属物。
通过使用这些宏来解决这样一个从属物,已有的组件例程不需要它属于哪个组件的预先了解,是因为例程被该组件自动地区分,并且在该组件中被编译和链接到该组件库中。已有的组件例程也不需要被重新编译。此外,所有组件例程能够被封装在单个组件库内,并且经由该组件被区分,这增加了代码的封装性。
这些用于解决一个对存在于至少两个组件中的公共命名例程的引用的宏是不需要的。能够使用用于跟踪外部引用(即分支转移)的任何方法。能够使用其它的跟踪机制,例如,一个预处理器、汇编器或者编译器关键字、以及一个定制的链接器。同样地,本发明能够使用用于跟踪公共声明的任何方法。能够使用允许跟踪公共声明的任何方法和声明类型(即截取或者不截取)。
能使用该宏的另一种方法是,在可能的解决方案当中,选择在一个构造的对象中未解决的编译引用。对象的名称和它们的位置被保持在一个数据库中。每个文件系统目录仅仅可能有一个对象,而且每个对象目录包含一个COMPNENT.INF文件或者一个FEATURE.INF文件。该数据库可以通过为这样的INF文件扫描该文件系统,或者是通过使用一个API操作该数据库,来更新该数据库。
这些对象能够被明确指定。能够指定然后将为对象搜索哪个目录或者目录列表,它不是为了确定次序,而是为了确定存在或者不存在。检测以一种及时的方式发生,并且能够被自动地处理。能够使用一个数据库或者其它的存储装置。
INF文件包括ASCII文本,其中该ASCII文本包含用来浏览该软件项目以及控制编译过程的属性。此外,BaseClass被用来标识具有相同接口的两个特征并且提供相同的基础功能。通常,没有最终的软件产品可以包含两个具有相同BaseClass的特征。
由于该构造能够用于很多类型的目标硬件平台,因此把这些平台分类成为一般的类别、诸如BasicPC、Notebook或者嵌入式是有用的。有可能为这些平台类型中的每一个指定缺省的行为,该行为然后能够由设计员人工地改变。这些缺省行为之一是一个“OnDemand”属性,它指示如果存在有由另一个对象对该对象的引用,则该对象将被包含在该最终软件产品中,其中具有相同BaseClass的另一个对象没有被系统设计员明确地包含在内,而且系统设计员已经指定了该硬件平台属于列在PlatformType命令中的一般类别。
OnDemand属性能够被放置在一个源文件(而不是一个单独的文件)内。该属性也能够在某些类的主数据库中,而不是在该树中。做为选择,在确定该OnDemand属性是否应当被使用时,该属性能够用于一个或多个平台类型或者根本不使用平台类型。该OnDemand属性能够被链接到任意数量用户指定的软件项目属性(不仅仅是Platform Type)或者根本不链接。该On Demand属性还能够被移动到接口函数本身中(用于函数等级的排除)。
使用宏PUBLIC_PROC和PRIVATE_PROC声明接口函数(即能够在对象之间调用的函数)。这些宏为该函数指定范围及其它属性信息。使用接口函数的对象必须要么和该函数在同一个文件中要么使用一个PUBEXT或者PRVEXT宏声明它的原型。使用EXTCALL宏进行实际的函数调用。在正常编译过程开始之前,配置器700扫描该源文件以便确定所有接口函数的位置以及所有到这样功能的引用。然后,基于平台类型和来自于系统设计员的明确指令,将对接口函数的引用列表和接口函数声明的列表进行比较。当存在一个没有声明的不可选的引用时,这被认为是未被解决的。
不使用宏就能够完成对未解决引用的检测。能够使用标准方法,这些方法包括留下这种检测直到编译链接阶段为止。它还可以通过使用库和它们的属性的一个列表,被使用在稍后和动态载入库的捆绑中。
此时,检查被列为OnDemand的所有对象,以查看包括它们是否将解决一个或多个未解决的引用。如果是这样的话,则包含该对象。在正常编译开始之前确定一个对象将被包含在最终软件产品中。这通过从编译过程中在该对象中包含或者排除该文件来完成。对于某些对象来说,其中包含或者排除了所有文件。对于其它对象来说,这在一个文件接一个文件的基础上完成。在两种情况中都修改了make(生成)文件。当具有相同BaseClass的两个组件都被标记为OnDemand、而且它们两者或者其中一个将解决一个未解决的引用时,将检测到一个错误状态。虽然更可取地是在编译之前完成,但是做为选择,在最终生成产品中包含一个对象的确定,能够使用链接阶段捆绑或者运行时期捆绑来完成。
在编译之前解决引用的这种方法允许该对象的一个开发者确定默认时应当包含哪个对象。这降低了错误的机会并且提高了生产率。由于所有对象和所有从属物的预编译知识把要汇编的文件数目限制到准确的最少数,所以它还允许更快的构造。
基于正被引用和声明的对象的版本公布,这些宏还能够被用来解决从属物。宏PUBLIC_PROC被用来声明公共的函数接口。在这个宏中的一个参数是以x.y形式的一个版本号,其中x是主要版本号而y是次要版本号。
增加主要版本号表示该接口的一个更新修订版,它不是和输入、输出及/或边界效应向后兼容的。增加次要版本号表示该接口的一个更新修订版,它和具有相同主要版本号和更低次要版本号的接口版本是向后兼容的。这表示由更低次要版本号期望的所有输入和输出、以及相似的边界效应都被支持了。然而,新的输入可以产生新的输出和不同的边界效应。这个版本公布方案仅仅是许多可能方案中的一个,这些可能方案包含非数字、单一版本号、以及其中一个是当前版本而另一个是向后兼容版本的双版本号。
宏PUBEXT用来声明对一个公共接口的引用,该接口可以是函数或者数组。参数之一包含调用者期望的版本号。该版本号的格式相似于PUBLIC_PROC和LIST_CREATE宏的版本格式。如果调用者和被调用者在主要版本号中不同,或是如果调用者具有一个比被调用者高的版本号,则产生一个警告。
访问该数据库以确定“被调用者”的位置和它的版本。使用DBUPDATE(数据库更新)工具更新在该数据库中的信息,当激活该工具时,它在每个对象的所有源代码文件中扫描先前描述的宏,并且在该数据库中放置接口的名称以及它的版本。通过扫描PUBEXT以及在数据库中记录调用者的位置和版本,它还查找对这些接口的引用。
然后,为每个调用者搜索数据库以查看版本是否和被调用者兼容。如果调用者的主要版本号和被调用者相同而且被调用者的次要版本号大于或等于调用者版本号,就认为版本是兼容的。这个信息能够被显示、输出到一个文件中以便向设计员通知任何潜在的不兼容性。
数据库不是必需的,而且扫描过程根本不需要使用一个数据库。相反地,版本信息能够作为由一个预处理器或者一个编译器的特定版本处理的一个特定关键字被添加到该数据原型中。例如,在C语言中,函数的版本号能够被编码作为在该函数原型中的一个_-style关键字。
此外,版本号被附加到调用者和被调用者上的确切方式能够随着从编程语言到编程语言的变化而变化。例如,在C语言中,如果使用了宏MASM,则它能够被附加到函数原型上。对于其它实施例来说,能够使用一个外部文件来附加版本。该版本公布还能够应用于静态变量或者数据结构。
这个版本公布使用通过跟踪在输入参数中的语义变化(程序错误修正-修改的参数定义),允许大的软件项目被更独立地构造。它还在编译和运行时间之前给出了关于该软件项目是否可能工作的改进反馈。因为通过检查版本号可以容易地识别出功能的变化,所以版本公布还可以降低错误。
宏的另一个使用是截取对第一例程的一个调用,并且用第二例程取代对第一例程的调用,这就是截取例程。首先,使用了两个用于分支转移代码执行的宏EXTJMP和EXTCALL。EXTJMP和EXTCALL是用于在组件之间跳转或调用例程的宏。两个宏都产生修正数据,该数据列出了每个调用和跳转的地址以及将要被调用的例程名称。该修正数据被保存在中间库中,而且在构造工具产生最终的二进制映象之前被删除。
截取了一个对另一个例程调用的一个例程应当具有与将要被截取的例程相同的名称。截取例程使用宏PUBLIC_PROC,并把关键字INTERCEPT指定为一个宏参数,将其本身声明为一个接口例程。宏PUBLIC_PROC产生修正信息,该信息列出了截取例程的地址、该截取例程的名称(和原始例程相同)、以及该例程被用来截取另一个例程的属性。同样,该修正数据被保存在中间库中,而且在构造工具产生最终的二进制映象之前被删除。
使用产生的、被保存在该中间库中的修正数据,一个链接工具被用来正确地链接每个分支转移并且产生最后的二进制映象。如果一个例程没有被截取,则被调用例程的地址直接为在启动该分支转移的组件中的分支转移指令进行修补。然而,每当存在截取例程时,将修补该截取例程而不是原来被调用例程的地址。
虽然修补了该截取例程的地址而不是原来被调用例程的地址,但是从该截取例程内部、使用宏EXTJMP和EXTCALL,能够可选地分支转移到原来的被调用例程。通过使用在该中间库中的修正信息来正确地链接该分支转移指令到原始例程,链接工具将能执行这个。此外,如果截取例程不调用原来被调用的例程而且在最终二进制映象中没有其它代码引用它,则能够可选地删除该原来被调用的例程。
这个截取处理能够扩展到用引用的变量替换被调用例程。它还可以扩展到允许在同一个组件内的例程之间的调用也被截取。能够修改该处理过程,以允许截取例程名称不同于被截取的例程名称、即原来被调用的例程名称。这将仅仅需要一个替换和单独的机制将该截取例程和调用者例程进行连接。
借助于这个截取处理过程,调用能够直接链接到它们的例程而不需要间接指示。此外,调用者不需要预期或者了解截取一个调用的任何潜在例程。调用者仅仅把它本身声明为其它任何程序。如果原来被调用例程从未被调用或者引用的话,则该处理过程也不需要原来被调用的例程处于该最终映象中。
从该最终二进制映象中对一个截取的例程清除,通过清除未被使用的代码,允许更有效地利用空间。这个效率能够被扩展到清除做出不必要调用的代码。当组成一个项目的所有源文件都存在时,一个扫描和更新工具为引用在其它文件中的声明的特定宏,扫描每个项目源文件。两个分支转移宏EXTCALL和EXTJMP使用宏PUBEXT和PRVEXT来声明所有的引用。扫描工具将扫描PUBEXT和PRVEXT宏。然后该分支转移指令涉及(经由PUBEXT和PRVEXT)的声明名称,连同该源文件名称和位置一起由该扫描工具记录到一个数据库里。
这两个分支转移宏EXTCALL和EXTJMP需要两个BIOS外部声明宏的一个:PUBEXT或者PRVEXT。该宏具有一个属性字段,其允许该宏声明对该转移声明的引用是″可选的(optional)″。为了从最终二进制映象中清除不必要的代码,如果该转移指令引用的声明是可选的而且定义该声明的源文件不在该构造中,则将不会编译该转移指令。
每个转移都和它的公共声明一致,该公共声明在另一个文件中。对于每个声明引用来说,有一个标记表示一个特定声明是否存在于该构造中。将不会为不在一个项目源文件中的任何声明引用产生一个标记。该标记被保存在一个包含文件中,以由该宏在编译期间提取。
两个转移宏EXTCALL和EXTJMP将解释由扫描工具产生的数据(并且经由该包含文件传递)以及可选地产生用于编译的必须转移指令。如果该声明不在该项目中而且使用宏PUBEXT或者PRVEXT把该转移标记为可选,则将不会产生转移代码。如果用于该转移指令的声明被解决了,则宏EXTCALL和EXTJMP也提供一种机制,以插入要被编译的附加代码。相反地,如果用于该转移指令的声明不被解决,则能够删除除了该转移指令之外的附加代码。
这个处理过程能够扩展到用引用的数据类型替换被转移的例程。使用的机制和用于代码转移的机制是一样的。此外,在这个处理过程实现中讨论的宏不需要用于它的实现。代之以使用宏,当项目被拼接时、而不是恰好在编译之前,通过动态地扫描该声明,能够实现该处理过程。用于宣告声明和记录声明引用的宏,能够被由编译器或者其他诸如一个预处理器工具解释的关键字代替。也如上所讨论,一个不同于正规数据库的不同方法可用于记录该声明和它们的引用。除了其他记录数据的方法之外,能够使用一个为信息而被分析的单个文件。此外,一个不同于一个包含文件的机制可用于传递该标记。
这个删除可选转移代码的处理过程,使用该系统的先验知识,允许在源代码编译之前删除代码,其减少了编译时间。除了该声明本身之外删除该声明引用不用一个存根就可完成。该处理过程还跨越多个转换单元操作。
声明和引用的解决以及版本控制的使用还可以应用于标志。类似于程序即、例程,PUBLIC_PROC和PRIVATE_PROC宏用来声明每个标志定义。由PUBLIC_PROC或者PRIVATE_PROC宏定义的标志可以用来解决公共或者私有标志引用。每个标志定义包含该标志的名称、该标志的位置、该被定义标志的版本。PUBEXT和PRVEXT宏用来声明每个标志引用。每个标志引用包含该标志的名称、该标志的位置、该被引用标志的版本。
一个验证工具用来验证每个标志引用。该验证工具的功能能够和另一个工具,诸如编译器或者集成开发环境,集成。该工具保证每个标志引用具有一个相应的标志定义。该工具然后为每个标志比较版本信息。如果一个被引用的标志不存在或者如果该被引用的标志具有一个错误的版本,则该工具将报告一个错误。一旦所有标志引用都已经被解决了,则该验证工具将报告每个标志引用的解决状态。能够为每个标志报告解决状态以在构造处理过程的调试中给予帮助。
这个处理过程,通过在执行费时的构造处理过程之前快速地检测和校正所有与构造有关的标志解决错误,允许执行该构造处理过程的设计员节省时间。它还不需要预先构造在该软件产品代码库外部的库或者组件,以便检测与构造有关的标志解决错误。
在程序开发系统100中,该主要数据结构被称作一个“列表”。一个列表是一个固定尺寸单元的数组,它的入口可以由任何源代码文件增加。列表必须使用一个LIST_CREATE宏创建一次。这指定了该列表名称以及每个列表入口的尺寸。列表入口被添加到组中。组以一个LIST_START宏开始并且以一个LIST_END宏结束。每个列表入口都被分配了一个名称。
对于包含替换列表入口的组来说,在LIST_START宏上的一个额外参数指定了越权优先级。该越权优先级应用于在该组内的所有列表入口。如果该软件项目包含两个具有相同名称但是具有不同越权优先级的列表入口,则保持具有较高优先级的列表入口而放弃另一个。两个具有相同名称和优先级的入口是一个错误情况。
二进制链接器创建最终列表,该列表包含所有的列表入口。该二进制链接器发现所有的列表入口。对于那些具有相同名称的列表入口,它比较它们的越权优先级。保持最高优先级入口且放弃其它。用于一个特定列表的列表入口被连续地放置,只要给定一个地址,就能够解决所有对该列表以及它的入口的引用。
这个列表处理过程能够和任何静态的、已初始化的数据结构一起使用。该列表能够使用不同的关键字来创建和初始化该数据结构,或者只要能够标识该替换数据结构,就什么都不使用。越权等级号能够从一个简单的一级变化到n级,n是一个大于一的整数。能够由正常的链接器乃至编译器执行列表的合并。
使用该列表过程,能够正常地创建数据结构。此外,能够完成超过一级的替换,其允许“核心”、“产品线”和“平台”的区别。
程序开发系统100还提供了一个机制用于基于在该构造内其他库的存在,在该构造中包含库。一个加载库是一个类似于现有技术加载库的动态触发加载库,这是因为该库的整个代码集都被包含该构造中。一个检索库是动态触发的加载库,其提供一种类似于现有技术搜索库的机制,用于在该构造中有条件地包含代码。在这两个类型库之间的差别在使用的引用类型中可以看到。
搜索库使用一个″前向″引用在一个构造中包含该库代码。例如,如果库A取决于在搜索库B中的一个对象,则来自搜索库B的对象代码将包括在该构造中。另一方面,动态触发的加载库,使用一个″后向″引用以在一个构造中包含该库代码。例如,库B将声明当库A在一个构造中时,它应当被归入该构造中-即使库A没有在库B上的从属物。
需要三个东西来实现该动态触发的加载库:一个配置脚本、一个触发指令、和一个构造脚本生成器。一个配置脚本是标识哪些模块被包含在该最终产品中所必需的。这可以是一个简单的MAKEFILE,或者可以是一个简单地列出该模块名称的定制文件。
一个“External Trigger(外部触发器)”命令与基于外部条件要被加载的库有关联。例如,一个特定文件(ModuleY.INF)能够与该触发的组件有关联。该包含一个External Trigger(外部触发器)命令的INF文件指示:例如,如果已经包含了“ModuleX”,则“ModuleY”应当包含在最终产品中。虽然在这个实例中的触发声明在一个INF文件内做出,但是该触发声明能够包含在该库代码内的任何地方。该脚本生成器的职责简单地是定位这些声明并且恰当地使用它们。
该构造脚本生成器的主要任务是生成一个用于构造该可执行产品的MAKEFILE(或者适当的编译器/链接器脚本)。该生成器使用所有潜在库的INF文件和配置脚本作为输入。在该脚本生成阶段,该生成器基于外部触发器,将确定该库的任何一个是否应当包含在最终构造中。一个MAKEFILE的使用假定使用了利用这样一个脚本的工具。然而这不是一个要求,而且可以用任何厂商的构造工具代替以获取相同的效果。
动态触发加载库的使用提供了这样的功能:在一个产品中包含库而不需要直接修改该触发的模块代码或者构造脚本。当库数目和在模块中的从属物增加了时,还发现动态触发加载库的一个好处。例如,当一个设计员从400种可能的选择中选定包含20模块到一个软件项目构造里时,很难知道可能存在什么“后向”引用库。该外部触发加载库解决了这个问题,因为该后向引用库将把它们自己带入到该最终产品中。
在程序开发系统100中,一个工具能够扫描一个系统的源代码文件以检测和记录公共声明和外部引用。公共声明和外部引用是可在该源代码文件中扫描的关键字。创建将用作源代码库(与假定在该构造中的那些文件相反)的一个源文件列表。
如上讨论,一个工具能够解决对在该源代码中检测到的公共声明的外部引用。类似于一个链接器,该工具首先在假定在该构造的文件中发现对外部声明的引用。它试图利用假定在该构造中的文件来解决它们,继之以在库中的文件。这是个递归过程;纳入该构造的一个文件或者模块可以引用其他文件或者模块。这个解决处理过程需要输出将属于该构造一部分的源代码文件结果列表。能够续之以正常的编译和链接,而不需要创建目标库。
在产生的列表中,文件能够列在一个makefile、批处理文件、或者命令行应用程序中,类似于它为目标库的创建所做的。一个集中式列表能够列出一个项目的库文件。对公共声明外部引用的解决能够在开发和构造的交替阶段完成。它能够在编辑一个源代码文件期间动态地完成,用于向开发者提供实时反馈,或者它能够在单个文件编译之后完成,使用编译输出来提供公共和引用信息。此外,能够进行要编译和链接的目标模块的列表以形成用于命令行链接执行的一个批处理文件,或者一个列表输入。
该列表和解决帮助节省开发时间。首先,它们帮助防止开发者在调试故障解除期间错误地检查错误的源代码,这是因为实际文件和它们的位置将被列出而且是可查看的。对在一个构造中使用的特定文件的认识还帮助开发者检测遗漏了的问题特征或者添加的不希望有特征的位置。开发者还在构造该系统之前获得未解决引用的即时反馈。这个节省了开发时间,因为一般仅仅在构造处理过程结尾处当链接完成时,报告未解决的外部访问。
程序开发系统100通过排除指定该包含文件位于哪儿的需要,还向包含一个特定特征类文件的源代码提供了灵活性。在用于程序开发系统100的源代码文件中,能有一个宏类和一个包含文件的文件名。该包含文件列出它在一个宏内的类信息。在编译之前,由一个系统工具扫描该源代码文件,并且确定该恰当包含文件的位置。
该系统工具源代码文件包含一个具有静态、系统确定名称的本地包含文件。这个包含文件在编译该源代码之前由该系统动态创建。该源代码文件在这个宏被列出之前,列出一个本地的固定名称包含文件。
使用该系统扫描工具,将在编译之前,为上述定义的宏扫描该软件系统的源代码树。系统配置工具使用从扫描该系统中检索的信息,并且使该文件的类信息与发现的包含文件一致。该系统工具产生一个对于该源代码文件是本地的包含文件。产生的本地包含文件提供了宏扩展以指定该包含文件的物理位置。该系统工具还利用该包含从属物的恰当位置,动态地创建makefile。
为了保持对位于不同位置的包含文件变化的控制,能够使用一个版本控制方案,在那儿源代码文件和包含文件都把该包含文件的版本列为它们宏的参数。该系统工具验证它们是否是兼容的。
使用这个系统,该源代码不必须知道将使用哪个包含文件,而且该系统的一个部署不需要人工地指定它。这在具有包含文件、或者多个版本特征(更新...)在不同位置处的多态特征中是有利的。该系统工具自动地把该包含文件解决为适当文件。该类信息阻止同名的一个包含文件的多个实例成为一个问题。
以下描述提供了程序开发系统100的一个更详细描述。图11给出了程序开发系统100的一个概述,其强调在例程(图中心)和管理该图形用户界面200的设计员之间流入、流出、以及来回流动的信息流(图的右侧),并且流入最终产品1106中(图的左下角)。数据流由双线箭头指示,而例程指令路径由单线箭头指示。在图11以下给出的描述主要着重于本发明的数据、数据结构、和数据流方面。最初,组件源代码库1200在诸如一个固定盘驱动器的一个媒体上的一个目录内部进行设置。在该库目录内,子目录被分配给该软件产品的每个组件。在每个组件的子目录下面,为特征建立子-子目录,每个特征都包含一个或多个对应于该特征的源代码文件,而且在第一个层特征子目录下面的进一步子目录可以定义子特征,等等。每个组件子目录还包含一个“component.Inf”文件1400,其定义了将如何编译和链接一个特定组件,它可以、必须、或者不能用于什么类型平台,等。每个特征子目录还包含一个″feature.inf″文件1600,其在其他的东西当中,定义了将如何编译和链接一个特定组件,它可以、必须、或者不能用于什么类型平台,等等。由这些文件支持的选项将结合以下给出的图14到17的描述,进行更详细地描述。
数据库更新例程400扫描所有这些文件并且构造数据库1800,其然后包含从传递给所有特定宏调用的参数中提取的信息,加上从″feature.inf″和″compnent.inf″文件中收集的全部信息,其中这些宏插入在源代码文件中。这个数据然后能够由配置器程序700访问。特别地,该数据库系统被这样设计和构造,以便它能够回答以下问题:什么是组件?什么是特征?对于一个对象(组件或者特征),什么是它的从属物,包括函数从属物(跳转、调用、等)、选项、和包含文件从属物?什么是它的接口、包括程序、标志、和列表?什么是它的选项?什么是它的文件?什么是它的细节?它能够给出一个组件及/或特征列表,它们在最终产品中的包含由一个特定的触发器类型触发,这些类型诸如:一个外部触发器(如果Y在里面则X必须在里面);推荐触发器(推荐由服务器使用);以及″按要求″触发器(因为组件Z需要它的存在,所以它必须在里面)。它能够确信一个文件(通过名称、路径、数据以及时戳标识)存在。它还能够给出关于由名称标识的一个特定选项的消息。以及最后,它能够为一个指定选项给出一个“Enums(枚举)”列表(或者枚举的数据名称和值)。
该配置器程序700使用从数据库1800得到的信息和从产品配置文件“platform.cfg”2100中得到的信息,创建该配置状态数据,来定义该最终产品的配置。如图32所示,配置器700,其在该最佳实施例中用C++编写,在一个C++RAM类(在C程序设计意义中的单词类)数据结构中保持这个信息。如图所示,任意数量的产品配置3202可以保存在这个RAM数据结构中。每个这样的产品配置可以与任意数量的类3204(在本发明的意义上),组件3206、和特征3208链接。类3204还可以与任意数量的组件3206和特征3208链接(注意:如果组件不与源代码文件有关,它们通常不是这样,则不需要向组件分配一个类)。每个特征3208可以和任意数量的子特征3208链接。组件3206和特征3208可以与文件3214(源代码文件和包含文件)以及选项3210(诸如,在传统的“包含”文件中,正式表示为,例如“STARTDELAY EQU12”,类型的等同体或者显现常数)有关联。在源代码文件3214的情况中,每个文件都可以和任意数量的从属物3216(“包含”、“选项”、宏、和函数,在那儿函数包含列表、标志、函数调用、和字符串)以及任意数量的接口3218(任何能够被公共地(在组件之间)或者私有地(局限于双亲和兄弟访问)引用的东西,诸如程序)链接。如果一个名称没有声明为是公共的,则在一个源代码文件中的一个名称的“可见性”因此由类首先限制、然后由组件/功能(双亲/兄弟)关系限制。就选项而论,可以可选择地向任何选项分配一个枚举集合3212,如在PASCAL计算机程序中,向每个枚举量分配一个数值,诸如“Fast=3;Slow=2;Off=1”,以给出一个简单的实例。枚举菜单然后可以通过该用户界面呈现给设计员(当在图33E中显示的菜单3338中做出″Modify″选择时)。
在图11中的图形用户界面200在别处进行了更详细地描述。简要概括来说,设计员在206处可以双击表示源代码文件、“feature.inf”和“component.inf”文件的图标并且可以由此编辑任何文件,此后自动发出对数据库更新例程400、配置器程序700、和图形化的配置显示212调用以更新数据库1800、配置状态数据1900、和用户显示(图33A)。在208处,设计员可以使用提供的工具来引用和搜索各个命名系统组件,引用它们以及通过该库导航来寻找它们可以被定义的地方,在这之后,如刚才描述的那样可以查看和修改它们的定义。在210处,利用真实记录在配置状态数据1900(如在图19所示的“X”)中和磁盘驻留产品配置数据文件2100“platform.cfg”中的变化,设计员可以调用该配置器程序700来修改该最终产品配置。所有这样的变化,再一次,依据该图形化的配置显示212被显示出来。
最后的用户命令是在图11中的用户构造请求指令214。如先前结合图7进行描述的那样,这个指令导致用户-选定和系统-选定配置状态数据(在图20中说明(和图19相比))被提供给产品生成例程800(在图8中概述而在图34中更详细地描述),以首先构造组件生成文件2400和产品生成文件2500,它们一起控制编译和链接的所有方面,以及导致该对应于每个特征和特征从属物(包含或者排除“调用”等等)的接通和断开的特征包含文件2300“feature.inc”被构造或者更新。
当产品生成例程900完成了它的工作时,它在图11中简单地调用一个标准的Unix make(生成)工具来执行该产品生成文件2500,并且由此进入在图10中概述的产品构造例程1000的执行,该例程1000在单个组件生成文件的控制下,调用编译器、汇编器、和链接器为每个组件创建构造产品组件文件1104,并按用于每个单独特征的特征包含文件2300的要求修改该源代码。
最后,调用在图11中的产品组件链接器3600来接受构造产品组件文件1104,从它们中去除包含在特定宏产生段中的数据,这些段用于在该产品组件链接器执行最终目标代码映象的“固定”时控制它,利用把通过名称和类的调用替换为对在ROM映象中绝对地址的恰当调用;利用列出从它们特定段中检索到的组件、其被编组成独立的列表、按指令分类、并且插入到指示的恰当代码段中;利用完全解决的选项;以及利用完全完成的所有其他链接最终步骤;把它们封装在一起到一个完全-链接的、单一ROM映象中。以这样的方式,产品组件链接器产生准备好安装到一个EEPROM或者闪速ROM等等中的最终产品1106。
图12说明了组件源代码库1200的一般结构。这个库在一台计算机或者服务器的硬盘驱动器上、在任意适当的根目录中构造。在该最佳实施例中,所有系统单元都必须驻留在这个根目录的范围之内,该根目录仅仅是由该数据库更新例程400扫描的磁盘驱动器的唯一部分。
能有任意数量的系统组件。每个组件都驻留在分配给该库的根目录内的它自己子目录内。在图12中,文本行的轮廓结构符号化地表示在其中存储了东西的目录和子目录等级,而矩形包围单个子目录以及它们的内容。
因此,在图12中的根目录是源库A1202。在这个源库内的每个东西都由数据库更新例程400扫描。在这个根目录内显示有两个子目录,一个分配给组件A1202而一个分配给组件B1206。每个组件子目录包含一个组件信息文件。组件A的子目录包含一个组件A信息文件1400(其详情显示在图14中),而同样地组件B的子目录包含一个组件B信息文件1210。每个组件子目录还包含一个或多个特征子-子目录。在图12中,组件A子目录包含两个特征子目录1212和1214。如图所示,每个特征子-子目录都包含特征源代码文件1300、1220、1224、和1226以及一个特征信息文件1600和1222。参考特征1子-子目录,它包含特征1信息文件1600,它的详细资料显示在图16中;以及特征1源代码文件A,它的详细资料显示在图13中。
图13给出了一个源代码文件″BEEP.ASM″,一个具有本发明强调的宏调用的汇编语言源文件。这个文件用来说明配置显示(Configuration Display)(图3 3A)。
使用本发明的所有源文件都应当包含“SYSTEM.INC”1306,该文件包含由本发明使用的其他包含文件。在其他的事物当中,这些包含文件包含可用来实现本发明许多方面的特定宏。所有和本发明一起使用的源文件还应当包含“FEATURE.INC”1308,这是由产品构造筹备(Product Build Prepare)(图9)产生的特征包含文件,该产品构造筹备(Product Build Prepare)为每个特征建立一个特征包含文件(图35:建立一个特征包含文件)。如图23所示,由本发明建立、用于特征BEEP的特征包含文件将由BEEP.ASM包含。如将被说明的那样,“FEATURE.INC”包含文件包含宏变量,其控制由PUBEXT 1312和EXTCALL 1318宏产生的代码,这两个宏允许指导设计员控制程序的链接而不用对源代码进行改变。
PUBEXT宏1312声明了具有接口版本1.0、在类TIMER中的一个外部程序DELAY。该宏名称本身声明了该程序是一个由包含在一个分别链接的组件内的PUBLIC_PROC宏定义的程序。这些引用将由产品组件链接器(Product Component Linker)(图36)解决。PUBEXT宏在下面给出的宏逐行描述2.1节中进行描述。
宏PUBLIC_PROC 1316定义了一个在类BEEP中、具有一个接口版本1.0的外部程序ERRORBEEP。该宏名称本身定义了该程序能在用一个PUBEXT宏声明它、分别链接的组件中被引用。宏PUBLIC_PROC在宏逐行描述3.1节中进行描述。如将说明的那样,在编译或者汇编之前,类命名由该宏替换为一个绝对库地址。
EXTCALL宏1318使用在宏PUBEXT 1312中的声明,调用分配给类TIMER的外部程序DELAY。由于这个程序定义在一个分别链接的组件中,对它的引用将由产品组件链接器(Product Component Linker)(图36)解决。EXTCALL宏在宏逐行描述1.1节中进行描述。
宏END_PROC 1320结束由宏PUBLIC_PROC1316打开的程序。它在宏逐行描述3.3节中进行描述。
每个对象,即一个组件或者特征,都具有一个相应的信息文件,该文件能够表示为一个INF文件。这些信息文件的目的是包含由BIOS工具,或者任何正被开发的软件产品使用的工具所需要的、但不能从该树状结构或者汇编文件扫描中导出的信息。一个数据库更新处理过程扫描这些INF文件和汇编文件,来搜集信息并且把它放置到一个集中化的数据库里面。
在每个组件端包含一个组件信息文件(COMPNENT.INF)。在一个组件或者特征目录的每个子目录内都包含一个特征信息文件(FEATURE.INF)。由于COMPNENT.INF和FEATURE.INF文件事实上是相同的,以下描述简单地把它们引用为INF文件,并且仅仅在存在差别的地方区分这两种类型。一般说来,在INF文件中的信息包含对象和相关库或者二进制文件的名称、有关该对象的自由流动描述性信息、该对象所属的类或者子类、以及选项声明。
每个INF文件可以包含一个或多个命令。这些命令更可取地是不区分大小写而且不超过一行。此外,更可取的是每行仅仅存在一条命令。注释可以单独放置任何行上、或者通过在它前面用一个标识符,诸如′//′,放在任何命令行的末尾处。
可以在INF文件体中使用的命令可以是可选的、要求的、或者条件要求的。此外,某些命令可以仅仅用于一个组件信息文件或者一个特征信息文件。在该可选命令当中的一个是BringUp命令。这个命令用来标识该对象应当包含在一个平台BIOS中,其在该PLATFORM.CFG文件中标识为“BringUp”。它利用引导一个主板所需要的最少对象,来帮助快速地配置一个BIOS。当这个命令被添加到PLATFORM.CFG文件中时,仅仅引导一个系统到DOS中所需的对象将被安装在该BIOS中。
Class命令是一个条件需要的命令。它提供了该对象所属的类名称。每个INF文件仅仅允许一个类或者子类。通过它们的函数名前头加以它们的类.子类[.子类...]路径来引用一个对象的公共程序。一个组件不需要声明一个类。然而,如果一个特征的父对象声明了一个类或者子类,则它需要声明一个类或者子类。换句话说,取决于一个特征的父对象是否声明了一个类或者子类,在一个特征信息文件中的一个Class命令是条件需要的。
该Classification命令仅仅应用于组件信息文件,但是为所有组件信息文件所需要。这个命令用于指定那些允许使用例如,BIOS工具,来分类和分类组件的信息。Classification命令包含一个或多个字段名,诸如ComponentType、DeviceVendor、DeviceAlias、PartNumber、和Category。
ComponentType字段名的值要么是硬件要么是软件,并且在该Classification命令中总是需要的。DeviceVendor字段名定义供应厂商并且仅仅为硬件组件类型所需要且仅仅适用于硬件组件类型。DeviceAlias字段名为该组件类型定义一个通常已知的昵称,并且仅仅对于硬件组件类型可选且仅仅适用于硬件组件类型。PartNumber字段名定义了该组件部件号并且仅仅为硬件组件类型所需要且仅仅适用于硬件组件类型。Category字段名用来定义该设备或者软件组件适合的类别,并且对于软件和硬件组件类型都是可选的。
CompileUsing命令是一个可选的命令,其标识在该组件MAKEFILE中、为该指定的扩展而使用的一个定制编译命令,而不是由COMPMAKE产生的缺省命令。这个命令包含三个字段:Command、SourceExtension、和DestinationExtension。Command字段是,例如,一个定制DOS命令,其具有标识特定文件信息应当位于的位置的参数,以及用于其他控制信息的参数。SourceExtension字段提供了应当受到该定制命令影响的源代码文件的一个文件扩展名。DestinationExtension提供了由该定制命令创建的目标文件的一个文件扩展名。
CoreVersion命令是一个需要的命令,其标识该对象兼容的核心版本。这个命令可以包含一个或多个值,这些值每个都表示一个兼容的核心版本。
Description命令是一个需要的命令,并且提供一个可以由高级接口使用的文本注释,以提供有关正被描述的组件、特征或者选项的详细资料。该描述可以例如,最多有512个字符长。
LinkUsing命令是一个可选命令,其标识在该组件MAKEFILE中使用的一个定制链接命令,而不是由COMPMAKE产生的缺省命令。类似于CompileUsing命令,LinkUsing命令包含一个Command字段、SourceExtension字段和DestinationExtension字段,它们提供了和上面所述相同的功能。
Name命令是一个需要的命令,其提供对象的名称。在该Name命令中指定对象名称的一个标识符,可以是例如40字符长的一个字母数字串,而且更可取地是不以一个数字开头,或者不包含空格。
Option命令是一个可选的命令,其声明一个可配置的选项并且给它一个缺省值。设计员能够使用PLATFORM.CFG文件改变该选项的设置。这个指令支持一个用于提供该选项所支持值的描述性名称的“主体”区域。这些名称可以代替数字值使用,用于在该PLATFORM.CFG文件中声明缺省值或者改变值。该值名称应当在一个单独行上定义。不包含该主体区域表示仅仅数字值可被用来设置该值。
除了定义选项名称的名称字段之外,在Option指令中还有几个其他字段。DefaultValueName字段提供了一个在该主体区域中定义的正确的“值名称”,并且当值名称已经在该指令的主体区域中定义了时,它是需要的。Default_numeric_value字段提供了一个正确的数字值,该数字值更可取地是不超过指定的长度。当存在枚举名称时数字值可以不被用作一个缺省值。Size字段指定了该选项空间的大小。RomEditDescription字段是一个选项描述字符串,如果设计员在PLATFORM.CFG文件中选择了“Romedit”,则其被保存在ROM中。ValueName字段是一个描述名称,当设置该选项值时,可以使用它来代替一个数字值。Value字段表示和ValueName关联在一起的具体数字值。ValueDescription字段提供了该值意义的一个文本描述。
Owner指令是一个需要的指令,其提供了该对象所有者的一个公司名称。当向客户站点发行或者复制核心树时,这个指令用于过滤客户的组件。
PlatformType指令是一个可选的指令,其基于PLATFORM.CFG文件的平台类型标识,描述缺省情况下何时一个对象应当被包含在一个构造中。这个指令包含一个或多个PlatformType字段,这些字段每个都具有一个相应的Usage字段。PlatformType字段能够是,例如,BasicPC、Desktop、Server、Notebook、PICO或者AllOthers。
Usage字段用来描述用于在一次构造中包含一个对象的条件。如果它是“Recommended”,默认时对象被包含在其中,但是设计员可以从该构造中人工地删除该推荐的对象。如果它是“Test”,默认时一个对象将被包含在该构造中用于测试目的,但是将被排除在一个产品发行之外。′如果是“OnDemand”,则当需要一个对象来解决硬外部引用时,就自动地引入该对象。对于“Explicit”,一种对象被阻止包含在一个用于该相关联PlatformType的构造中,除非它在PLATFORM.CFG文件中被明确地添加了。“External Trigger”标识将触发一个对象被包含在一个构造中的一个Class.SubClass(类.子类)名称。
一个类可以将“External Trigger”和“OnDemand”或者“Recommended”组合用于单个平台类型。然而,用于单个平台类型的任何其他Usage字段组合都是不允许的,并且将导致一个验证失败。此外,仅仅有一个用于单个类的对象在该核心文件内可以把它自己声明为OnDemand、Recommended或者Externally Triggered。否则,对一个从属物具有超过一个的缺省解决将导致一个验证失败。在单个组件内,仅仅一个特定具体子类的特征可以把它自己声明为OnDemand、Recommended或者Externally Triggered。具有超过一个可以导致一个从属物的多个解决,将导致一个验证失败。
ShieldPrivates指令是一个可选指令,其保护一个对象的私有程序不被它的兄弟对象所访问。这个指令对于被用作各种各样在功能上不相关对象的贮藏室的对象是有用的。图41显示了该ShieldPrivates指令如何进一步限制超过私有访问级别的代码访问。该图说明了在任何特征等级处,对函数调用的访问是如何被封装到它们适当级别中、这些级别是公共、私有或者保护的任意一个。这应用于从属物,包含程序、标志、以及包含。
SubClass指令是一个条件需要的指令,其提供了一个特征所属的一个子类的名称。每个INF文件仅仅为一个类或者子类允许。通过在一个对象公共程序的函数名前头加以它们的类.子类路径来引用它们。如上面关于Class指令所述,一个组件不需要声明一个类,但是如果一个特征的父对象声明了一个类或者子类,则要求该特征声明一个类或者子类。
Target指令是一个可选的指令,其仅仅适用于组件信息文件。这个指令提供了应当从构造该特定组件中产生的一个库或者二进制文件的名称。Target指令包含一个TargetName字段和一个TypeKey字段。TargetName字段定义了一个字符文件名。TypeKey字段是用于标识非标准类型文件的四个字符码。这个代码由BIOSMAKE工具使用,用于修正引用这些文件的调度表。
Uses指令是一个可选的指令,其用于标识由一个被描述对象使用的共享代码位置。构造工具可以在为该对象创建的MAKEFILE中使用这个指令来标识该文件为一个相关文件。共享文件的使用是受限制的。特别地,对象可以仅仅使用标识它们自己为共享使用的文件,这些文件使用,例如,具有“Shared”属性的一个PRIVATE_PROC或者PRIVATE_INCLUDE指令来标识它们为共享。此外,一个对象可以仅仅使用在兄弟目录中,或者上游目录结点的直接孩子中的共享源文件。Uses指令包含一个Filepath字段,该字段提供了由该对象使用的共享文件的相对路径和文件名。
图14给出了用于类CORE 1406的组件信息文件。这是包含特征BEEP(图16)的组件,特征BEEP包含源代码文件BEEP.ASM(图13)。本发明的这个部分包含描述该组件的指令以及在该组件的配置(图15)中使用的指令。BRINGUP指令1412表示,当一个用户使用本发明开始构造一个具有最少功能、以便快速起动的新BIOS时,这个组件应当被包含为该配置的一部分。
PLATFORMTYPE指令1424表示,当构造一个将在一个IA32结构上运行的产品时,可使用这个组件。ALLOTHERS指令1428表示对于所有没有在PLATFORMTYPE指令1424中明确指定的平台类型,这个组件是RECOMMENDED。除非被明确地排除在外,CORE 1406组件将被包含在由本发明产生的、运行在一个IA32结构上的所有配置中。
图15显示了在本发明的一个组件信息文件中、在该组件配置中使用的那些指令。粗体的名称是关键字,而不是粗体的名称由设计员指定。字符″//″表示该行的其余部分是一个注释。所有驻留在一个指令的花括号{}之间的指令被认为是在该指令的范围之内。
PLATFORMTYPE指令1506指定这样的规则,依据该规则,组件将被包含在该配置中。该规则应用于一个用于一个特定PlatformType(平台类型)诸如″DeskTop″或者″NoteBook″或者任何没有明确提及的PlatformType(平台类型)(ALLOTHERS)的配置。规则1516包含RECOMMENDED:除非明确排除在该配置之外,包含组件;ONDEMAND:如果在该组件中的一个程序被已经在该配置中的另一个组件引用,则包含组件;EXPLICIT:只有当被明确地包含在该配置之内时,才包含组件;以及EXTERNALTRIGGER:如果由ClassPath指定的组件或者特征在该配置中,则包含这个组件。
OPTION指令1522定义一个可以在包含一个组件的源代码文件中使用的选项名称和缺省值。它还可以定义可以在该产品配置中指定的选项可接受值名称(图22)。
图16给出了用于类BEEP 1602的特征信息文件。这是包含源代码文件BEEP.ASM(图13)的特征。本发明的这个部分包含描述该特征的指令以及在该特征的配置(图17)中使用的指令。
BRINGUP指令1612表示,当一个用户使用本发明开始构造一个具有最少功能、以便快速起动的新BIOS时,这个特征应当被包含为该配置的一部分。
PLATFORMTYPE指令1616表示,当构造一个将在一个IA32结构上运行的产品时,可使用这个特征。ALLOTHERS指令1620表示对于所有没有在PLATFORMTYPE指令1616中明确指定的平台类型,这个特征是RECOMMENDED。除非被明确地排除在外,BEEP1602特征将被包含在由本发明产生的、运行在一个IA32结构上并且包含CORE组件的所有配置中。
图17显示了在本发明的一个特征信息文件中、在该特征配置中使用的那些指令。粗体的名称是关键字,而不是粗体的名称是由设计员指定的。字符″//″表示该行的其余部分是一个注释。所有驻留在一个指令的花括号{}之间的指令被认为在该指令的范围之内。
PLATFORMTYPE指令1706指定这样的规则,依据该规则,该特征将被包含在该配置中。该规则应用于一个用于一个具体PlatformType(平台类型)诸如″DeskTop″或者″NoteBook″或者任何没有明确提及的PlatformType(平台类型)(ALLOTHERS)的配置。规则1516包含RECOMMENDED:除非明确排除在该配置之外,包含特征;ONDEMAND:如果在该特征中的一个程序被已经在该配置中的另一个组件引用,则包含特征;EXPLICIT:只有当被明确地包含在该配置之内时,才包含特征,以及EXTERNALTRIGGER:如果由ClassPath指定的组件或者特征在该配置中,则包含这个特征。
OPTION指令1721定义了可以在该特征的源代码文件中使用的一个显现常数的名称和缺省值,它还可以为可以在该产品配置中指定的选项,定义容许值名称(图22)。
PLATFORM.CFG文件是一个指定对一个构造的定制的文本文件,并且包含指导该构造的语句。OEM可以在该PLATFORM.CFG文件中包含信息来标识OEM特征、OEM钩子、以及OEM文件越权。此外、虽然PLATFORM.CFG文件由用户界面200维护,但是它是一个可编辑的文件,允许设计员明确地指定配置参数。
PLATFORM.CFG文件包含BIOS的一个最小描述。基于这个信息,配置器700能够导出该BIOS配置的一个更全面描述。例如,如果一个设计员明确地声明一个组件应当被包含在该构造中,则该配置器700能够确定另一个组件或者特征是否也应当被包含在该BIOS中,即使它没有明确地在PLATFORM.CFG文件内进行声明。
有几个与PLATFORM.CFG文件关联的指令。BuildOption指令指定专门用于一个特定软件产品构造的信息。在该BuildOption指令主体内的指令指定要被存储信息的详细资料。这些指令包含Type,指定构造选项的类型、Name,指定正应用该构造选项的入口名称、以及Value,指定一个正设置入口的值。
BringUpBios指令用来指示一个特定的配置越权。这个特定越权指示配置器700构造一个最小的BIOS,该BIOS仅仅包含获得该最小的BIOS所需要的最小单元集合。该BringUpBios指令仅仅可以在该PLATFORM.CFG文件中出现一次。
Classification指令指定平台特有信息。这个信息能够对一系列平台特定数据定义一个名称或者值,包括一个供应厂商名称、一个别名、一个平台号、一个修订版或者版本号、以及一个类别。
Component指令指定从该构造中附加、配置或者删除任何组件,而不考虑打算使用的平台类型。一个组件的配置由在该Component指令内指定的Features、Options、SystemOptions、Files和OverrideFiles定义。当基于指定的平台类型被缺省引入时,该组件没有列在PLATFORM.CFG文件中。
Component指令最好包含一个ForceFlag。这个标记指定一个组件是否被放置在一个构造内、排除在一个构造之外、或者设置为使用缺省的构造包含从属物和触发器。当该标记设置为ForceIn时,它将与任何用于该组件的现有缺省定义合并。当一个组件被设置为NoForce时,它将回复到它的缺省状态,意指它将取决于其他从属物和触发器选择。当一个组件被设置为ForceOut时,它是明确地不包含在该构造内。
每个Component指令还包含一个要被纳入该系统的组件名称。在该指令中使用的名称从该命名组件的INF文件中导出。由于每个组件最好具有一个唯一名称,所以在该Component指令中命名的组件应当没有非单值性。
驻留在一个组件指令花括号内的所有指令,被认为在命名组件的范围内,其中该花括号用来描绘什么被包含在该Component指令中。这些指令的实例包括Feature、Option、和SystemOption指令。组件本身不能放置在其他组件内部。此外,Component指令仅仅能够为每个唯一的组件出现一次。换句话说,不能有两个或更多描述同一个组件的Component指令。
Feature指令允许在一个给定组件内添加、配置和除去一个特征。在该指令中命名的特征必须对它驻留在其中的组件有效。类似于一个组件,一个特征的配置由在该Feature指令内指定的Features、Options、SystemOptions、Files和OverrideFiles定义。此外,类似于Component指令,Feature指令包含一个ForceFlag,指定一个特征是否放置在一个构造内、排除在一个构造之外、或者设置为使用该缺省构造包含从属物和触发器。
虽然所有特征都必须驻留在一个组件定义内,但是特征可以在另一个特征的定义之内定义。当一个特征在另一个特征内部指定时,该内部特征就变成子特征而外部一个就变成了母特征。在一个特征内的所有指令被认为是在那个特征的范围内,而且也在其下面定义了该特征的组件的范围内。能够被放置在一个特征的花括号内部的指令或者语句的实例,包含Feature、Option、systemoption、File和OverrideFile,其中花括号描绘了什么将被包含在该Feature指令中。
File指令允许一个附加文件被包含在一个构造内。这个指令仅仅可以在一个组件或者特征的范围内使用。包含在该File指令中的参数包括一个FileName和一个FilePath。FileName定义了要被纳入一个构造的文件名称。FilePath提供了要被纳入一个构造中的一个文件的相对物理位置。
Option指令指定将用来生成组件和特征包含文件的一个选项的设置。该Option指令仅仅可以在一个组件或者特征的范围内使用。包含在该Option指令中的参数包括一个Name、一个Value、一个RomEditFlag、和一个Description。Name参数定义了一个要改变选项的名称。Value参数设置由该选项在.INF文件中定义的任何正确值。RomEditFlag参数是一个布尔值,其设置一个RomEdit是否为该选项所允许。Description参数是一个可选参数,其提供了可以显示在RomEdit工具中的选项一个描述。
OverrideFile指令越权一个组件文件。如果该越权是陈旧的,则一个文件版本允许向设计员显示一个警告。这个指令仅仅可以在一个组件或者特征的范围内使用。新越权文件的名称必须和被越权文件的名称一致。在OverrideFile指令中的参数包括一个FileName,其提供了该越权文件的名称、一个NewPath,其提供了该越权文件的相对物理路径、以及一个OriginalVersion,其提供了该原有文件的一个版本。
PlatformType指令为该构造指定一种平台类型。这个指令用来基于指定的平台类型,引入缺省的组件和特征。只有一个PlatformType指令可以在该PLATFORM.CFG文件中使用。在该PlatformType指令中的参数包括一个Name,其定义了平台的名称;以及一个Architecture,其由CPU和指令集确定,并且指定一组将执行相同代码的系统。Architecture参数可以是,例如,用于IA-32指令集结构的IA32或者用于IA-64指令集结构的IA64。
SysternOption指令用来建立一个横穿该构造描述的整个范围都看得见的选项。可以在处理过程的不同级别处设置和重置预定义的选项,这些级别诸如是一个全局级别、一个组件级别、或者特征级别。在该SystemOption指令中的参数包括一个Name和一个Value。Name参数给定与该构造描述相关联的SystemOption的名称。该名称必须是一组预定义选项的一个。Value参数设置一个和该命名SystemOption相关联的值。
图18符号化地给出了一个用于一个源库A的组件数据库1800的表示。用于每个组件的数据显示为包含在一个矩形内。显示了两个组件,组件A1802和组件B1804,也假定地给出了其它组件,但是为了简明起见就忽略了。仅仅显示了用于组件A 1802的数据的详细资料。
每个组件都具有一个名称和一个描述(行1806)。每个组件都具有一个数据选项表,其为一个列出所有用户可设置选项1808的表格,这些选项1808会影响在这个组件内的源代码文件。通过用户界面(例如,参见图33E)的使用调整这些选项,而且当链接器3600构造最终产品1106时,该选项值实际上由该产品组件链接器3600(图36)载入到二进制映象中作为该“解决”处理过程的一部分。给出了为一个组件指定的任何编译、汇编、和链接选项1810。
如果一个组件的目录包含源代码文件,则可以由它的“component.inf”文件把该组件分配给一个类,但是本最佳实施例给出的实践是把源代码文件放置到特征子目录中,而且让每个特征通过它的“feature.inf”文件分配给一个类。因此,每个特征都被明确地分配给一个类。如图所示,因此几个特征可以在该数据库内由类组织。显示了两个类,类A1812和类B1814。在类A1812内有两个特征,特征11816和特征21818(没有为特征2显示详细资料)。大概,任何正常的系统都能够具有许多特征,以及子特征等。特征11816具有一个名称和描述1820、一个数据选项表1822(实质上和用于组件的一样但是应用于特征源代码文件)、编译器和链接选项1824(如果该特征源代码文件被分别编译、汇编、及/或链接的话)、特征源代码文件的名称1826、以及到在别处的那些源代码文件的入口1828和出口1830的一个完全列表,更确切地说,调用接口和从属物的完全列表。
图19和20是包含在配置状态数据1900中的数据结构的符号化表示,它们类似于图18所示的数据库进行组织。显示了三个组件-组件A1902、组件B1904、组件C1906,每个都拥有一个由一个有或者没有“X”的表决正方形符号化表示的″选中″或者″未选中″标记,该标记指示一个组件是否被选中或者未被选中包含在该最终产品1106中。用于组件A和B的标记1922和1930显示为具有“X”,指示这些组件当前是最终产品1106的一部分。用于组件B的标记1928显示为没有一个X、指示要么由于缺省的,要么由于系统设计员的介入,这个组件没有被选中。组件A具有一个名称和描述1908,而且它具有两个特征:特征11910,它的标记1924指示它没有被选中;以及特征21912,它的标记1926指示(通过一个“X”)它已经被选中了。特征11910显示为具有一个类分配1914、分配给它的源代码文件1916、选项定义1917、以及引用1919-从属物和接口。(这个在RAM内的数据结构的一个更详细视图呈现在下面的图32中,其已经在上面进行了描述。)
图19简单地说明了当创建一个最终产品1106时,从该配置状态数据中取出选中的组件和特征数据2000,并把它们传送到产品生成例程900。如图所示,用于该选项的全局常量由该产品组件链接器3600向前传送,作为应用于最终产品1106的“解决”数据的一部分。选中的组件A2002和C2004,连同是一个被选定组件的一部分的、每个选中特征的特征数据一起,被向前传送。选中的特征22006相当于在图19中、设置了选择标记1926的特征21912。这个特征22006伴随有它的源代码文件名称2998,以及从那些源代码文件及其他从属物和接口中退出的出口2008,以及分配给特征特有选项的特征特有常数2012。
图21给出了用于一个DeskTop平台2102的产品配置数据(ProductConfiguration Data)。这是包含组件CORE(图14)的配置。本发明的这部分包含在该产品(图22)的配置中使用的指令。
PLATFORMTYPE指令2102指示这个配置用于在一个IA32结构上运行的平台类型(PlatformType)“DeskTop”。所有在它们的组件信息文件中包含一个指定了DeskTop(Rule)或者AllOthers(Rule)的PlatformType(IA32)指令的组件将依据它们的(规则)Rule包含在该配置中。类似地,在被考虑要包含的组件中,所有在它们的特征信息文件中包含一个指定了DeskTop(Rule)或者AllOthers(Rule)的PlatformType(IA32)指令的特征将依据它们的(规则)Rule包含在该配置中。
COMPONENT指令2104允许为组件PNP配置一个附加源文件。
在该配置中,FILE指令2108允许来自在当前组件源代码库中的目录\DEVREF\INTEL\440BX的、附加的源代码文件MYFILE.ASM被包含作为组件PNP的一部分。
图22显示了在本发明的一个平台配置文件中的可能指令列表。粗体的名称是关键字,不是粗体的名称是由设计员指定的。字符″//″表示该行的其余部分是一个注释。所有驻留在一个指令的花括号{}之间的指令被认为在该指令的范围内。
SYSTEMOPTION指令2202用来建立一个选项名称和值,该选项名称和值在该产品配置的任何源代码文件中都是可用的。FEATURE指令2216允许在一个给定组件内添加、删除、或者配置一个特征。由本发明定义的一个特征配置2212,为那些在那个特征花括号{}的开口和闭口内定义的Feature、Option、SystemOption、FileOverrideFile指令。
OVERRIDEFILE指令2216用于在一个组件或者特征指令内使用,通过代之以使用指定的新路径,来越权那个组件或者特征的一个文件。OPTION指令2218用于在一个组件或者特征指令内使用,指定在那个组件或者特征信息文件中定义的一个选项的名称和新值。该选项的新值将出现在为那个组件或者特征生成的特征包含文件中。
图23给出了特征包含文件(Feature Include File)。这就是当汇编源代码文件BEEP.ASM(图13)时,包含的FeatureIncludeFile(特征包含文件)。D_TIMER_DELAY变量就是在图13中宏PUBEXT1312(宏逐行描述节2.1)和EXTCALL1318(宏逐行描述区域1.1)所期望的defineName。
图24给出了用于组件CORE的组件makefile。组件CORE(图14)包含特征BEEP(图16),特征BEEP包含源代码文件BEEP.ASM(图13)。一个makefile,这样称呼是因为历史上生成(make)程序会在当前工作目录中查找一个缺省时名为MAKEFILE的文件,包含由该生成程序解释的指令。
EXTASMS2404被定义为一个包含要被汇编的每个外部汇编源文件路径的宏。在每行结尾处的反斜杠\指示继续。一般规则2436指定了把任何具有一个ASM扩展名的文件转换成具有一个OBJ扩展名的相同文件所必需的汇编器指令行。COMPONENT_NAME规则2440指定将链接来自于目标文件的组件的链接器指令行,其中该目标文件从所有由宏EXTASMS和ASMS定义的汇编源文件中产生。作为一个副作用,它导致不存在的目标文件使用一般规则2436从汇编源中产生。CLEAN规则2456必须明确地在生成程序指令行上指定(图25)。它删除由该CORE组件makefile生成的文件,以便下一次解释CORE组件makefile时,将重新生成所有文件。
图25给出了由本发明生成的产品makefile,其被用于构造包含组件CORE的产品(图24)。BIOS.ROM规则2502进入在该配置中包含每个组件的目录,并且运行NMAKER生成工具程序来解释在那个目录中、由本发明生成的组件makefile。这将为每个组件产生目标文件的一个链接集合、“*.exe”文件。这个格式允许象一个统计工具那样执行该组件,目的是显示声明的公共接口、从属物、以及资源使用。这些链接的文件然后可以由该产品组件链接器“BINLINK”3600合并成的单个ROM可执行文件(图36)。
CLEAN规则2532进入在该配置中包含每个组件的目录,并且运行每个组件makefile(图24)的CLEAN规则,然后进入包含平台配置文件的目录,并且清除在该构造处理过程中产生的文件,使得下一次构造将重新生成所有这些文件。
图26说明了扫描该组件源代码库1200的数据库更新例程400。该搜索开始2602在该组件源代码库1200的根目录寻找组件,这些组件是包含一个名为“COMPONENT.INF”的组件信息文件2604的根目录子目录。调用文件扫描例程2700,为每个组件2606扫描该组件信息文件2610以及可能在该组件目录中的任何源或者包含文件2612。该搜索然后继续在该组件目录中寻找该组件的特征,这些特征是包含一个名为“FEATURE.INF”特征信息文件2614的、该组件目录的子目录。调用文件扫描例程2700,为每个特征2616扫描该特征信息文件2620以及在该特征目录2622中的源或者包含文件。
图27显示了文件扫描例程2700。当由该数据库更新例程(图26)调用来扫描一个文件时,该文件扫描例程从数据库2716中获取要被扫描的文件最后被修改的日期与时间,并且把它和来自该文件本身2702的最后修改日期与时间进行比较。如果该文件没有改变,则数据库不被更新2704。如果该文件已经改变了或者该文件扫描例程由变化输入例程206(图11)调用,则扫描该文件2706。如果该文件是一个名为“COMPNENT.INF”的组件信息文件2708,则把该组件信息2709添加到数据库2716中。如果该文件是一个名为“FEATURE.INF”的特征信息文件2710,则把该特征信息2711添加到数据库2716中。否则,该文件是一个源或者包含文件2712。把在该文件中,来自任何退出声明宏、入口宏、包含宏和列表宏的参数的附加信息添加到数据库2716中2714。
图28显示了配置器程序2800的一般流程,其从初始启动2900开始(图29)、接着通过产品配置3000(图30),并结束于指示一个正确配置(图33A)或者不兼容的接口、遗漏组件等等(图33B)的一个配置状态报告2806。
配置器程序2800的初始起动2900始于从产品配置数据2100中检索平台类型2102。然后它从数据库1800中读取604与允许或者强制在该指定平台类型上的组件有关的所有组件信息,并且在随机存取存储器中创建该产品配置器状态数据1900。该产品配置器状态数据1900包含每个特征的源文件以及在那些源文件中的每个PUBLIC_PROC宏和PUBEXT宏的参数。当每个特征都由该产品配置例程3000激活(3004、3008、3010、3014)时,在它的源文件中被每个PUBEXT宏引用的程序被添加到一个未解决引用列表中。该产品配置例程3000进行以下步骤,注意3002不激活那些已经指定为排除在外的任何对象(3335、2204、2210、2208)。
在步骤A3004处,在该产品配置器状态数据1900内把那些已经被指定为包含在内(3333、2204、2210、2208)的所有对象(组件或者特征)以及它们的双亲设置为活动状态。在步骤B3006处,在该产品配置器状态数据1900中把所有推荐的组件对象(1510、1514、1516)设置为活动状态。在步骤C3008处,为在该产品配置器状态数据1900中的所有活动对象,设置所有推荐的子对象(1710、1714、1716)为活动状态并且重复这个过程。在步骤D3010处,对于具有一个指定为一个外部触发器(1518、1718)类的每个组件对象或者一个活动对象的子对象,如果那个类的一个对象在该产品配置器状态数据1900中是活动的,则该外部触发的对象被设置为一个活动状态。在步骤E3100处,解决外部引用(图31)并且维持一个未解决引用和解决了引用的不匹配版本的列表。在步骤F3014处,如果一个特征解决了一个未解决的引用且是请求的(1716)且所有的双亲对象都是活动或者请求的(1516、1716),则在该产品配置器状态数据1900中把该对象和所有父对象设置为活动状态并且重复步骤C、D、和E,直到没有更多的对象能够被设置为活动或者没有引用未被解决为止。
该解决外部引用例程3100从一个未解决引用列表中获取由一个PUBEXT宏(宏逐行描述节2.1)声明的一个程序引用并且发现所有由PUBLIC_PROC宏(宏逐行描述节3.1)定义3102的、具有一个匹配名称的程序。匹配的PUBEXT宏的name(名称)参数和宏PUBLIC_PROC的procedurename(程序名称)参数都是类路径,其包含由句点隔开的一个分类名、零或更多子类名称以及实际的程序名。该类路径用来在一个组件、特征和子特征分级结构中标识一个特有的程序,其与在该组件源代码库1200内包含它定义的源文件位置无关。该类路径不与在其他组件中具有相同名称的程序冲突,因为它们将具有一个不同的类路径。如果有具有相同类路径3104的多个定义,以及如果该定义的PUBEXT宏指定了一个组件名称3106,则它选择在该命名组件3108中的定义。此外,如果一个定义的PUBLIC_PROC宏指定了关键字INTERCEPT3110,则它选择那个定义3112。否则,它从该未解决引用的列表中删除该引用并且返回一个发现多个定义3114的指示。如果发现了一个匹配的定义3116而且该定义是在一个活动特征3118或者一个指定为请求(1716)的不活动特征3122的源文件中,从该未解决引用列表中删除该引用并且返回成功3120。如果该引用的PUBEXT宏指定了关键字ALTERNATE 3124,使用由该altname参数指定的类路径3126并且重新进行尝试3128。如果该引用的PUBEXT宏指定了关键字OPTIONAL3130,则定义不是必需的,且从该未解决引用列表中删除该引用并且不返回定义3132。否则,从该未解决引用列表中删除该引用并且返回不匹配3134。
刚才描述的图30和31,给出了该配置处理过程的一个通用算法以确定该产品的活动特征。
图32已经在上面图11的环境中进行了讨论。
图33A给出了当一个设计员使用本发明来修改在用于IA32结构3308的“Desktop”平台的“POST Services”组件3306的“DecompressManager”特征3304中的源文件WORKADDR.ASM 3302时,将看到的视图。这是使用在图33F中描述的图标来显示组件和特征的一个组件源代码库的一个逻辑视图(图12),其与一个显示目录分级结构的组件源代码库的物理视图相反。图标显示“Fdisk”3310和“kcManager”3312组件已经被排除在该构造之外,而组件“Inte1371ab”3314和“Inte1440BX”3316已经包含在该构造内。
图33B给出了当使用本发明时、一个设计员将看到的一个组件源代码库的逻辑视图,该组件源代码库和在图33A中的相同,然而组件“Fdisk”3310不再排除在该构造之外。该图标(在图33F中描述)指示组件“Fdisk”3310、特征“ata”3318和文件“FDSKINIT.ASM”3320具有错误,以及用于在类“fdisk”中的函数“protocolTable”3322和在类“pic”中的函数“SendEOI”3324的公共函数从属物具有错误。
图33C使用在图33F中描述的图标,给出了在图33A和33B中显示的组件源代码库的另一部分的一个逻辑视图。这个逻辑视图显示当使用本发明的一个系统设计员通过右键点击在组件“Inte1440BX”3330的特征“Memory Configuration”3328中的越权文件“EARLYCFG.ASM”3326时,将会看见的东西。它也显示文件“oemfile.asm”3332是一个定制文件,其使用如图33D所示的本发明窗口的“Add Custom File”行进行添加。
图33D使用在图33F中描述的图标,给出了在图33A和33B中显示的组件源代码库的一部分的一个逻辑视图。这个逻辑视图显示了使用本发明的一个系统设计员通过右键点击已经被排除在该构造之外的组件“Fdisk”3310将会看到的东西。
图33E使用在图33F中描述的图标,给出了在图33A和33B中显示的组件源代码库的一个不同部分的一个逻辑视图。这个逻辑视图显示使用本发明的一个系统设计员通过按右键点击在组件“Intel440BX”3330中的选项“CacheLineSize”3336将会看见的东西。选项“CacheLineSize”当前具有十六进制值04。这个窗口允许该系统设计员修改该当前值或者把它重置为在该组件信息文件中指定的缺省值。
图33F给出了出现在如图33A到33D中所示的、本发明一个组件源代码库的一个逻辑视图中的图标。每个图标表示该逻辑视图的一个不同单元并且当该单元不被包含在BIOS配置中时具有一个较浅的颜色。用于归入到该配置中的组件和特征的图标显示为一个复选标记,而用于排除在该配置之外的组件和特征的图标具有一个较浅颜色而且显示为具有一个斜杠贯穿它的圆圈。具有错误的单元显示为具有一个x的图标,而具有警告的单元显示为具有一个包含一个感叹号的三角形图标。
图34显示了产品生成例程800。对于在该产品配置器状态数据1900中的每个活动组件3402,该例程为该活动组件的每个活动特征3404,构造一个特征950(图35),然后它为在该当前特征3406中的每个源代码文件添加一条指令到当前组件3408的组件“make”文件中,来说明如何编译该源代码文件。当该当前组件的所有活动特征已经被处理过了时,添加一个指令到当前组件3410的组件“make”文件中,说明如何进行链接以形成一个BIOS组件。当所有活动组件已经被处理过了时,创建一个产品“make”文件(图10),该文件包含用来执行每个组件“make”文件的指令加上一个执行该产品组件链接器908的指令。然后调用该生成(make)工具程序执行在产品“make”文件1000中的指令。
图35显示了构造特征包含文件例程950。该例程为在该特征3502的每个文件中的每个PUBINC宏(宏逐行描述节6.2),从它的classpath参数3504中产生一个I_CLASSPATH符号,然后添加一条把该I_CLASSPATH符号定义为包含该包含文件3506的目录路径的汇编语句。例如如果宏PUBINC的classpath参数是″post.dispatcher″,则该PUBINC宏将期望定义名为I_POST_DISPATCHER的I_CLASSPATH符号。当所有的PUBINC宏已经被处理过了时,该例程为在该特征的每个文件中的每个PUBEXT宏3508,从该名称(name)参数中产生一个D_NAME符号。如果由该名称(name)参数指定的公共程序被包含在该构造中,则该例程添加一条把该D_NAME符号定义为TRUE的汇编语句3514(图23),否则添加一条把该D_NAME符号定义为FALSE的汇编语句;而且如果该PUBEXT宏指定了关键字ALTERNATE,就从PUBEXT宏的altname参数中产生一个D_ALTNAME符号以及添加一条把该D_ALTNAME符号定义为TYPE_RESERVED_TRUE的汇编语句。例如,如果该PUBEXT宏的name(或者altname)参数为“timer.delay”1312,则宏PUBEXT将期望定义一个名为D_TIMER_DELAY的D_NAME(或者D_ALTNAME)符号。
图36给出了产品组件链接器3600的一个流程图,该链接器3600是一个分配了符号名称″bin_link″的例程。它接受当调用常规链接器把由编译器和汇编器产生的“*.obj”目标代码文件链接在一起时产生的“*.exe”可执行二进制文件作为输入数据。它还接受由该常规链接器产生的“*.map”文件为输入,以及从它们中获悉产生的代码段名称以及它们驻留在该“*.exe”文件中的位置。它还直接从设计员中接收一个或多个脚本命令文件“bios.scr”,该命令文件包含有关它将如何处理不同可执行程序的指令--段以什么次序占据最终的ROM映象、分配绝对地址到某些段等。在该最佳实施例中,在所有的可执行映像中解决了地址等之后,以及在把从该可执行映像中提取的各个命名段块结合在一起之后,产品组件链接器“BINLINK”3600(图36),不把该可执行映像组合在一起以形成一个统一的ROM映象,并且执行如在必要处压缩可执行映像和复制映象这样的任务。这些任务由一个名为“rom_image”的例程执行,该例程从“bin_link”接收输出文件“bios.scr”,然后执行这些最后的任务,以及把声音和图像文件集成到实际上最终ROM映象里的任务。
流向该产品组件链接器3600的输入控制信息显示在图37中,其描述如下。从被包含在该最终产品中的一个组件列表开始,并且限制要检查的“*.exe”文件为那些对应于该设计员选定组件(一般地在该组件子目录中发现)的文件;并且使用从该链接器产生的“*.map”文件中获得信息来定位和分离在每个“*.exe”文件内的命名段;并且通过依据该选定的组件,直接操作“*.exe”文件,该产品组件链接器3600能够在每个“*.exe”文件内识别所有的命名代码段,这些代码段在下文中被称为最终产品1106的″构造组件″。将频繁地发现:指定用于包含在该最终产品单个段内的可执行目标代码和数据将遍及许多不同的“*.exe”可执行文件分布。同样地,一般也将发现:用于控制该产品组件链接器操作、以及此后将被放弃并且不包含在该最终产品1106中的数据也遍及许多不同的“*.exe”文件分布,但是该数据总是放置在两个“解决”数据段中,一个为公用段3804(图38)(“publicSegment”),其包含公共程序的名称、表格、等等;以及扩展段3802(图38)(“externSegment”),其包含所有调用、跳转、读取等等语句的名称,一旦该段和偏移地址由该产品组件链接器3600确定和固定,则这些语句的地址必须由该产品组件链接器通过插入该公共入口点的地址来解决。
因此,在它的第一步骤3602处,该产品组件链接器3600收集所有的构造组件并且按照段名分类它们;合并具有相同名称的段到统一段里(其可能称作″模块″),即使这些段被分别编译和链接;然后链接对该程序的调用、等等,以从由几个不同组件提供的代码段片段中汇编来创建统一的可执行程序模块。例如,对初始化各个组件的调用,其在许多不同组件源文件内部创建但是被分配给单个段,能够汇集到单个模块里以形成一个统一的初始化例程,以及甚至能够自动地排列到指令执行的一个特定次序中。
用于构造模块的大多数段简单地从各个组件文件中读取。然而,某些段由该产品组件链接器3600创建以包含该最终二进制映象的一部分,其中该二进制映象部分直到执行了链接器3600之后才存在。
在由该链接器3600创建的附加内容将由‘near’编址方法访问的情况中,该内容和引用必须驻留在同一个段中。这个意味着链接器3600必须增加一个现有段的尺寸,以创建用于该附加内容的空间。注意到当处理该新段尺寸时,必须保留现有的定位要求。
当把段收集在一起以创建模块时,会呈现本身的间隙可能性。这些间隙是保持各个段定位属性的结果。为了降低这些间隙的影响,链接器3600检查能够在其中组合段的各种次序,并选择最小化段间间隙空间的数量的次序。同时,能够指定放置到那些间隙里的二进制数据,这可以允许在要被压缩的模块压缩比中的一个改进。
在某些情况中,用于模块放置的目标可以不包含单个、整体式的地址范围。当在该目标范围内的具体地址是专为特定目的保留时,就能够发生这种情况。这能够导致这样一种情况,在这种情况中,没有足够大的单个子范围来保持整个模块。能够指示链接器3600构造多个段组,它们足够小以符合可用的子范围,由此产生一个碎片化的模块。
有时在该最终二进制映象中的相同代码必须在超过一个位置处出现。该产品组件链接器3600具有复制一个构造模块、并且把该拷贝放置在一个不同于初始地址处的能力。这消除了需要超过一次汇编/编译该源代码。模块能够被放置在具体地址处,或者它们能够简单地挤进一个地址范围内。这通过指定一个模块的目标区域(或者地址范围)来完成。区域的使用也允许一个地址范围在执行的不同阶段期间,不止一次被指定用于使用。此外,一个模块能够被放置到超过一个区域里,这允许在超过一个执行阶段期间,使用该模块。
为了允许一个模块在超过一个执行阶段期间存在,并且位于同一个地址处,该模块被标记(在BIOS.SCR文件中的3812)为用于被镜像放置到该期望区域里。链接器3600将选定一个位置,该位置驻留在那些区域内同一个地址处。
这通过创建一个‘池’区域对象作为一个临时数据结构(未显示)来完成,该临时数据结构仅仅包含那些在所有目标区域中都可用的地址范围。换句话说,如果在任何目标区域中的一个地址范围已经被占据了,则那个范围在该池区域中是不可用的。一旦该模块已经放置到该池区域里,它占据的地址范围在所有目标区域中都被标记为占据了。
当一个模块有必要在执行的不同阶段期间驻留在不同的地址处时,该模块被标记(在文件3812中)为用于拷贝放置。该产品组件链接器3600将在每一指定的区域内确定一个位置,将在那儿放置该模块。
有时在一个区域内的特定地址范围需要为特定目的保留。这些地址范围能够被指定(在公共部分3804)为排除块,来通知该产品组件链接器3600它们不可用于模块放置。
接下来,链接器3600从该外部段3802中读取(步骤3604)该外部段3802的内容,其命名了该组件包含的程序及/或标志定义;而且该链接器3600在一个表格中存储它们的位置,用于以后当从其他构造组件对这些程序、表格、等等进行调用和访问时,解决它们并且向它们分配相同的绝对地址。
在步骤3606处,该产品组件链接器3600从公共段3804中读进来到程序,等等外部定义的所有相关引用,如刚刚描述那样,这些外部定义包括调用、跳转、表格查找访问等等;而且它存储这些引用的地址用于以后引用,以及在需要插入绝对地址的该代码位置处放置地址。
所有这些地址,包含在外部段3802中的外部地址,以及包含在公共段3804中的从属物地址,都在源代码内由特定宏标记;该特定宏在适当时,把绝对地址放置到该外部或者公用段里,以便使得在该外部和公共定义的代码内的精确位置被传递给产品组件链接器,该链接器将解决实际的调用和跳转。如在下面阐明的宏代码中所看到的,每个宏除了在这些特定外部和公用段内放置偏移地址之外,作为一个额外的错误检查,还把这些相同的地址插入到实际代码里,以便当产品组件链接器实际上在该链接的目标代码内检查入口点时,发现在每个偏移处的一个数字都等于该偏移地址。
接下来,在步骤3608,链接器3600生成定义和引用的复制实例,这些实例可能为执行-时间信息所需要,在哪儿一个可执行代码段将重复在该ROM映象中出现或者将在运行时被重定位。例如,代码可以移动、在不同位置复制,或者越权,而且这可能需要对定义和引用都进行复制。
这导致处理过程进行到步骤3610,在这一点上引用和定义实际上是相关联的而且最终会被链接在一起。参考图38,例如这是在本发明的环境中,做出最后的选择以链接一个给定调用到一个程序或者到另一个的地方;因为该过程是由产品组件链接器3600在宏3806的直接控制下完成(通过外部和公共部分3802和3804的中间物)。但是这些宏本身通过特征包含文件2300的中间作用,被命令在编译或者汇编之前编辑该源代码(例如,删除不需要的、对未选择的组件″调用″以及用那些包含文件的绝对地址来替换包含文件类标识符),以及通过该配置状态数据1900控制发送什么信号给产品组件链接器,该配置状态数据1900反映了包含在该产品配置数据2100和组件以及特征信息文件内的指令。由于这些文件是在设计员通过用户界面200的直接控制之下创建的,所以由此给予设计员对确定哪些组件和特征被选中的整个过程一个不寻常的详细控制,这在上面已经阐明了。
将引用与定义关联以如下所述的某个次序执行:
首先,指向一个特定组件的引用(从属物:例如,“call”语句)与在那个命名组件内发现的定义(外部的:例如,“proc”语句)关联。如果两个不同的组件包含具有相同名称的程序,则该组件名称确定那个被挑做一个给定调用语句的目的地。
其次,象这样由宏生成的“调用”信息标识、系统设计员指定的“截取”外部程序(一个会“截取”和接替由该源代码调用的一个程序的功能),优先于任何否则将已经使用的引用,链接到该截取引用。
第三:接下来建立这些链接引用,以达到该最终产品将包含复制的代码,或者由该产品组件链接器3600生成的代码(诸如分类的表格,等等)的程度。
以及最后,把所有私有引用范围限制为链接到在一个给定组件内的父母和兄弟,所有剩余的引用将链接到定义。
在步骤3612处,产品组件链接器3600接下来收集和处理所有需要特别处理的段,诸如需要分类和插入到段里的列表引用、必须被汇编和放置到该代码里的字符串段、也必须被特别处理的非易失性RAM代码、指示在系统启动期间的不同时期可以发现一个给定程序的不同位置的重定位表、以及在非RAM子例程调用期间需要起子例程“返回”点作用的ROM堆栈。
在这些当中,需要解释一下ROM堆栈:一个ROM堆栈如同下述以汇编源程序代码显示,并且由宏CREATE_ROM_STACK生成:
returnAddr:
    DW   returnAddr+4
    DW   SEGMENT returnAddr
    jmp  bx
宏INIT_ROM_STACK生成以下堆栈指针和栈段指针缺省值:
mov ss.SEGMENT returnAddr
mov sp,OFFSET returnAddr
生成非RAM调用函数的宏ROMCALL在该CALL语句点处生成以下代码:
mov bx,returnOffset
jmp FAR xyz
returnOffset:
[neXt instruction beyond the macro]
能够看到,ROM堆栈简单地是一个伪堆栈框架,任何标准的被调用程序都可以对该框架执行一个RET指令。依据程序控制的返回,RET指令载入该微处理器的程序代码地址和段到包含在该堆栈框架内的地址里,其为恰好超过该伪堆栈框架的地址“returnAddr+4”。因此,微处理器执行在该伪堆栈框架之后的指令,其为“jmp[bx]”,而且回跳到由该bx寄存器指定偏移处的调用程序里。
这正是返回程序,很清除创建非RAM其他段子程序调用的特定宏,必须预载在该调用点之后的下一条指令的返回偏移地址;如上所述的地址“returnOffset”,到bx寄存器里。然后该“调用”执行一个远“跳转(jmp)”指令,当执行该调用时,其不在该伪堆栈框架中尝试和保存任何东西,这是由于该伪堆栈框架已经预载了由该RET指令执行使用的返回地址。
以这个简单的方式,在一个非RAM环境中运行的ROM BIOS系统初始化例程(例如在一个PC的存储器控制器设立之前)可能调用在它们的设计中为传统的子程序。注意:产品组件链接器3600仅仅需要插入一个伪堆栈框架到每个需要一个堆栈框架的代码段里,这是因为许多不同对程序的调用(实际上是跳转)能够共享单个伪堆栈框架,而在每个情况中让寄存器bx控制该返回并且把它引导到在该代码内的正确偏移处。
在RAM可用之前实现远子程序调用的一个替换方法涉及创造一个返回地址表格,其用于在该子程序完成处返回到调用代码。调用者在跳转到该子程序之前,加载具有到一个表格的一个索引到预先确定的寄存器里。在完成处,该子程序跳转到一个公共的调度例程,该例程使用该索引值访问返回地址,并且回跳到该调用代码。链接器3600创建该表格并且指定索引值。
链接器3600基于从该组件中获得内务信息创建返回地址表格并且通过公共段3804传递。
接下来,在步骤3614处,代码模块,其现在包含列表、伪ROM堆栈、字符串、非易失性RAM块和代码、以及重定位表格,可以被映射到用于该整个统一代码块的最终地址空间里,这是在这以前不能完成的事情。在Intel386类计算机(奔腾、486、等)上发现的IBM PC以及兼容″实模式″内,所有内部段寻址必须基于真实、绝对的段地址和在那些段内的偏移。因此,在这时候,产品组件链接器3600完成所有外部程序的地址-所有引用的地址。而且最后,链接器3600实际上修正了在该代码中的地址,由此最终解决和满足所有的代码从属物。现在该代码完全准备好安装在最终映象中。
由该产品组件链接器执行的最后步骤,步骤3616,是写出rom模块,符号映射、以及与列表、字符串和非易失性RAM有关的记录信息,用于让系统设计员检查以及转交给分开的(在最佳实施例中)″ROM_IMAGE″例程,该例程输入ROM模块以及BIOS.SCR和有关要被复制的映象部分信息,并且执行该ROM代码映像的最后汇编,包含压缩某些部分、添加用于声音和图象的压缩代码、以及创建最终ROM目录。
图37显示了列表创建和管理过程3700。显示在源代码文件3702的一个代码片段中的LIST_CREATE宏3704(宏逐行描述节5.1),通过保留用它的参数指定的列表名称和入口尺寸以及当它被调用的时候标识当前段,在当前段中创建一个列表。源代码文件B3706的代码片段,包含一个LIST_START宏3708(宏逐行描述节5.3),该宏指定和保留和LIST_CREATE宏3704相同的列表名称和入口尺寸,以及列表入口优先次序。在这个代码片段3710中的LIST_ENTRY宏(宏逐行描述节5.5)指定和保留用于一个列表入口的数据、该入口名称、它的分类优先级(一个用于分类具有相同分类键的列表入口的数字)以及分类关键字。LIST_END宏3717(宏逐行描述节5.4)结束该从LIST_START宏3708开始的列表入口并且允许指定多重列表入口。源代码文件C3714的代码片段说明能够不同源代码文件中指定多个列表入口,其中这些源代码文件可以是不同组件的一部分。产品构造处理过程1000使用由LIST_CREATE宏3704保留的信息来标识一个列表名称,组合由LIST_START 3708和LIST_ENTRY 3710宏保留的信息,分类该入口数据,并且在由该LIST_CREATE宏3704标识的段中,把该分类了的入口数据放置到该最终产品3716里。
每个列表入口声明指定一个分类‘关键字’字符串3711,其能够用来定义在该列表中的入口次序。当提供了一个主分类列表(未显示)时,分类在该实际列表中的入口以匹配该分类列表次序。该主分类列表可能包含这样的入口,该入口不具有在该实际列表中的匹配入口。每个实际列表入口必须具有一个出现在该主分类列表中的分类关键字(如果存在该主分类列表的话),以确定该列表入口的位置。如果超过一个列表入口具有相同的分类关键字字符串,则通过使用该入口分类优先值3713来进行进一步分类。
该产品组件链接器3600从要被分类的名单名称开始,读取包含该主分类列表的内务段(包含在图38的公共段3804中)。然后按次序读取每个分类关键字字符串,并且放入一个作为一个列表对象的容器中,该列表对象(未显示)是一个临时数据结构。该列表入口的实际分类通过向每个入口指定一个索引值来完成的。首先,该索引值被初始化为零。然后,从该主列表中检索第一个分类关键字字符串。在该入口对象容器中搜索具有一个匹配分类关键字字符串3711的入口。如果发现有一个或多个,则当前索引值被分配给具有最高分类优先值3713的那个,并且递增该索引值。这继续进行直到不再有可用的匹配入口为止。这个处理过程为来自该主列表的每个分类关键字字符串重复。
当多个列表入口具有相同的分类关键字字符串,或者当没有提供一位主分类列表时,该列表入口的分类优先值3713用来确定列表入口的次序。分类优先值3713实际上是数字,而且产品组件链接器3600将分类该入口,使得较小值在该列表中出现在较大值之前。当试图通过优先级分类入口,而该优先值相同时,报告一个错误。
列表和列表入口宏生成这样的内务信息,该信息查找它到公共段3804里的路线,并且由产品组件链接器3600使用来确定列表位置和入口次序。这些参数控制实际的分类处理过程。一旦分类已经执行了,就能够删除这个内务信息,由此减小最终可执行代码的尺寸。
当一个列表入口数据3709包含一个‘公共声明’时,能够通过名称做出对它的引用、诸如一个对它的″调用″。由于该列表的最终位置,以及这个入口在该列表中的位置,在由该产品组件链接器确定之前不是已知的,这些引用必须在该列表位置和列表入口位置已知和最后确定之后解决。
这在两个步骤中完成,一个用于该入口的偏移而一个用于该段。该入口的偏移能够在该列表已经分类之后,把入口的索引乘以入口的尺寸3707来确定。这产生了离该段开始处的距离。该计算的偏移值与一个到该列表段对象的指针一起使用。当该列表段被放置在指定区域中时,入口段值对于所有在该列表中的入口将是一样的。
一个列表入口可能在它的数据区域内包含一个公共定义,其需要由该产品组件链接器3600解决以指向一个外部引用。在发生了段组合和放置之前不能解决这些引用,而在所有列表已经被创建了之前不能完成段放置。为了解决这个问题,临时地存储和创建一个包含该列表入口起始位置(在公共段中)和该列表入口新位置(在指定目标段中)的关联对象。当解决每个引用时,进行一个检查以查看该公共定义的位置如果在该公用段中。如果是这样的话,查找包含该定义的用于该列表入口的关联对象,并且把该引用解决到在该列表入口内的新定义位置处。
作为列表处理的一部分,该产品组件链接器3600产生一个结果列表结构的‘源程序列表’,用户可以把它保存为组件源代码库的一部分。这个列表(未显示)能够在该产品组件链接器3600的后续请求上使用,做为该宏和数据3704、3708、3714的替代和越权,其中这些宏和数据定义该列表‘封闭’一个实际列表的内容和结构。当提供了该锁定的列表时,在所有列表声明上执行一个一一对应(即每个列表声明(3704、3708、3714等)必须匹配一个,而且仅仅一个在该锁定列表中的入口)。
为了减小对一个列表入口声明进行改变所需要的努力,这个初始声明能够被留下,并且能够用一个越权修改标记附加到它的宏上来创建一个新的声明。当期望对一个列表入口进行简单的改变时,这消除了修改一个现有文件的需要(其可以包含在一个核心目录中)。当检测到具有相同名称的多个列表入口时,仅仅具有最高数字越权值3705的声明用于该列表的创造。多个具有相同越权值的入口(同名)会导致一个错误。
产品组件链接器3600的一个″精确匹配段″特征消除了使用分别的‘开始’和‘结束’仅仅来确定一个入口列表的位置和尺寸的需要。通过为每个列表定义,以及每个列表入口定义包含额外的标识信息,该源-级别列表声明语句能够被编译到公共段3804里。然后链接器3600能够创建具有需要的确切尺寸的新段。
在所有的列表入口定义已经被读取了之后,能够从在该列表中的入口数目,以及入口尺寸中确定该列表段需要的尺寸。然后创建一个段对象,而且添加到用于适当模块的段对象容器中。
产品组件链接器3600能够在从一位到16字节的尺寸范围中连续(紧密压缩的)地分配非易失性RAM空间,诸如电池备份C-MOS空间。调整8位或者更少的任何东西,以便使它们不穿过一个字节边界。超过16位的任何东西被舍入到一个字节的整数倍数(参见图39)。
提供一个NVRAM_MEDIA宏3902来定义一种特别的媒介,诸如电池备份CMOS。这个宏向该媒介指定一个名称、指定它的尺寸、并且用名称声明用于读取和写入该非易失性媒介的读取和写入子程序。
NVRAM_ITEM宏3904通过指定它的名称、尺寸、缺省值、标记、媒介、和地址来定义非易失性RAM域。例如,该标记指示该域是否将校验和包括在内,以及当校验和失败或者NVRAM被清除时,它是否需要初始化。媒介参数把它指定到由一个NVRAM_MEDIA宏定义的几个可能媒介的特定一个中。地址和媒介两个参数都是可选的。但是如果指定了一个地址,就必须也指定媒介。
NVRAM_RESERVED宏是类似的,但是仅仅用于保留空间,例如,为实时时钟保留空间。
NVRAM_STRUCTURE_START和NVRAM_STRUCTURE_END宏能够把几个NVRAM_STRUCTURE_ITEM宏包括起来,以把一系列入口定义为单个、大的数据结构项目用于检索和存储目的。
READNV宏3906生成读取一个命名NVRAM数据项的代码,而一个WRITENV宏3908生成写入一个命名数据项的代码。
该″READNV<name>″宏生成以下代码:MOV AX,<16 bit space
call read.sub
其导致某些索引(由产品组件3600随后插入)调用适当的子程序(也由该产品组件链接器随后插入)来取出该命名值。这个宏也在公共段3804中生成一个这个调用位置的记录、一个它是一个″读取″调用的指示、加上该NV_RAM域的名称,该名称允许该产品组件链接器3600正确地调整该插入的代码。宏″WRITE_NV<name>″类似地工作。
产品组件链接器3600分配NV_RAM到由该NVRAM_ITEM宏定义的域,并且保持一个把每个名称与到NV RAM的一个偏移相关的临时表格。这个表格然后如刚刚阐明的那样,用于在调整在该程序段中的读和写代码。
STR_DEFINE和STR_DEFINE_END宏4002接受一个字符串并且为该字符串指定一个名称。字符串也具有一个由一个STR_LANGUAGE宏指定的″语言″属性(例如,″US″或者″IT″)以及一个由一个STR_TEXT宏指定的ASCII值。
链接器收集所有由这个宏的实例定义的字符串并且将每一个和它的名称和语言相关。用于一个给定PC的″活动″语言参数通常保存在NVRAM中并且可以由系统设计员改变。
一个″LOADSTR<name>″宏4004生成字符串写入预备代码:
MOV SI,<16bit space>
在一个程序段内,给定该程序一个到该字符串数据的″源索引″指针(其将在下面阐明)。如同在NV_RAM宏的情况下,包含字符串名称、16位空间的地址、以及这个指令特性等的数据被放置到公共段3804里、由此允许该产品组件链接器3600完成这个引用。
产品组件链接器3600为每个语言构造一个单独的表格,其为每个语言包含一个字符串值指针数组和实际的字符串值。在每个表格内,在每个不同的语言中具有相同意识的字符串,由保存在该值指针队列相应位置中的值指针指向。因此,在每个语言表格的字符串值指针队列内的一个″源索引″值,si,诸如″18″标识到相应文本字符串开始处的一个索引值。因此,继″mov si<ptr>″代码之后的代码能够容易地利用该″si″值,其标识一个特定消息以及标识该语言NV_RAM国家值,来查找和检索以该恰当语言写出的恰当消息。
图38在一个视图中给出参与本发明并在别处描述的本发明单元,其允许系统设计员保持详细地控制把特征和组件汇编到一个最后的成品1106里。
设计员,通过该用户界面,查看配置状态数据(图33A)并进行有关组件、特征、和从属物的选择,如已经说明的那样。这个用户信息保留在该产品配置数据文件2100中并且被反馈到该配置状态数据里。同样还扫描组件源代码库1200,而且有关调用、程序、包含等等的详细信息被收集到数据库1800里,其包含这样的东西作为组件命名、类命名、版本命名、及其他有用信息。同样,关于组件和特征消息,诸如它们和哪些平台兼容、或者它们为哪些平台所需要,都从组件和特征信息文件中收集并且放置到数据库1800里。数据库1800的内容也被传送到配置状态数据1900里。
包含在配置状态数据1900中的所有信息然后确定该产品的配置,该配置在用户界面处以逻辑形式向系统设计员呈现。使用该用户界面,设计员可以通过编辑在该组件源代码库1200中的文件或者通过选定或者取消选定特征和组件(图33D)并且调整关于从属物和外部的选项(图33E),来修改该配置。而且当然,通过在该用户界面上的红色X(图33B),把在该系统合适方式中的所有错误直接告知该设计员。
一旦完成了该配置,调用产品生成make例程800来创建最终产品1106。首先,生成组件和产品生在文件2400和2500来指示在它们任务中的汇编器、编译器、和链接器。接下来,生成特征包含文件2300,以便编译器和汇编器在编译和组合之前将把它们插入到源代码文件里。该特征包含文件应当被认为是从系统设计员和配置状态数据直接输入到源代码文件中的信号管道,其实际上控制在编译和组合之前的预编辑,包括删除全部已经取消选定的、对组件和特征的调用;用包含文件在组件源代码库1200内的绝对地址替换它们的″类″命名;传递控制值到宏,来改变该宏指示该产品组件链接器关于什么将被最终链接到什么的方式。
特定的宏,当由编译器和汇编器执行时,为每个程序、标志、和表格(外部)生成数据,该数据被指定放置到一个特定的外部段3802、一个第一伪代码段里。它们为每个调用、跳转、选项、和全局(从属物)生成数据,该数据被指定放置到一个特定的外部段3804、一个第二伪段里。这些伪段应当被认为是在独立源代码文件位置和产品组件链接器之间的通信通道,通过该通道可以传递定义如何执行解决最终地址操作的信息。注意这个信息由系统设计员始创。组件和特征信息以及源代码文件被包含在配置状态数据中,通过该特征包含文件2300被部分地传递到编译汇编过程里;而且通过该特定宏3806被最终收集、改变、和传送给产品组件链接器3600。
接下来执行编译、组合、和链接处理过程,生成由链接器映射文件3808索引到单独段里的可执行文件1104。因此,当产品组件链接器3600进入操作中时,能够通过该可执行文件进行过滤,通过代码段分类它们的内容,以便聚集所有段的内容。以这种方式,聚集了公共和外部段数据3802和3804,以便它能够控制和指导产品组件链接器的操作,以及选定的组件3810列表和指定绝对段地址、分段次序、及其他这样东西的BIOS.SCR文件。所有这些允许系统设计员在链接组件和特征一起到一个集成产品里的过程中,保持一个非比寻常的控制程度,如已经说明的那样。
如先前所述,该开发系统取决于从源代码文件、和信息文件(INF文件)中数据的收集。贯穿该开发环境的运行过程,都在扫描INF文件和源代码文件。特别地,每当一个文件被添加到该工作目录中或者在该工作目录中的一个现成文件被修改时,就扫描任一类型的文件并且把数据放置到数据库中。如果一个文件从该工作目录中删掉,则从该数据库中删除相关数据。这个处理过程确保数据库总是最新的。以下段落将描述从源和INF文件中收集的特定数据,并且给出这些数据的特定使用。
利用本开发系统的程序源文件要求使用先前给出和描述的一个标准宏集合。
INF文件表示该最佳实施例用于存储不保存在源代码宏中、但是便于该系统的许多功能所需要的各个组件和特征信息。注意到:包含在INF文件内的数据能够使用各种其他方法存储,包含而不是局限于数据表、源文件、PLATFORM.CFG文件、或者某些为那个目的特别创建其它文件。在该最佳实施例中,每个组件和特征必须在它的相应目录内具有一个INF文件。INF文件使用一种严格的命令语言,该命令语言在该数据库中存储的扫描处理过程期间,便于简单的数据收集。
在扫描处理过程期间,能够在该树中识别许多错误。这是有用的,因为在试图使用源代码构造该系统之前,或更重要地是在发行一个编译的BIOS之前,在该开发过程的初期就识别该错误。能够被识别的错误包括:1)通过分析每个指令来确保和指令规格说明一致,来标识不适当的命名组件、特征、和选项。2)通过当添加一条记录到该数据库中时要求唯一的组件名称,来识别具有相同组件名称的多个组件或者特征。3)在触发器解决期间能够可能产生不定状态的无效触发器组合。4)识别错误的宏使用,包括在构造处理过程期间将最终导致一个汇编错误或者运行时错误的语法错误或者无效数据错误。
另外,继初始扫描过程之后,数据库用于实时计算在开发过程期间出现的错误状态。本领域目前状态的开发系统仅仅在构造处理过程期间进行相似的错误检查。这个发明在该构造处理过程之前,在一个有效、实时环境中完成这些任务,在该环境中如果发生了一个错误,用户在标准个人计算机系统(奔腾400兆赫)上接收即时反馈(在大多数情况下<1秒)。能够被识别的错误包括1)未解决的从属物,2)违反存取级别的调用,诸如从一个组件到在另一个组件中的一个私有程序的调用。3)调用在该适当程序段外面的程序。4)没有首先声明PUBEXT或者PRVEXT就使用EXTCALL语句,5)对远程序的近调用6)对近程序的远调用7)未解决的从属物,8)对无效版本号的调用9)旧文件越权。10)基于在一个工作树中的用户改变,识别不确定的触发器状态。
可以从该数据库中获得各种统计信息。这些信息包括1)确定不用的接口、标志、或者变量。2)代码流分析。3)在触发器解决期间能够可能产生不定状态的无效触发器组合。4)识别错误宏使用,包括在构造处理过程期间将最终导致一个组合错误或者运行时错误的语法错误或者无效数据错误。
也可以从该配置中获得信息来向仅仅包含是一个产品一部分的源代码库子集提供过滤搜索。例如,为了搜索一个显示的字符串,查看在该源代码库中那个字符串的所有实例比查看实际上由该产品使用的实例要更没有用一些。能够生成给于开发者信息的报告,这些信息诸如)没有硬从属物的特征(可选特征),2)可用的公共接口,3)选项和设置值和缺省值,4)使用指定代码段的特征,以及许多其它的东西。
定制技术
本发明支持从预编译配置以及该二进制链接器(Binary Linker)最终映象创建阶段中定制的方法。预编译配置定制允许源代码库的″指向和单击″定制。如上所述的选项允许用户改变值而不用修改代码。这个方法能够扩展到表格。在一个BIOS情况中,能够定制寄存器和CMOS表格而不用修改代码。能够越权源代码库文件,其中初始文件被原封不动的物理留下,但是越权文件驻留在定制文件夹中,却被构造到组件映象里。定制文件能够被添加到一个特征里,其物理上驻留在定制文件夹中,而且构造到该组件映象里。图42显示了在这些技术中涉及的步骤,说明从一个表格中定制单一项目,使用产品组件链接器3600来用一个定制版本替换该原始记录,并且调整该链接引用。
定制由产品组件链接器3600支持,并且允许表格次序锁定以及表格入口越权。在该表格中的完全入口能够被越权,而且在该代码段中的原始数据能够用该越权替换。当在公共程序(Public ProcedureDeclaration)声明上声明截取参数时,通过截取任何调用者到公共被调用者的链接,产品组件链接器3600也支持定制。这个方法对于具有自定义代码在一个公共(Public)程序前后执行是有用的。
存档
该开发系统定义了一个应用程序员接口用于和改变管理系统(诸如PVCS、Dimensions、Visua1 Sourcesafe等)相互作用。这个接口包括从一个组件或者特征的INF文件中直接移植所有权信息到该改变管理系统数据库里,因此当登记新组件或者特征时,就抛弃了迫使一个用户再输入这个数据到该改变管理系统里的需要。被移植的信息包括包含在该INF文件中的所有归类信息。然而要注意到:利用附加的适当接口,任何附加的信息能够被容易地移植。一旦处于该改变管理系统中,这个信息能被使用用于各种报告目的,以及基于特定准则用于定位组件或者特征。例如,该改变管理系统的一个用户能够查询该改变管理数据来定位支持设备号″371AB″的组件或者特征。
此外该数据库扫描过程也扩展到提供在信息归档和检索区域内的支持。在一个该软件开发系统正被用来描述一个大的可互换组件和特征核心集合的环境中,挑选这些组件和特征的一个子集供一个特定项目之用变得是必须的。本技术的当前状态要求一个用户简单地从标准目录文件夹列表中挑选软件部分来聚集期望的部分,或者一个更先进的系统可以提供用于简化这个处理过程的脚本。在本发明中,先前描述的相同扫描过程应用于组件和特征的核心集合中,以获取该可用的软件核心集合的一个完全数据库。该图形用户界面(GUI)然后利用这个数据库来提供用户选择在一个新产品中需要的组件或者特征的能力。该用户界面仅仅需要该数据库来便于这个选择过程。该数据库能够是当地的或者它能够位于一个远程服务器上。另外,依据一个特定组件或者特征的选择,如果这部分取决于其他组件或者特征的话,该GUI能够立即通知该用户。理论上,一个用户具有在从这存档中下载一个比特代码之前,没有错误地完全选择新软件产品所需要的所有组件和特征的能力。
产品发行一般地,在其他的事情中,要求创建一个标识被发行产品的所有部分的基准线标志。这个标志处理过程允许在一个随后日期处的产品再生性。使用目前工艺水平的开发和改变管理系统,如果一个感兴趣的团体期望有关该发行产品的统计信息,则仅仅可以通过再下载所有构造该发行的产品需要的初始文件然后使用这些文件编译该需要的信息,来获取该信息。或者该改变管理系统可以为某些详情包含发行注释。由本发明提供的开发系统通过允许一个用户仅仅下载用于该产品发布的PLATFORM.CFG文件和存档的数据库(来自一个一般大的文件集合的两个文件)来获取大量的信息,来对目前工艺水平加以改进,其中这些信息否则在今天的技术现状系统中将是不可得到的。这个信息包括所有安装的组件、特征、从属物、接口、它们的版本号、以及任何其他能够从该标准数据库中获得的信息的完全报告。
除了向使用这个系统的开发者提供控制之外,从该代码库中收集的信息数据库能被使用用于各种目的,包括源库质量管理。在该系统中的许多错误在文件被编译之前是可视的。所有代码库的从属物以及定义以及相应的版本被捕获,这允许确定代码库的相干性。所有不引用功能的报告阻止来自存在于该代码库中的死代码。在具有兼容版本号的库中不可得到的从属物报告是一个有价值的工具。
在本发明的最佳实施例中使用的系统宏的描述
该程序(Procedure)以及标志声明宏(Label DeclarationMacros)包含PUBLIC_PROC、PRIVATE_PROC、END_PROC、PUBLIC_LABEL、PRIVATE_LABEL以及FBM_LABEL。
宏PUBLIC_PROC标记一个能够从其它组件调用的程序的开始。它必须和一个ENDvPROC宏匹配。它的参数是名称、版本以及一个可选的INTERCEPT关键字。名称参数由一个类名称、零个或更多子类名称以及实际程序名组成,由句点间隔。版本参数包含由一个句点间隔的主要以及次要版本号。具有不同主要版本号的调用者是不兼容的。具有相同主要版本号但是更大的次要版本号的调用者是不兼容的。增加次要版本号暗示着向后兼容性。可选的INTERCEPT参数指示如果有多个定义的话则该产品组件链接器将修正调用这个程序的调用者。
宏PRIVATE PROC标记一个能够仅仅从该组件内部调用的程序的开始。它必须和一个END_PROC宏匹配。它的参数是名称、范围关键字以及一个可选的版本。名称参数由一个类名称、零个或更多子类名称以及实际程序名组成,由句点间隔。范围关键字参数必须是NEAR或者FAR。该可选的版本参数只有当私有程序被定义在该组件外时,诸如一个共享文件或者原始设备制造商挂钩时,才是需要的。如果指定了,则它和如上所述的PUBLIC_PROC宏的版本参数相同。
END_PROC宏标记一个程序的结束而且没有参数。它必须和一个前面的PUBLIC_PROC或者PRIVATE_PROC宏匹配。
PUBLIC_LABEL宏创建一个能从其它组件中使用用于代码执行、例如创建固定入口点、的标志。它的参数是名称、版本以及一个可选的INTERCEPT关键字。名称参数由一个类名称、零个或更多子类名称以及实际的入口点名称组成,由句点间隔。版本参数和如上所述的PUBLIC_PROC宏的版本参数相同。可选的INTERCEPT参数指示如果有多个定义的话则该产品组件链接器将修正调用这个入口点的调用者。
PRIVATE_LABEL宏创建一个能仅仅从该组件内部中使用用于代码执行、例如创建固定入口点、的标志。它的参数是名称以及一个可选的版本。名称参数由一个类名称、零个或更多子类名称以及实际入口点名称组成,由句点间隔。该可选的版本参数只有当私有入口点被定义在该组件外时,诸如一个共享文件或者原始设备制造商挂钩时,才是需要的。如果指定了,则它和如上所述的PUBLIC_PROC宏的版本参数相同。
FBL_LABEL宏指定将来由产品组件链接器进行的二进制处理(FBM)并且不生成任何代码。它通知扫描工具和产品组件链接器标志表示由二进制链接器在建造时期生成的数据。单个名称参数由一个类名称、零个或更多子类名称以及实际入口点名称组成,由句点间隔。
外部引用(External Reference)宏包含PUBEXT、PRVEXT、EXTCALL、EXTJMP、EXTPTR、LOADADDR、LOADOFF、LOADSEG、EXTREF和EVALREF宏。
PUBEXT宏声明对一个公共程序、公共标志、公共列表或者公共列表入口的一个外部引用。它的参数是名称、版本和可选参数属性关键字或者组件名称、替换名称(altname)和替换版本(altversion)。名称参数由一个类名称、零个或更多子类名称以及实际入口点名称组成,由句点间隔。版本参数和如上所述的PUBLIC_PROC宏的版本参数相同。当可选的第三参数是关键字OPTIONAL时,如果该指定的标志不存在则将删除对该标志的引用。当可选的第三参数是关键字SUBSTITUTE时,如果指定的标志不存在则将使用十六进制值FFFFFFFF(far)或者FFFF(near)。当可选的第三参数是关键字ALTERNATE时,如果名称没有被定义的话,则第四参数是要使用的替换名称,以及第五参数是该替换名称程序的版本号。当对一个程序的调用由一个被定义为具有可选INTERCEPT参数的PUBLIC_PROC的第二程序截取,而且这个程序希望调用初始程序时,初始组件的名称被指定为可选的第三参数。
PRVEXT宏声明到一个私有程序或者标志的一个外部引用。它的参数是名称、范围关键字、版本和可选参数属性关键字、替换名称(altname)和替换版本(altversion)。名称参数由一个类名称、零个或更多子类名称以及实际入口点名称组成,由句点间隔。范围参数包含关键字NEAR或者FAR。版本参数和如上所述的PUBLIC_PROC宏的版本参数或者关键字NO_VER相同。只有当该标志被定义在该组件之外时,诸如一个共享文件或者越权时,才指定版本。当可选的第四参数是关键字OPTIONAL时,如果该指定的标志不存在则将删除到该标志的引用。当可选的第四参数是关键字SUBSTITUTE时,如果指定的标志不存在则将使用十六进制值FFFFFFFF(far)或者FFFF(near)。当可选的第四参数是关键字ALTERNATE时,如果名称没有被定义的话,则第五参数是要使用的替换名称,以及第六参数是该替换名称程序的版本号。
EXTCALL宏用来调用一个公共或者私有程序,并且必须和前面的一个PUBEXT或者PRVEXT宏一起使用。它的参数是名称、可选的代码文本字符串和可选的组件名称。名称参数由一个类名称、零个或更多子类名称以及实际程序名组成,由句点间隔。可选的代码文本字符串包含在该调用已经返回之后要被执行的一条指令。当到一个程序的调用由一个被定义为具有可选INTERCEPT参数的PUBLIC_PROC的第二程序截取,而且这个程序希望调用初始程序时,初始组件的名称被指定为可选的第三参数。
EXTJMP宏跳转到一个公共或者私有程序,并且必须和前面的一个PUBEXT或者PRVEXT宏一起使用。它的参数是名称、一个可选的寄存器名、一个可选的代码文本字符串、以及一个可选的组件名称。名称参数由一个类名称、零个或更多子类名称以及实际程序名组成,由句点间隔。可选的寄存器名指定将保持返回地址的16位寄存器。可选的代码文本字符串包含在该调用已经返回之后要被执行的一条指令。当到一个程序的调用由一个被定义为具有可选INTERCEPT参数的PUBLIC_PROC的第二程序截取,而且这个程序希望调用初始程序时,初始组件的名称被指定为可选的第四参数。EXTPTR宏分配到一个程序或者一个标志的一个指针,并且必须和前面的一个PUBEXT或者PRVEXT宏一起使用。它的参数是名称以及一个可选的组件名称。名称参数由一个类名称、零个或更多子类名称以及实际程序名组成,由句点间隔。当到一个程序的调用由一个被定义为具有可选INTERCEPT参数的PUBLIC_PROC的第二程序截取,而且这个程序希望指向初始程序时,初始组件的名称被指定为可选的第二参数。
LOADADDR宏加载一个程序或者一个标志的地址到寄存器里,并且必须和前面的一个PUBEXT或者PRVEXT宏一起使用。它的参数是名称、一个可选的段寄存器(segmentreg)、一个可选的偏移寄存器(offsetreg)以及一个可选的组件名称。名称参数由一个类名称、零个或更多子类名称以及实际程序名组成,由句点间隔。可选的段寄存器(segmentreg)参数指定保持该地址段部分的16位寄存器(缺省是ES)。可选的偏移寄存器(offsetreg)参数指定保持该地址偏移部分的16位寄存器(缺省是DI)。当到一个程序的调用由一个被定义为具有可选INTERCEPT参数的PUBLIC PROC的第二程序截取,而且这个程序希望加载初始程序的地址时,初始组件的名称被指定为可选的第四参数。
LOADOFF宏加载一个公共或者私有标志的偏移到一个16位寄存器里,并且必须和前面的一个PUBEXT或者PRVEXT宏一起使用。它的参数是偏移寄存器(offsetreg)、名称以及一个可选的组件名称。偏移寄存器(offsetreg)参数命名将保持该偏移的16位寄存器(缺省为DI)。名称参数由一个类名称、零个或更多子类名称以及实际程序名组成,由句点间隔。当到一个程序的调用由一个被定义为具有可选INTERCEPT参数的PUBLIC PROC的第二程序截取,而且这个程序希望加载初始程序的地址时,初始组件的名称被指定为可选的第四参数。
LOADSEG宏加载一个公共或者私有标志的段到一个16位寄存器里,并且必须和前面的一个PUBEXT或者PRVEXT宏一起使用。它的参数是段寄存器(segmentreg)、名称以及一个可选的组件名称。段寄存器(segmentreg)参数命名将保持该段的16位寄存器(缺省为DI)。名称参数由一个类名称、零个或更多子类名称以及实际程序名组成,由句点间隔。当到一个程序的调用由一个被定义为具有可选INTERCEPT参数的PUBLIC PROC的第二程序截取,而且这个程序希望加载初始程序的地址时,初始组件的名称被指定为可选的第四参数。
EXTREF宏用来修正一个结构成员以包含一个公共或者私有标志的地址,并且必须和前面的一个PUBEXT或者PRVEXT宏一起使用。它的参数是名称、一个可选的结构成员(srucMem)名称、一个可选的组件名称以及一个可选的FORWARD_REFERENCE关键字。名称参数由一个类名称、零个或更多子类名称以及实际程序名组成,由句点间隔。如果修正是far,则可选的结构成员(strucMem)名称标识要修正的结构成员。当到一个程序的调用由一个被定义为具有可选INTERCEPT参数的PUBLIC PROC的第二程序截取,而且这个程序希望修正初始程序的地址时,初始组件的名称被指定为可选的第三参数。可选的FORWARD_REFERENCE关键字导致该宏使用一个向前引用的匿名标志来计算偏移。
EVALREF宏允许一个标志的地址在一个指令内使用。它的参数是操作码、目标以及源。操作码参数是要被生成的指令的名称。目标参数指定一个寄存器、标志或者程序,而且源参数指定一个寄存器、即时值、程序或者标志。在目标或者源参数中的程序或者标志必须使用包括在尖括号(<>)中的一个EXTREF宏来进行定义,该尖括号嵌入在该EVALREF宏中。
包含文件声明(Include File Declaration)宏是PUBLIC_INCLUDE_START、PRIVATE_INCLUDE_START、PRVINC以及PUBINC。
PUBLI_CINCLUDE_START宏声明能由其它组件使用的一个包含文件的开始。它的参数是类层次结构(classheirarchy)和版本。该类层次结构(classheirarchy)参数是用句点分开的类名称和零个或更多子类名称。版本参数是由一个句点隔开的、由包含文件定义的接口的主要和次要版本号。
PRIVATE_INCLUDE_START宏声明仅仅能够在当前组件内使用的一个包含文件的开始。它的参数是类层次结构(classheirarchy)以及一个可选的版本。该类层次结构(classheirarchy)参数是用句点隔开的类名称和零个或更多子类名称。版本参数是由一个句点隔开的、由该包含文件定义的接口的主要和次要版本号,并且只有当该包含文件驻留在组件之外时,诸如一个共享的包含文件时,才使用该版本参数。
PRVINC宏包含一个私有包含文件。它的参数是类层次结构(classheirarchy)、文件名以及一个可选的版本。该类层次结构(classheirarchy)参数是用句点隔开的类名称和零个或更多子类名称。文件名参数是该包含文件的名称。版本参数是由一个句点隔开的、由该包含文件定义的接口的主要和次要版本号,并且只有当该包含文件驻留在组件之外,诸如一个共享的包含文件时,才使用该版本参数。
PUBINC宏包含一个公共的包含文件。它的参数是类层次结构(classheirarchy)、文件名以及一个可选的版本。该类层次结构(classheirarchy)参数是用句点隔开的类名称和零个或更多子类名称。文件名参数是该包含文件的名称。版本参数是由一个句点隔开的、由包含文件定义的接口的主要和次要版本号。
程序头部(Procedure Header)宏是DESCRIPTION、INPUT:、OUTPUT:、MODIFIED:、MEM、REG、NONE和OEM_HOOK。这些宏当中没有一个生成任何代码,它们的目的是:当扫描源文件时,标识描述了由前面的PUBLIC PROC或者PRIVATE PROC宏定义的程序的信息的类型和位置。
段(segment)宏是CODE_SEGMENT_OPEN、DATA_SEGMENT_OPEN、ASSUME_CODE_SEGMENT、ASSUME_DATA_SEGMENT以及SEGMENT_CLOSE。
CODE_SEGMENT_OPEN宏标记一个代码段的开始,其中该代码段必须使用SEGMENT_CLOSE宏关闭。它的参数是一个使用加号(+)组合的属性关键字表达式,其确定随后代码的位置和″使用期(lifetime)″。
DATA_SEGMENT_OPEN宏标记一个数据段的开始,其中该数据段必须使用SEGMENT_CLOSE宏关闭。它的参数是一个使用加号(+)组合的属性关键字表达式,其确定随后数据的位置和″使用期(lifetime)″。
ASSUME_CODE_SEGMENT宏迫使汇编器假定指定的段寄存器指向包含有指定属性的代码段。它的参数是用以生成有关假定的段寄存器,以及一个指定该属性的、使用加号(+)组合的属性关键字表达式。
ASSUME_DATA_SEGMENT宏迫使汇编器假定指定的段寄存器指向包含有指定属性的数据段。它的参数是用以生成有关假定的段寄存器,以及一个指定该属性的、使用加号(+)组合的属性关键字表达式。
SEGMENT_CLOSE宏标记一个代码或者数据段的结尾,其中该代码或者数据段必须已经用一个前面的CODE_SEGMENT_OPEN或者DATA_SEGMENT_OPEN宏打开了。
选项(Option)宏是OPTEXT、OPTCHK、LOADOPT、DB_OPT、DW_OPT以及DD_OPT。
OPTEXT宏从在该组件或者特征信息文件中声明的另一个组件或者特征中声明到一个选项的一个引用。它的参数是名称以及一个可选的组件名称。名称参数由一个类名称、零个或更多子类名称以及实际的选项名称组成,由句点间隔。当到一个程序的调用由一个被定义为具有可选INTERCEPT参数的PUBLIC PROC的第二程序截取,而且这个程序希望引用该初始组件或者特征的一个选项时,初始组件的名称被指定为可选的第二参数。
OPTCHK宏用指定的条件和值测试指定的选项(其必须已经用前面的一个OPTEXT宏声明)。如果是true真的话,则执行真代码文本(truecodetext);否则执行假代码文本(falsecodetext)。它的参数是选项名称(optionname)、条件关键字、值、真代码文本(truecodetext)以及一个可选的假代码文本(falsecodetext)。选项名称(optionname)参数由一个类名称、零个或更多子类名称以及实际的选项名称组成,由句点间隔。条件关键字是LE、LT、GE、GT、NE或者EQ中的一个,它们具有通常的意义。值参数是一个常数。真代码文本(truecodetext)参数包含如果该条件是true真时要被执行的代码,而可选的假代码文本(falsecodetext)参数包含如果该条件是false错误时要被执行的代码。
LOADOPT宏用指定选项的值加载指定的目标。该选项必须先前已经用OPTEXT宏声明了。它的参数是目标和选项名称(optionname)。目标参数指定要保持该选项值的存储单元或者寄存器,并且必须少于或者等于该选项尺寸。选项名称(optionname)参数由一个类名称、零个或更多子类名称以及实际的选项名称组成,由句点间隔。
DB_OPT、DW_OPT和DD_OPT宏分别在包含该指定选项值的当前段中放置一个字节、字或者双字,其中该指定选项必须先前已经用OPTEXT宏声明过了。选项名称参数由一个类名称、零个或更多子类名称以及实际的选项名称组成,由句点间隔。
宏的逐行描述
在随后本发明最佳实施例中的宏的描述中命名宏、宏参数以及宏变量的标识符,可以从一个大写字母(A-Z)或者小写字母(a-z)或者一个问号(?)开始,继之以零个或更多字母、数字(0-9)、下划线(_)或者问号字符。从三个问号(???)开始的宏变量名称区分那些仅仅在宏内被定义和引用的变量。在一个宏语句内引用的宏变量通常用它们的当前内容替换。当宏语句始于一个百分比(%)时,宏变量象正常那样用它们的当前内容进行替换;然后,在替换之后,任何命名一个剩余的宏变量的标识符用它的当前值替换。
字符串由小于号(<)和大于号(>)定界。
IF语句表示这么一个条件,如果是真的,则导致直到匹配的ELSE或者ENDIF语句之前的宏语句被估算。如果前面的IF语句是错误的,则ELSE语句导致直到匹配的ENDIF语句之前的宏语句被估算。ELSE语句可以和一个IF结合来表示,如果前面的IF语句是错误的而且ELSEIF语句是真的,则直到匹配的ENDIF语句之前的宏语句被估算。某些If语句是:IFE表达式-如果表达式等于零,IFNB<字符串>-如果字符串不是空的,IFDEF variable-如果变量是定义的,IF表达式-如果表达式是真的,IFIDN<字符串1>,<字符串2>-如果字符串1和字符串2是一样的,以及IFDIF<字符串1>,<字符串2>-如果字符串1不同于字符串2。
1.Exit宏
Exit宏为这里描述的EXTCALL和EXTJMP以及在第4节中描述的ROMCALL。Exit宏标识退出当前程序的控制流程的点,进入由该Exit宏标识的程序并且随后返回。
DEFINE_PREFIX TEXTEQU<D_>
PROC PREFIX TEXTEQU<P>
这两个文本等式定义将在随后宏中使用的、包含该字符串前缀的全局宏变量。
1.1 EXTCALL宏
EXTCALL宏由本发明使用来调用在一个不同组件中的公共程序或者在当前组件中的一个私有程序。由EXTCALL宏生成的代码取决于ExitDeclaration宏和Entry Definition宏,用于它由本发明扫描的procedureName。来自于这些宏的信息反过来,被用来生成一个用于在由本发明产生的该特征包含文件中的procedureName的全局宏变量,并且被包含在每个源代码文件中,其表示如果有的话,应当生成什么代码。EXTCALL MACRO procedureName:REQ,optionalCode,component
BRANCH HANDLER procedureName,call,<optionalCode>,,<component>ENDM
EXTCALL宏生成一条调用指令、用于建造的修正数据、以及如果提供时可选的代码。用法:″EXTCALL pci.oprom.init,<jc exit>″。它的参数是:
procedureName(必需)-以点标记格式被调用的程序名称,例如″class.subelass.procedure″;
optional Code-要汇编的可选代码,一般为一个在由该程序设置的进位标记上的跳转;以及
component-可以用于指定当多个组件定义了同一个procedurename时定义了该程序的组件名称。
EXTCALL宏通过激活具有适当参数的BRANCH HANDLER宏来实现。注意到:BRANCH HANDLER宏的第四个参数是故意被省略的。
1.2 EXTJMP宏
EXTJMP宏由本发明使用来调用在一个不同组件中的公共程序或者在当前组件中的一个私有程序。由EXTJMP宏生成的代码取决于ExitDeclaration宏和Entry Definition宏,用于它由本发明扫描的procedureName。来自于这些宏的信息反过来,被用来生成一个用于在由本发明产生的该特征包含文件中的procedureName的全局宏变量,并且被包含在每个源代码文件中,其表示如果有的话,应当生成什么代码。EXTJMP MACRO procedureName:REQ,register,optionalCode,component
BRANCH HANDLER procedureName,jmp,<optionalCode>,<register>,<component>ENDM
EXTJMP宏用来调用一个公共或者私有程序。它生成一个跳转指令、用于建造的修正数据、以及如果提供的话,可选的代码。用法:″EXTJMPpci.oprom.init,<jc exit>″。它的参数是:
procedureName(必需)-以点标记格式的程序名称,例如″class.subclass.procedure″;
register-保持返回地址的可选寄存器。
optional Code-要汇编的可选代码,一般为一个在由该程序设置的进位标记上的跳转;以及
component-可以用于指定当多个组件定义了同一个procedurename时定义了该程序的组件名称。
EXTJMP宏通过激活具有适当参数的BRANCH HANDLER宏来实现。
1.3 BRANCH_HANDLER宏
BRANCH_HANDLER宏是一个向本发明提供了一个必需功能的内部宏,并且从不由一个源代码文件直接调用。
BRANCH_HANDLER MACRO            externName:REQ,branchInstruction:REQ,  \
optionalCode,register,component
BRANCH_HANDLER宏用来调用一个公共或者私有程序。在第一行结尾处的反斜杠(\)指定行继续。它的参数是:
erternName(必需)-以点标记格式的要被调用的外部程序名称,例如″class.subclass.procedure″;
branchInstruction(必需)-一个调用或者转移;
optionalCode-要汇编的可选代码,一般为一个在由该调用过程设置的进位标记上的跳转;
register_pegister-包含返回地址偏移的寄存器;以及
component-可以用于指定当多个组件定义了同一个procedurename时定义了该程序的组件名称。
LOCAL???addr
LOCAL???retAddr
LOCAL???defineName
LOCAL???procedureName
LOCAL???extern
这些是由该宏使用的局部变量。
GET-SYMBOL-NAME<externName>,<component>
GET SYMBOL NAME宏返回在全局变量???symbol中的externName(或者如果指定的话,component.externname),用下划线(_)替代点(.);例如<pci.oprom.init>被返回作为pci_oprom_init。
???defineName CATSTR DEFINE_PREFIX,???symbol
???procedureName CATSTR PROC_PREFIX,???symbol
If externName是pci.oprom.init;则???defineName是D_pci_oprom_init,并且???procedureName是P_pci_oprom_init。
IFNB<component>
IFNB<optionalCode>
.ERR<BRANCH HANDLER:Cannot specify optional Code withcomponent>
ENDIF
ENDIF
如果component和optional Code参数都被指定了,则产生一个错误。
%IFDEF???defineName
%IF((???defineName EQ TRUE)OR(???defineName EQ FALSE))
%.ERR<BRANCH HANDLER:The name!′externName!′has notbeen PUBEXT or PRVEXT>
ENDIF
验证该externName(pci.oprom.init)已经使用一个PUBEXT或者PRVEXT宏声明了。这将导致该系统定义一个全局变量(D_pci_oprom_init),并且给于它一个既不是TRUE也不是FALSE的值,来表示它的类型。在各行开始处的百分比符号(%)导致IF语句引用用???defineName表示的全局变量值。
%IFE???defineName AND TYPE SUBSTITUTE
如果用局部变量???defineName表示的全局变量值没有设置TYPE_SUBSTITUTE位,则externName没有用SUBSTITUTE属性声明并且能够生成代码。
%IFE???defineName AND TYPE_NOT_INSTALLED
如果没有设置TYPE_NOT_INSTALLED位,则包含externName定义的该组件或者特征被包含在该建造中,并且能够生成代码。
IFNB.<register>
  mov register,???retAddr
ENDIF
如果指定了一个寄存器则加载返回地址偏移到该寄存器里。
% IF???defineName AND TYPE_NEAR
% GET SYMBOL NAME???procedureName
% ???extern CATSTR<???symbol>
% branchInstruction???extern
如果设置了TYPE_NEAR位,则生成branchInstruction(调用或者转移)作为一个近转移。如果该名称参数是pci.oprom.init,则???procedureName包含P_pci_oprom_init,由包含这个程序名称的PUBEXT宏定义的全局变量名称。GET_SYMBOL_NAME宏传送这个全局变量的值(一般为pci.oprom.init)以便使PUBEXT宏当需要时能够使用一个替换的程序名。GET_SYMBOL_NAME宏返回在全局变量???symbol中的???procedureName,并用下划线(_)替换点(.);例如<pci.oprom.init>被返回作为pci_oprom_init,由PUBLIC_PROC宏定义的程序名称。
ELSE

       IFIDNI<branchInstruction>,<call>

            DB      09Ah;用于远调用的操作码

       ELSEIFIDNI<branchlns truct ion>,<jmp>

            DB      OEAh;用于远跳转的操作码

       ELSE

  %.  ERR  <BRANCH_HANDLER:Unknown branch
instruction!′branchInstruction!′>

       ENDIF

       ???addr EQU$

       DW$

       DW$
用以后要被修正的一个程序地址生成远调用(或者跳转)代码。如果该branchInstruction参数没有包含什么期望的东西,则产生一个错误。注意到:该修正位置(???addr)的实际地址将被存储在修正位置本身内。建造工具将使用所存储的修正地址(引用返回它本身)作为一个健全检查。
%    SAVE EXT FIXUP DATA???procedureName,TYPE EXTFAR,???addr,,component
ENDIF
调用SAVE_EXT_FIXUP_DATA宏来保存用于这个外部引用(见下文)的修正数据。在该行开始处的百分比符号(%)导致保存在用???procedureName(P_pci_oprom_init)表示的全局变量中的程序名(pci.oprom.init)被保存为该转移的目标。
???retAddr EQU$
定义被加载到上述一个寄存器里的返回地址。
  IFNB<optionalCode>
  optionalCode
  ENDIF
  ENDIF
  如果存在optionalCode则产生它。
  ELSE
  .ERR<BRANCH_HANDLER:Cannot use the SUBSTITUTE attributewittt;calls/jumps>
ENDIF
如果设置了TYPE_SUBSTITUTE位则产生一个错误。
ELSE
%ERR<BRANCH_HANDLER:!′externName!′is not defined>
ENDIF
如果用???defineName(D_pci_oprom_init)表示的全局变量没有被定义则产生一个错误。
ENDM
结束该宏并且返回到它的调用者。
1.4 SAVE_EXT_FIXUP_DATA宏
SAVE_EXT_FIXUP_DATA宏是一个向本发明提供一个必需功能的内部宏,并且从不由一个源代码文件直接调用。
SAVE EXT FIXUP DATA MACRO call Procedure:REQ,fixupType:REQ,addr:REQ,\
addrOffset,component
SAVE_EXT_FIXUP_DATA宏是一个用于在一个特别命名段中保存由它的参数表示的修正数据的内部宏。它的参数是:
callProcedure(需要)-程序名;
fixupType(需要)修正类型,例如TYPE_EXT_FAR;
addr(需要)-修正地址;
addrOffset-如果偏移修正从段修正中分开,则表示偏移的地址;以及
component-可以用于指定当多个组件定义了同一个procedurename时定义了该程序的组件名称。
该宏产生以下结构:
  DB    procedure name

  DB    0

  DB    component name

  DB    0

  DB    fixup  type

  DW    offset of offset fixup

  DW    offset of segment fixup

  DW    segment for fixups

  externSegment SEGMENT

        DB  ′&amp;callProcedure′;程序字符串

        DB  0                 ;以空值终止该字符串

  IFNB<component>

        DB′&amp;component′      ;要解决的组件

  ENDIF

        DB  0                 ;以空值终止该字符串

        DB fixupType          ;修正类型
				
				<dp n="d81"/>
  IFNB<addrOffset>

        DW OFFSET addrOffset;偏移修正的偏移

  ELSE

        DW OFFSET addr

  ENDIF
  IFB<addrOffset>

        DW OFFSET addr+2    ;段修正的偏移

  ELSE

       DW OFFSET addr 

  ENDIF

        DW SEG addr         ;用于修正的段

  externSegment ENDS

  ENDM
包含外部修正的该结构被放置在一个特定段中。该callProcedure被存为一个以空值结束的字符串。如果该组件参数是非空的,则它也被存为一个以空值结束的字符串。如果该组件参数为空,则仅仅存储空值终结符。空值终结符是ASCII字符NUL,其具有零值并且用来表示一个字符串的结尾。如果addrOffset参数为空,则要被解决的偏移和段被分别保存在addr和addr+2处的相邻字中;否则,addrOffset指定要被解决的偏移地址,而addr指定要被解决的段地址。
当包含该调用的源代码文件被编译、链接、以及由该产品组件链接器处理时,由每个到这个宏的调用产生的修正数据被合并到单个externSegment中。当目标文件被链接以形成组件.EXE文件时,在每个目标文件中的externSegment被合并到单个externSegment中。在每个组件.EXE文件的externSegment中的修正数据由BIOS组件链接器使用来修正该外部引用的段和偏移。
2.退出声明(Exit Declaration)宏
2.1 PUBEXT宏
PUBEXT宏由本发明使用来声明将由一个退出(Exit)宏引用的公共程序名称。该PUBEXT宏名称和它的参数由本发明从该源文件中进行扫描。来自于这个宏和Entry Definition宏的信息,用来生成一个用于在由本发明产生的特征包含文件中的程序名的全局宏变量,并且被包含在每个源代码文件中,其表示如果有的话,该Exit宏应当生成什么代码。
PUBEXT MACRO name,version,attribute,altName,altVersion
PRVEXT宏用来声明到一个公共程序或者标志的一个外部引用。用法:PUBEXT memctrl.shadow.set,1.0,OPTIONAL″。它的参数是:
name-以点标记格式的程序或者标志名称,例如″class.subclass.procedure″;
version-该外部接口的主要.次要版本;
attribute-
OPTIONAL->只有当公共程序或者标志存在时才生成代码,
ALTERNATE->如果公共程序或者标志不存在则使用替换引用,
SUBSTITUTE->如果公共标志是未定义时则存储OFFFFh,或者
component->可以用于指定当多个组件定义了同一个procedurename时。定义了该程序的组件名称。
altName-替换公共程序或者标志的名称;以及
altVersion-该替换接口的主要.次要版本。
LOCAL???defineName
LOCAL???attrib
LOCAL???component
这些是由该宏使用的局部变量。
???attrib CATSTR<attribute>
???component TEXTEQU<>
被越权的属性参数包含一个属性关键字或者组件名称。这两个局部变量用来保持由该属性参数表示的属性关键字和组件名称。由于该参数是被越权的,所以一个或另一个将为空的。最初,假定???attrib包含一个属性关键字,且因此???component是空的。
IFNB<attribute>

IFDIF<attribute>,<OPTIONAL>

IFDIF<attribute>,<ALTERNATE>

IFDIF<attribute>,<SUBSTITUTE>
				
				<dp n="d83"/>
              ???component CATSTR<attribute>

              ???attrib TEXTEQU<>

           ENDIF

        ENDIF

     ENDIF

  ENDIF
检测该被越权的属性参数是否真的是一个组件名称。如果是这样的话,则???component包含该组件名称,且???attrib为空。
NAME_VER CHECKER<name>,<version>
%ATTRIB CHECKER???attrib,<altName>,<altVersion>
NAME_VER_CHECKER宏验证名称和版本参数是否都被指定了。该ATTRIB_CHECKER宏验证如果ALTERNATE属性被指定了则altName和altVersion参数也都被指定了,或者如果没有指定ALTERNATE属性则既不给出altName也不给出altVersion参数。如果每一个名称都不具有一个相应的主要.次要版本号,则这两个宏调用将产生错误。否则版本号由该生成代码忽略。
从该源文件中扫描所有来自于每个PUBEXT宏调用的参数,并且把它们输入到一个数据库中。这允许BIOS开发系统将由该过程定义使用的实际程序接口的版本和在PUBEXT宏调用中声明、并且在包含该宏调用的该源代码文件中使用的程序接口版本进行比较。由于两个程序声明、和定义的版本号都被保存在一个数据库中,因此系统能够在编译之前通过版本比较确定该接口是否是兼容的。
GET EXT NAME name,???attrib,altName,???component
在用???defineName表示的全局变量中的设置位表示公共程序或者标志已经由一个PUBEXT宏调用声明,并且依据所指定的属性被定义或者将被处理。参看在下面的描述。
GET_SYMBOL_NAME name
???defineName CATSTR DEFINE PREFIX,???symbol
GET_SYMBOL_NAME宏返回在全局变量???symbol中的名称,并用下划线(_)替代点(.);即<memctrl.shadow.set>被返回作为memctrl.shadow.set。如果名称是memctrl.shadow.set;则???defineName是D_memctrl_shadow_set。
IFDEF???defineName
%???defineName=???defineName OR TYPE_PUBLIC
ENDIF
如果定义了包含用于这个程序的各种类型位的全局变量,则设置TYPE_PUBLIC位来表示它是一个公共程序。
该BIOS开发系统产生由包含在源库中的每个源代码文件包含的一个特征包含文件。它为每个由一个包含各种类型位的PUBEXT宏声明的程序定义一个全局变量???defineName,例如D_memctrl_shadow_set。例如,如果该程序被声明为OPTIONAL并且该程序定义没有被包含在该构造中,则该系统将用一个TYPE_NOT_INSTALLED位定义该全局变量,以表示将没有为它的调用产生代码(参看上面的BRANCH_HANDLER宏)。
ENDM
结束该宏并且返回到它的调用者。
2.2 GET_EXT_NAME宏
GETE_EXT_NAME宏是一个向本发明提供一个必需功能的内部宏,并且从不由一个源代码文件直接调用。
GET EXT NAME MACRO name:REQ,attribute,altName,component
该GET_EXT_NAME宏确定由一个PUBEXT宏调用声明的全局变量名称,并且在它之中设置位来表示公共程序或者标志已经被声明了,并且依据所指定的属性被定义或者将被处理。它的参数是:
name(需要)-以点标记格式的程序或者标志名称,例如″class.subclass.procedure″;
attribute-
OPTIONAL->只有当公共程序或者标志存在时才生成代码,
ALTERNATE->如果公共程序或者标志不存在则使用替换引用,或者
SUBSTITUTE->如果公共标志是未定义时则存储OFFFFh;
altName-替换公共程序或者标志的名称;以及
component->可以用于指定当多个组件定义了同一个procedurename时定义了该程序的组件名称。
LOCAL???defineName
LOCAL???publicName
LOCAL???tempDefineName
这些是由该宏使用的局部变量。
  IFNB<attribute>

   IFDIF<attribute>,<OPTIONAL>

    IFDIF<attribute>,<ALTERNATE>

     IFDIF<attribute>,<SUBSTITUTE>

         .ERR<GET EXT NAME:Invalid!attribute supplied>

        ENDIF

      ENDIF

    ENDIF

  ENDIF
如果非空则验证该属性参数。
GET_SYMBOL NAME<name>,<component>
???defineName CATSTR DEFINE PREFIX,???symbol
GET_SYMBOL_NAME宏返回在全局变量???symbol中的externName(或者如果指定的话,component.externname),用下划线(_)替代点(.);例如<pci.oprom.init>被返回作为pci_oprom_init。如果名称是pci.oprom.init;则???defineName是D_pci_oprom_init。
IFDEF???defineName
如果其名称用???defineName表示的全局变量由构造工具定,则设置在该全局变量中的位来指定该程序声明的类型。
IF???defineName EQ TRUE
如果其名称用???defineName表示的全局变量具有值TRUE,则该程序被包含在该构造中并且能够被调用。
???publicName CATSTR PROC PREFIX,???symbol%    ???publicName TEXTEQU<name>%    ???defineName=???defineName OR TYPE TRUE
构造该全局变量的名称,它将包含要被调用的程序名称并且在其中存储字符串<名称>。如果名称是pci.oprom.init;则???publicName是P_pci_oprom_init,它包含字符串<pci.oprom.init>。在其名称用???defineName表示的全局变量中设置TYPE_TRUE位。
%  ELSEIF???defineName EQ FALSE
如果其名称用???defineName表示的全局变量具有值FALSE,则该程序没有被包含在该构造中,而且它的类型由它被用其声明的属性确定。
IFIDN<attribute>,<SUBSTITUTE>%    ???defineName=???defineName OR TYPE_SUBSTITUTE
ELSEIFIDN<attribute>,<OPTIONAL>%    ???defineName=???defineName OR TYPE_NOT_INSTALLED ORTYPE OPTI ONAL
如果指定了SUBSTITUTE或者OPTIONAL属性,则设置适当位。
ELSEIFIDN<attribute>,<ALTERNATE>
   ???publicName CATSTR PROC PREFIX,???symbol
   GET SYMBOL NAME altName
   ???tempDefmeName CATSTR DEFINE PREFIX,???symbol
如果指定了ALTERNATE属性,则构造该全局变量的名称,它将包含要被调用程序的名称。
构造该全局变量的名称,其包含用于该altName的类型位。
%    IFDEF???tempDefineName
%        IFE???tempDefineName AND TYPE_RESERVED_TRUE
      .ERR<GET_EXT_NAME:!′altName!′is not in the build>
    ENDIF
  ELSE
    .ERR<GET EXT NAME:!′altName!′is not defined>
  ENDIF
如果没有定义包含了用于altName的类型位的全局变量,或者它被定义了但是没有设置TYPE_RESERVED_TRUE位,则产生一个错误。
%    ???publicName CATSTR<altName>
%    ???defineName=???defineName OR TYPE_AITERNATE
  ENDIF
设置要被调用的程序名称为<altName>,并且在包含该类型位的全局变量中设置TYPE_ALTERNATE位。
%  ELSE
%  .ERR<GET EXT NAME:!′name!′was already qualified withPUBEXT or PRVEXT>
   ENDIF
包含该类型位的全局变量不具有值TRUE或者FALSE,所以产生一个错误。
ELSE
 .ERR<GET_EXT_NAME:!′name!′was not picked up by thebuild tools>
ENDIF
没有定义包含该类型位的全局变量,所以产生一个错误。
ENDM
结束该宏并且返回到它的调用者。
3.入口定义(Entry Definition)宏
3.1 PUBLIC PROC宏
PUBLIC PROC宏由本发明使用用来生成定义了一个将由一个Exit宏引用的公共程序的PROC语句。由本发明从该源文件中扫描PUBLIC_PROCT宏名称和它的参数。来自于这个宏和Exit Declaration宏的信息,用来生成一个用于在由本发明产生的特征包含文件中的程序名的全局宏变量,并且被包含在每个源代码文件中,其表示如果有的话,则该Exit宏应当生成什么代码。
PUBLIC_PROC MACRO procedureName:REQ,version:=<MISS ING>,attrib
PUBLIC_PROC宏定义了一个能够从其它组件中调用的程序。用法:″PUBLIC PROC pci.oprom.init,1.3″它的参数是:
procedureName(必需)-以点标记格式的程序名称,例如″class.subclass.procedure″;
version-主要.次要程序接口版本号,它缺省时被给予值<MISSING>,以便能够检测一个遗漏的版本号;而且
attrib-INTERCEPT,如果在该配置中有多个相同procedureName的定义,则告诉BIOS开发系统调用这个程序。
它使全局变量???procedur eName包含该程序名称
LOCAL???addr
LOCAL???procName
LOCAL???error
LOCAL???procType
这些是由该宏使用的局部变量。
  ???error=FALSE

  IFDEF???procedureName

   IFNB???procedureName
%     .ERR<PUBLIC PROC:The procedure???procedureName is
open>

    ???error=TRUE

    ENDIF

  ENDIF
如果一个现有的程序没有被关闭,则产生一个错误。局部变量???error最初被设置为FALSE,用来表示一个现有的程序没有被关闭以阻止另一个PROC语句的产生,这将导致附加的更不明确的错误。
  IFIDNI<version>,<MISSING>

  .ERR<PUBLIC PROC:!Version information missing>

  ENDIF

  IFNB<attrib>

    IFDIF<attrib>,<INTERCEPT>

  %  .ERR<PUBLIC PROC:!′attrib!′is an invalid attribute>

    ENDIF

  ENDIF
验证是否指定了一个版本参数以及验证该属性参数。
IFE???error
如果没有检测到错误,则定义该程序。
GET_SYMBOL_NAME procedur eName
???procedureName CATSTR???symbol
GET_SYMBOL_NAME宏返回在全局变量???symbol中的procedureName,并用下划线(_)替代点(.);例如<pci.oprom.init>被返回作为pci_oprom_init。设置全局变量???procedureName为用于该汇编器解决的程序名称。如果procedureName是pci.oprom.init;则???procedureName是pci_oprom_init。
???procedureName PROC FAR PRIVATE
???addr EQU$
生成公共程序并且获取它的位置,以便能够修正来自于其它组件的调用。
IFIDN<attrib>,<INTERCEPT>
  ???procType TEXTEQU<TYPE PUBLIC INT PROC>
ELSE
  ???procType TEXTEQU<TYPE PUBLIC PROC>
ENDIF
为该修正数据设置???procType来表示这是一个常规的公共(组件内)程序还是一个截取到具有相同名称的常规程序的调用的特定程序。
%SAVE PUBLIC FIXUP DATA procedureName,
  ???procType,???addr
调用SAVE_PUBLIC_FIXUP_DATA宏(如下所述)来保存该修正数据。
ENDIF
ENDM
结束该宏并且返回到它的调用者。
3.2 SAVE_PUBLIC_FIXUP_DATA宏
SAVE_PUBLIC_FIXUP_DATA宏是一个向本发明提供一个必需功能的内部宏,并且从不由一个源代码文件直接调用。
SAVE_PUBLIC_FIXUP_DATA MACRO publicLabel,publicType,addr
SAVE_PUBLIC_FIXUP_DATA宏是一个用于在一个特别命名的段中保存用它的参数表示的修正数据的内部宏。它的参数是:
publicLabel-以点标记格式的公共符号名称,例如″class.subclass.procedure″;
publicType-公共符号类型(等同枚举);以及
addr-公共符号的地址。
publicSegment SEGMENT
DB   ′&publicLabel′    ;公共字符串
DB   0                   ;以空值终止该字符串
DB   publicType          ;公共类型
DW   OFFSET addr         ;修正偏移
DW   SEG addr            ;修正段
publicSegment ENDS
当包含该调用的源代码文件被编译、链接、以及由该产品组件链接器处理时,由每个到这个宏的调用产生的修正数据被合并到单个publicSegment中。当该目标文件被链接以形成组件.EXE文件时,在每个目标文件中的publicSegment被合并到单个publicSegment中。在每个组件.EXE文件的publicSegment中的修正数据由BIOS组件链接器使用来修正每个外部引用的段和偏移。
ENDM
结束该宏并且返回到它的调用者。
3.3 END_PROC宏
END_PROC宏由本发明使用以在标记从前面具有一个ENDP指示(即指令)的PUBLIC_PROC宏开始的程序结束之前,执行由汇编器所需要的某些错误检查。
END_PROC MACRO
该END_PROC宏定义一个公共程序的结束。
IFNDEF???procedureName
  .ERR<PROC END:No procedure defined>
ELSE
  .ERRB???procedureName,<END PROC:No procedure currentlyopen>全局变量???procedureName包含当前程序的名称。如果没有定义程序或者当前没有打开程序则产生一个错误。
IFNB???procedureName%        ???procedureName ENDP
???procedureName TEXTEQU<>
ENDIF
如果当前打开了一个程序,则为那个程序产生一个ENDP语句,并且把全局变量???procedureName设置为一个空串。
ENDIF
ENDM
结束该宏并且返回到它的调用者。
4.ROM堆栈(ROM Stack)宏
4.1 CREATE_ROM_STACK宏
CREATE_ROM_STACK宏由本发明使用来创建一个ROM堆栈。ROM堆栈是一种用于返回到在一个不同段中的调用者而同时最小化在存储器上的影响的机制。它可以在当处理器被首先加电时被执行的代码中使用,因为那时没有随机存取存储器RAM可以用来存储该返回地址直到存储器已经被初始化了为止。
CREATE_ROM_STACK MACRO
CREATE_ROM_STACK宏生成该ROM堆栈,并且提供一个小的分配器来返回到该调用者。寄存器BP被用作要返回到的偏移。
LOCAL returnDispatcher
LOCAL romStackLabel
这些是由该宏使用的局部变量。
% romStackLabel CATSTR<romStack>,<???currSegmentName>
从字符串<romStack>和当前段名中创建romStackLabel的名称。
%    PUBLIC romStackLabel
%    romStackLabel LABEL BYTE
    DW    OFFSET returnDispatcher
    DW    SEG returnDispatcher
定义romStackLabel的名称为一个在当前代码段中包含returnDispatcher的远地址的外部可视名称。
returnDispatcher:
%    mov sp,OFFSET romStackLabel
  jmp bp
returnDispatcher重置堆栈指针寄存器以指向ROM堆栈的顶端,并且分支转移到保存在BP寄存器中的返回地址偏移。
ENDM
ROM堆栈是一种用于返回到在一个不同段中的调用者而同时最小化在存储器上的影响的机制。它可以在当处理器被首先加电时被执行的代码中使用,因为那时没有随机存取存储器可以用来存储该返回地址直到存储器已经被初始化了为止。
CREATE_ROM_STACK宏被调用来在当前代码段中创建一个ROM堆栈。INIT_ROM_STACK宏被调用来初始化该堆栈寄存器,SS和SP,以指向在当前代码段中的ROM堆栈。ROMCALL宏在当前代码段中的返回地址偏移被保存在BP寄存器中之后产生一个远跳转指令。
被调用的程序保持该BP寄存器,并且用一个常规的远返回指令返回,其从ROM堆栈中弹出returnDispatcher的地址,因此返回到当前代码段。returnDispatcher代码重置堆栈指针,并且使用BP寄存器以返回到调用者。
4.2 INIT_ROM_STACK宏
INIT_ROM_STACK宏由本发明使用来初始化栈寄存器以指向在当前代码段中的ROM堆栈。ROM堆栈是一种用于返回到在一个不同段中的调用者而同时最小化在存储器上的影响的机制。它可以在当处理器被首先加电时被执行的代码中使用,因为那时没有随机存取存储器可以用来存储该返回地址直到存储器已经被初始化了为止。
INIT_ROM_STACK MACRO
INIT_ROM_STACK宏初始化该堆栈寄存器,SS和SP,来指向在当前代码段中的ROM堆栈。
LOCAL romStackLabel
这是由该宏使用的一个局部变量。
romStackLabel CATSTR<romStack>,<???currSegmentName>
从字符串<romStack>和当前段名中创建romStackLabel的名称。
%       EXTERNDEF romStackLabe:NEAR
%    mov  sp,SEG romStackLabel
      mov  ss,sp
%    mov  sp,OFFSET romStackLabel
ENDM
在当前代码段中声明ROM堆栈的名称作为外部的,并且初始化栈寄存器来指向它。
4.3 ROMCALL宏
ROMCALL宏由本发明使用,以使用ROM堆栈来调用在一个不同组件中的公共程序。由ROMCALL宏生成的代码取决于Exit Declaration宏和Entry Definition宏,用于它由本发明扫描的procedureName。来自于这些宏的信息反过来,用来生成一个全局宏变量,用于在由本发明产生的特征包含文件中的procedureName,并且被包含在每个源代码文件中,其表示如果有的话则应当生成什么代码。
ROMCALL MACRO jRoutineName,codeText,jComponent
    EXTJMP jRoutineName,bp,codeText,jComponent
ENDM
ROMCALL宏使用ROM堆栈调用一个远例程,jRoutineName。它使用EXTJMP宏在BP寄存器中保存返回地址的偏移之后产生一个远跳转指令。
5.列表(List)宏
一个列表是一个分类的、相同大小的数据结构(被称为列表入口List Entries)的数组,由一个列表名称(List Name)引用。一个组件(被称作列表所有者(List Owner))生成该列表,给它取个名字和格式,并且指定该列表将被放置在该ROM映象中的位置的段。任何其它组件(包含列表所有者(List Owner))可以使用该列表名称(List Name)添加列表入口(List Entrie)到该列表中。BIOS组件链接器收集所有的列表(List)和列表入口(List Entrie),通过它们的列表名称(List Name)将它们分组,分类它们并且把它们写入到ROM映象中。该BIOS组件链接器也修正到该列表(List)和列表入口(List Entrie)的引用。
5.1 LIST_CREATE宏
LIST_CREATE宏由本发明使用来创建一个列表。它产生信息来标识列表,其将由本发明中构造该列表的BIOS组件链接器部分获得。本发明扫描LIST_CREATE宏和它的参数,以便它们能够与定义该列表入口的LIST_START宏的参数相比较。
LIST CREATE MACRO listName,listVersion,listSize,listAttribute
LIST_CREATE宏创建一个列表。它的参数是:
li s tName-表示这个列表的唯一名称;
listVersion-列表的主要.次要版本号;
listSize-列表入口的大小,可以是字节、一个合格类型(BYTE、WORD、等)的名称、或者一个结构名的数目;以及
listAttribute-PUBLIC关键字。
用法:″LIST_CREATE postList,1.0,postTaskStruc″。
LOCAL???entrySize
LOCAL???listAttr
这些是由该宏使用的局部变量。
        ???entrySize=0

  IFNB<listAttribute>

     IFIDN<listAttribute>,<PUBLIC>

      ???listAttr=1

     ELSE

      ???listAttr=0

  %  .ERR<LIST CREATE:The attribute!′listAttribute!′is
illegal>

      ENDIF

  ELSE

      ???listAttr=0

  ENDIF
初始化???entrySize。如果指定了,则验证listAttribute,并且把它转换成为一个1(PUBLIC属性)或者0(没有属性)。
IFNB<listSize>
   IF OPATTR listSize EQ 24h
确保listSize是一个结构、合格的类型(BYTE、WORD、DWORD、等等),或者一个即时值。如果不是,则在ELSE语句中产生一个错误。
     IF TYPE listSize NE 0

        ???entrySize=SIZEOF(listSize)

     ELSE

        ???entrySize=listSize

     ENDIF

   ELSE

  %  .ERR<LIST CREATE:!′listSize !′is not a structure,
qualified type,or immediate value>

      ENDIF

   ENDIF
如果listSize具有一个类型,则它是一个结构或者合格类型。SIZEOF函数将返回它的尺寸。否则它是一个即时值(数字)而且不需要特定处理。
  IFNB<listName>

   IFNB<listVersion>

     IFNB<listSize>

  %SAVE LIST_CREATEDATA

  List Name,???currSegmentName,

  ???entrySize,listVersion,???listttr

        ELSE

          .ERR<LIST CREATE:Size of list entry is missing>

        ENDIF

  ELSE

  .ERR<LIST CREATE:List version is missing>

  ENDIF

  ELSE
  .ERR<LIST CREATE:List name is missing>

  ENDIF
验证listName、listVersion、以及listSize是否已经全部被指定了。调用如下所述的SAVE_LIST_CREATE_DATA宏来保存该列表生成数据。全局变量???currSegmentName包含当前段的名称。
ENDM
结束该宏并且返回到它的调用者。
5.2 SAVE_LIST_CREATE_DATA宏
SAVE_LIST_CREATE_DATA宏是一个向本发明提供一个必需功能的内部宏,并且从不由一个源代码文件直接调用。
SAVE_LIST_CREATE_DATA MACRO listName:REQ,list Segment:REQ,\entrySize:REQ,listVersion:REQ,listAttr:REQ
SAVE_LIST_CREATE_DATA宏是一个内部宏,用于在一个特别命名的段中,保存生成一个用它的参数表示的列表所需要的数据。它的参数是:
listName(需要)-列表名称;
listSegment(需要)-列表位于其中的段名称;
entrySize(需要)-列表入口的大小;
listVersion(需要)-列表的版本号;以及listAttr(需要)-1(PUBLIC属性)or 0(没有属性)。listDeclarationSegment SEGMENT
DB   ′&listName′               ;列表名称
DB   0                           ;以空值终止该字符串
DB   ′& listSegment′
DB   0                           ;以空值终止该字符串
DW   entrySize                   ;列表入口大小
DB   ′&listVersion′            ;版本号
DB   0                           ;以空值终止该字符串
DB   listAttr                    ;列表属性
listDeclarationSegment ENDS
ENDM
当包含该调用的源代码文件被编译、链接、以及由该产品组件链接器处理时,由每个到这个宏的调用产生的列表生成数据被合并到单个listDeclarationSegment中。当该目标文件被链接以形成组件.EXE文件时,在每个目标文件中的listDeclarationSegment被合并到单个listDeclarationSegment中。在每个组件.EXE文件的listDeclarationSegment中的列表生成数据由BIOS组件链接器使用来生成一个列表头部。listName将变成一个(PUBLIC)标志,指向在最终ROM映象的指定段中的列表头部。
5.3 LIST_START宏
LIST_START宏由本发明使用来标识一个将要被添加入口的列表。本发明扫描LIST_START宏和它的参数,以便使它们能够与创建该列表的LIST_CREATE宏的参数相比较。
LIST_START MACRO listName,listVersion,listType,lOverridePriority
LIST_START宏开始添加入口到指定列表的指定版本中。它和一个或多个LIST_ENTRY、LIST_DATA、及/或LIST_SORT宏一起使用来定义该入口,而且和一个匹配的LIST_END宏一起使用来结束该入口。它的参数是:
listName-唯一名称,由一个LIST_CREATE宏调用声明;
listVersion-列表的主要.次要版本号;
listType-列表入口的数据类型,可以是一个合格的类型(BYTE、WORD、等)的名称、或者一个结构名;以及
lOverridePriority-列表入口优先级次序(CORE、PRODUCT或者PLATFORM关键字)。这指定随后的列表入口是否将替换现有的同名、但是具有较低越权优先级的列表入口。PLATFORM替换PRODUCT,PRODUCT替换CORE,以及CORE替换缺省。
它初始化全局变量:
???listName-listName,
???listType-listType,以及
???listOverride-列表入口优先级次序,
以及打开一个特别命名的段。
  IFNDEF???listName

     ???listName CATSTR<LIST_UNDEFINED>

  ENDIF

  IFDIFI???listName,<LIST_UNDEFINED>

  %    .ERR<LIST START:List!′&amp;???listName!′is already
				
				<dp n="d98"/>
open>

  ELSE

    IFB<listName>

    .ERR<LIST START:List name is missing>

    ELSEIFB<listVersion>

    .ERR<LIST START:List version is missing>

    ELSEIFB<listType>

    .ERR<LIST START:List type is missing>

    ELSE
如果必要的话则初始化全局变量???listName,并且执行某些基本的错误检查。
  ???listName CATSTR<listName>

  ???listType CATSTR<listType>

  IFNB<lOverridePriority>

    IFIDN<lOverridePriority>,<CORE>

      ???listOverride CATSTR<OFOh>

    ELSEIFIDN<lOverridePriority>,<PRODUCT>

      ???listOverride CATSTR<80h>

    ELSEIFIDN<lOverridePriority>,<PLATFORM>

      ???listOverride CATSTR<010h>

    ELSE

  %.ERR<LIST START:Override priority type!′

  lOverridePriority!′is invalid>

      ???listOverride CATSTR<OFOh>

    ENDIF

  ELSE

    ???listOverride CATSTR<OFFh>

  ENDIF
至此没有查找到错误。初始化全部全局变量,把越权优先级转换成为一个数字值。当发现在该构造中的两个列表入口同名时,这个值允许BIOS组件链接器选择一个。CORE具有最低的优先级,PRODUCT较高,而PLATFORM是最高的。
  IF(OPATTR listType)NE 24h

  %  .ERR<LIST START:List type!′listType!′is nova
structure or qualified type>

      ???listType CATSTR<ERROR>

  ELSEIF TYPE listType EQ 0

  %  .ERR<LIST START:List type!′list Type!′is an
immediate value-not a structure or qualified type>

      ???listType CATSTR<ERROR>

  ELSE

      listEntrySegment SEGMENT

  ENDIF
  ENDIF
ENDIF
ENDM
验证listType是否是一个有效的结构或者合格类型,并且打开listEntrySegment段。
5.4 LIST_END宏
LIST_END宏由本发明使用来结束一个已被添加了入口的列表。
LIST_END MACRO
LIST_END宏结束用于一个列表的入口。
  IFDEF???list Name

    IFIDNI???listName,<LIST_UNDEFINED>

      .ERR<LIST END:The open list has already been closed
with LIST_END>

  ELSE

    listEntrySegment ENDS

    ???listName CATSTR<LIST_UNDEFINED>

  ENDIF

  ELSE

    .ERR<LIST END:Alist has not been opened with LIST
START>

  ENDIF
				
				<dp n="d100"/>
  ENDM
验证全局变量???listName是否指定了一个打开的列表。关闭listEntrySegment段并且设置???listName来指示一个关闭的列表。
当包含这些段声明的源代码文件被编译、链接、以及由产品组件链接器处理时,由这个listEntrySegment封装的列表入口数据被合并到单个listEntrySegment中。当该目标文件被链接以形成组件.EXE文件时,在每个目标文件中的listEntrySegment被合并到单个listentrySegment中。在每个组件.EXE文件listEntrySegment中的列表入口数据由BIOS组件链接器合并和分类来产生在最终ROM映象中的一个分类列表,其列表头部由创建该列表的LIST_CREATE宏表示。
5.5 LIST_ENTRY宏
LIST_ENTRY宏由本发明使用来定义要被添加到一个列表中的入口。
LIST_ENTRY MACRO entryName,entryData,ePriority:=<8000h>,eSortKey,listAttribute
LIST_ENTRY宏通过指定要出现该列表中的数据以及为分类该入口所必需的信息来创建一个列表入口。它必须出现在一个LIST_START宏调用之后以及在一个LIST_END宏调用之前。它的参数是:
entryName-单个列表入口的名称。在该列表内必须是唯一的;
entryData-在(<)和(>)内的数据,将出现在ROM映象中。结构数据必须被包含在附加的花括号({)和(})内;
ePriority-用于分类具有相同分类关键字的列表入口的数字。低数字放置在高数字的前面。最小值是0,最大值是65535(OFFFFh),以及缺省值是32768(8000h);
eSortKey-用于匹配该列表入口到一个主引用列表的字符串。该entryName是缺省的分类关键字;以及
listAttribute-LABEL及/或PUBLIC。
它还使用由前面的START_LIST宏调用提供的三个全局变量值:
???listName-打开列表的名称;
???listType-入口类型;以及
???listOverride-越权优先级数字(CORE、PRODUCT、PLATFORM、或者没有)。
用法:″LIST_ENTRY vgaData,<24h,45h>″。
LOCAL???qualifiedType
LOCAL???dataSize
LOCAL???eData
LOCAL???eSortKey
LOCAL???rawData
LOCAL???listAttr
这些是由该宏使用的局部变量。
  IFNB<listAttribute>

    IFIDN<listAttribute>,<PUBLIC>

      ???listAttr=1

    ELSEIFIDN<listAttribute>,<LABEL>

      ???listAttr=2

    ELSEIFIDN<listAttribute>,<LABEL OR PUBLIC>
      ???listAttr=3

    ELSEIFIDN<listAttribute>,<PUBLIC OR LABEL> 

      ???listAttr=3

    ELSE

      ???listAttr=0

  %    .ERR<LIST ENTRY:The attribute!′listAttribute!′is
illegal>

    ENDIF

  ELSE

    ???listAttr=0

  ENDIF
分析listAttribute参数并且把它转换成为一个数字值。PUBLIC关键字导致entryName被定义为一个引用该entryData的公共标志。LABEL关键字导致entryName被定义为在该列表内的一个标志(如果两个关键字都被指定了,则是一个PUBLIC LABEL),而实际上不产生一个列表入口。当列表由可选入口组成时,如果需要到一个列表里的一个索引,则这个属性是有用的。
IFB<eSortKey>
  ???eSortKey CATSTR<entryName>
ELSE
  ???eSortKey CATSTR<eSortKey>
ENDIF
如果eSortKey参数为空,则使用entryName参数作为缺省的分类关键字。
  IFB<entryName>

    .ERR<LIST ENTRY:Entry name for list data is missing
>

  ELSEIFB<entryData>

    .ERR<LIST ENTRY:List data is missing>

  ELSEIFNDEF???listName

    .ERR<LIST ENTRY:A list has not been started with
LIST_START>

  ELSEIFIDNI???listName,<LIST_UNDEFINED>

    .ERR<LIST ENTRY:The open list has already been closed
with LIST_END>

  ELSEIFIDNI???listType,<ERROR>

  ELSE
在该输入数据上执行某些健全检查。
  %    ???dataSize=SIZEOF???listType

      ???qualifiedType=TRUE

      IFIDNI???listType,<BYTE>

      ELSEIFIDNI???listType,<WORD>

      ELSEIFIDNI???listType,<DWORD>

      ELSEIFIDNI???listType,<FWORD>

      ELSEIFIDNI???listType,<QWORD>

      ELSEIFIDNI???listType,<TBYTE>

      ELSE

        ???qualifiedType=FALSE

      ENDIF
如果到达这里则没有发生错误。确定列表类型的大小以及它是否是一个结构或者合格类型。
  IFE???qualifiedType

    ???eDataCATSTR???listType,<!<>,<entryData>,<!>>

    ???rawData CATSTR<!<>,<entryData>,<!>>

  ELSE

    ???eDataCATSTR???listType,<>,<entryData>

    ???rawData CATSTR<entryData>

  ENDIF
如果该数据不是一个合格类型,则构造表达式“structureName<structureData>”,否则构造表达式“dataType data″(例如BYTE数据)。
%SAVE_LIST_ENTRY_DATA???listName,entryName,
???eSortKey,ePriority,\???listOverride,???listAttr,???dataSize,<???eData>,<???rawData>
ENDIF
ENDM
调用SAVE_LIST_ENTRY_DATA宏来保存该列表入口并且返回到该调用者。
5.6 SAVE_LIST_ENTRY_DATA宏
SAVE_LIST_ENTRY_DATA宏是一个向本发明提供一个必需功能的内部宏,并且从不由一个源代码文件直接调用。
SAVE_LIST_ENTRY_DATA MACRO listName,entryName,\
    sortKey,sortPriority,overridePriority,\
    listAttr,dataSize,listData,listTextData
SAVE_LIST_ENTRY_DATA宏在由LIST_START宏打开的段listEntrySegment中保存用它的参数表示的列表入口数据。
  DB    ′&amp;listName′            ;列表名称

  DB    0                        ;以空值终止该字符串

  DB    LISTMGR ENTRY TYPE       ;入口类型

  DB    ′&amp;entryName′           ;列表入口名称
				
				<dp n="d104"/>
  DB     0                     ;以空值终止该字符串

  DB     ′&amp;sortKey′          ;列表分类关键字

  DB     0                     ;以空值终止该字符串

  DW     sortPriority          ;分类优先级(多个入口)

  DB     overridePriority      ;分类越权(CORE、PLATFORM...)

  DB     overridePriority      ;数据越权(CORE、PLATFORM...)

  DB     listAttr              ;列表属性

  DW     dataSize              ;数据大小
@@:

  listData                     ;产生该数据

  DB    ″&amp;listTextData″      ;未加工的列表入口数据

  DB    0                      ;以空值终止该字符串
ENDM
局部标志(@@:)定义用入口数据值填充的一个位置。
5.7 LIST_DATA宏
LIST_DATA宏由本发明使用来越权用于一个列表入口的数据。
LIST_DATA MACRO entryName,entryData,eAttributes
LIST_DATA宏必须出现在一个LIST_START宏调用之后以及一个LIST_END宏调用之前。它的参数是:
entryName-将让它的entryData改变的列表入口名称;
entryData-用于列表入口的新数据;以及
eAttributes-LABEL及/或PUBLIC。
它还使用由前面的START_LIST宏调用提供的三个全局变量值:
???listName-打开列表的名称;
???listType-入口类型;以及
???listOverride-越权优先级数字(CORE、PRODUCT、PLATFORM、或者没有)。
  LOCAL???dataSize
  LOCAL???qualifiedType
  LOCAL???eData
  LOCAL???rawData
  LOCAL???listAttr
这些是由该宏使用的局部变量。
  IFNB<eAttributes>

  IFIDN<eAttributes>,<PUBLIC>

    ???listAttr=1

  ELSEIFIDN<eAttributes>,<LABEL>

    ???listAttr=2

  ELSEIFIDN<eAttributes>,<LABEL OR PUBLIC>

    ???listAttr=3

  ELSEIFIDN<eAttributes>,<PUBLIC OR LABEL>

    ???listAttr=3

  ELSE

    ???listAttr=0

  %  .ERR<LIST DATA:The attribute!′eAttributes!′is
illegal>

    ENDIF

  ELSE

    ???listAttr=0

  ENDIF
分析eAttributese参数并且把它转换成为一个数字值。PUBLIC关键字导致entryName被定义为一个引用该entryData的公共标志。LABEL关键字导致entryName被定义为在该列表内的一个标志(如果两个关键字都被指定了,则是一个PUBLIC LABEL),而实际上不产生一个列表入口。当列表由可选入口组成时,如果需要到一个列表里的一个索引,则这个属性是有用的。
  IFB<entryName>

    .ERR<LIST DATA:The list entry name is missing>

  ELSEIFB<entryData>

    .ERR<LIST DATA:The list entry data is missing>

  ELSEIFNDEF???listName

    .ERR<LIST DATA:A list has not been started with
LIST_START>

  ELSEIFIDNI???listName,<LIST UNDEFINED>
				
				<dp n="d106"/>
    .ERR<LIST DATA:The open list has already been closed
with LIST_END>

  ELSEIFIDNI???listType,<ERROR>

  ELSE

    %???dataSize=SIZEOF???listType
验证一个打开的列表是否存在以及所有需要的参数是否都给出了。确定一个列表入口的大小。
  ???qualifiedType=TRUE

  IFIDNI???listType,<BYTE>

  ELSEIFIDNI???listType,<WORD>

  ELSEIFIDNI???listType,<DWORD>

  ELSEIFIDNI???listType,<FWORD>

  ELSEIFIDNI???listType,<QWORD>

  ELSEIFIDNI???listType,_<TBYTE>

  ELSE

    ???qualifiedType=FALSE

  ENDIF
确定列表类型是否是一个结构或者合格类型。
  IFE???qualifiedType

    ???eData CATSTR???listType,<!<>,<entryData>,
<!>>

   ???rawData CATSTR<!<>,<entryData>,<!>>

  ELSE

    ???eData CATSTR???listType,<>,<entryData>

    ???rawData CATSTR<entryData>

  ENDIF
如果该数据不是一个合格类型,则构造表达式“structureName<structureData>”,否则构造表达式“dataType data″(例如BYTE数据)。
%SAVE_LIST_OVERRIDE_DATA???listName,entryName,
???dataSize,\
      <???eData>,<???rawData>,???listOverride,
    ???listAttr
ENDIF
ENDM
调用SAVE_LIST_OVERRIDE_DATA宏来保存该列表越权数据并且返回到调用者。
5.8 SAVE_LIST_OVERRIDE_DATA宏
SAVE_LIST_OVERRIDE_DATA宏是一个向本发明提供一个必需功能的内部宏,并且从不由一个源代码文件直接调用。
SAVE_LIST_OVERRIDE_DATA MACRO listName,entryName,dataSize,listData,\
  listTextData,overridePriority,attributes
SAVE_LIST_OVERRIDE_DATA宏在由LIST_START宏打开的段listEntrySegment中保存用它的参数表示的列表越权数据。
  DB      ′&amp;listName′              ;列表名称

  DB      0                          ;以空值终止该字符串

  DB      LISTMGR OVERRIDE_TYPE      ;越权类型

  DB      ′&amp;entryName′             ;列表入口名称

  DB      0                          ;以空值终止该字符串

  DB      overridePriority           ;越权优先级

  DB      attributes                 ;列表属性

  DW      dataSize                   ;数据大小
@@:

  listData                           ;产生该数据

  DB      ″&amp;listTextData″          ;未加工的列表入口数据

  DB      0                          ;以空值终止该字符串
ENDM
局部标志(@@:)定义用入口数据值填充的一个位置。
5.9 LIST_SORT宏
LIST_SORT宏由本发明使用来改变用于一个列表入口的分类条件。
LIST_SORT MACRO entryName,ePriority:=<8000h>,eSortKey
LIST_SORT宏必须出现在一个LIST_START宏调用之后以及一个LIST_END宏调用之前。它的参数是:
entryName-将让它的分类次序改变的列表入口名称;
ePriority-用于分类具有相同分类关键字的列表入口的数字。低数字放置在高数字的前面。最小值是0,最大值是65535(OFFFFh),以及缺省值是32768(8000h);
eSortKey-用于匹配该列表入口到一个主引用列表的字符串。该entryName是缺省的分类关键字。
它还使用由前面的START_LIST宏调用提供的三个全局变量值:
???listName-打开列表的名称;
???listType-入口类型;以及
???listOverride-越权优先级数字(CORE、PRODUCT、PLATFORM、或者没有)。
LOCAL???eSortKey由这个宏使用的局部变量。IFB<eSortKey>
  ???eSortKey CATSTR<entryName>
ELSE
  ???eSortKey CATSTR<eSortKey>
ENDIF
  如果eSortKey参数为空,则使用entryName参数作为缺省的分类关键字。
  IFB<entryName>

    .ERR<LIST SORT:Entry name for list data is missing>

  ELSEIFNDEF???listName

    .ERR<LIST SORT:A list has not been started with
LIST_START>

  ELSEIFIDNI???listName,<LIST_UNDEFINED>

    .ERR<LIST SORT:The open list has already been closed
with LIST_END>

  ELSEIFIDNI???list Type,<ERROR>

  ELSE

  %SAVE_LIST_SORT_DATA???listName,entryName,???eSortKey,
				
				<dp n="d109"/>
ePriority,???listOverride

  ENDIF

  ENDM
执行某些健全检查,而且如果事事都检查过了,则保存新的分类数据。
5.10 SAVE_LIST_SORT_DATA宏
SAVE_LIST_SORT_DATA宏是一个向本发明提供一个必需功能的内部宏,并且从不由一个源代码文件直接调用。
SAVE_LIST_SORT_DATA MACRO listName,entryName,sortKey,\
       sortPriority,overridePriority
SAVE_LIST_SORT_DATA宏在由LIST_START宏打开的段listEntrySegment中保存用它的参数表示的列表分类数据。
  DB     ′&amp;listName′          ;列表名称

  DB     0                      ;以空值终止该字符串

  DB     LISTMGR_SORT_TYPE      ;分类类型

  DB     ′&amp;entryName′         ;列表入口名称

  DB     0                      ;以空值终止该字符串

  DB     overridePriority       ;使用的最终入口

  DB     ′&amp;sortKey′           ;列表分类关键字

  DB     0                      ;以空值终止该字符串

  DW    sortPriority            ;分类优先级(多个入口)
ENDM
5.11 MASTER_START宏
MASTER_START宏由本发明使用来开始一个主索引的定义。
本发明中的BIOS组件链接器部分依据在主索引(Master Index)中的分类关键字(Sort Key)的次序来分类列表入口(List Entrie)。每个列表至多有一个主索引(Master Index)。主索引(MasterIndex),通常可在该列表所有组件中找到,在一个单独的汇编源文件中以便于越权。主索引用三个宏,MASTER_START、MASTER_ENTRY和MASTER_END,来创建。
MASTER_START MACRO listName,attrib
MASTER_START宏必须在任何MASTER_ENTRY或者MASTER_END宏被调用之前在被调用。它的参数是:
listName-这个主索引有关的完全合格的列表名称(包含组件路径);以及
attrib-LOCKED关键字。如果LOCKED,则这是一个锁定索引(Locked Index);否则它是一个主索引(Master Index)。
一个锁定索引(Locked Index)是主索引的一种特殊形式。并不是使用分类关键字来确定列表入口的最终次序,锁定索引而是使用列表入口名称。MASTER_START宏初始化全局变量:
???masterName-listName,以及
???masterAttribs-主Master或者锁定Locked索引,
打开一个特别命名的段并且在这个段中保存这些全局变量的值。
IFNDEF???masterName
  ???masterName CATSTR<MASTER_LIST_CLOSED>
ENDIF
IFIDN???masterName,<MASTER_LIST_CLOSED>
  masterIndexSegment SEGMENT
初始化全局变量???masterName,如果必要的话则执行某些一致性检查并且打开段masterIndexSegment。
    IFNB<attrib>

      ???masterAttribs=1

      IFDIF<attrib>,<LOCKED>

  %.ERR<MASTER_START:!′attrib!′is an invalid attribute>

      ENDIF

    ELSE

      ???masterAttribs=0

  ENDIF
该attrib参数转换成为一个数字值,并且设置全局变量???masterAttribs来指示指定了一个主Master或者锁定Locked索引。
  IFNB<listName>

  ???masterName CATSTR<listName>

  ELSE
				
				<dp n="d111"/>
      .ERR<MASTER_START:The list name is missing>

      ???masterName CATSTR<>

    ENDIF

  %SAVE_MASTER_I NFO_START???masterName,???masterAttribs

  ELSE
  %.ERR<MASTER START:Master index list !′&amp;???masterName!′
is already open>

  ENDIF

  ENDM
在全局变量中的存储listName,并且调用SAVE_MASTER_INFO_START来保存全局变量的值。如果该参数或者全局变量不一致则产生错误。
5.12 SAVE_MASTER_INFO_START宏
SAVE_MASTER_INFO_START宏是一个向本发明提供一个必需功能的内部宏,并且从不由一个源代码文件直接调用。
SAVE_MASTER_INFO_START MACRO masterListName,attributes
DB     ′&masterListName′    ;主列表名称
DB     0                      ;以空值终止该字符串
DW     attributes             ;列表属性
ENDM
该SAVE_MASTER_INFO_START宏在由MASTER_START宏打开的段中保存它的参数值。
5.13 MASTER_END宏
MASTER_END宏由本发明使用来结束一个主索引的定义。
MASTER_END_MACRO
MASTER_END宏结束一个主索引的定义。它必须继一个MASTER_START宏调用之后出现。
  IFNDEF???masterName

    .ERR<MASTER_END:A master index was not started with
MASTER_START>

  ELSEIFIDNI???masterName,<MASTER LIST CLOSED>
				
				<dp n="d112"/>
    .ERR<MASTER END:The master index was already closed
with MASTER_END>

  ELSE

    SAVE_MASTER_INFO  0

    master IndexSegment ENDS

    ???masterName CATSTR<MASTER_LIST_CLOSED>

  ENDIF

  ENDM
验证一个主列表是否打开。保存一个空的主列表入口来标记列表结束。关闭该主索引段并且标记???masterName为MASTER_LIST_CLOSED。
5.14 MASTER_ENTRY宏
MASTER_ENTRY宏由本发明使用来插入一个列表入口到一个主索引中。
MASTER ENTRY MACRO keyName
MASTER_ENTRY宏必须继一个MASTER_START宏调用之后以及一个MASTER_END宏调用之前。它的参数是:
keyName-用于在一个特定列表入口和这个主索引位置之间创建一个关联的名称。它必须是一个分类关键字Sort key(主索引MasterIndex)或者列表入口List Entry名称(锁定索引Locked Index)。
    IFNDEF???masterName

    .ERR<MASTER_ENTRY:A master index list has not been opened
with MASTER_START>

  ELSE 

    IFDIF???masterName,<MASTER_LIST_CLOSED>

  %    SAVE MASTER INFO keyName

    ELSE

  %  .ERR<MASTER ENTRY:The master index list has already
been closed with MASTER_END>

   ENDIF

  ENDIF

  ENDM
检查一个主列表是否已经开始。调用SAVE_MASTER_INFO宏存储Sort key或者List Entry名称。
5.15 SAVE_MASTER_INFO宏
SAVE_MASTER_INFO宏是一个向本发明提供一个必需功能的内部宏,并且从不由一个源代码文件直接调用。
SAVE_MASTER_INFO MACRO keyName
  IFDIF<keyName>,<0>
  DB       ′&keyName′    ;索引名
  ENDIF
  DB       0               ;以空值终止该字符串
ENDM
该SAVE_MASTER_INFO宏在由前面的MASTER_START宏调用打开的特定段中保存用它的参数表示的keyName。
6.包含(Include)宏
6.1 PUBLIC_INCLUDE_START宏
PUBLIC_INCLUDE_START宏由本发明使用来标识一个公共包含文件。本发明扫描PUBLIC_INCLUDE_START宏和它的参数,以便使它们能够与包含该文件的PUBINC宏的参数相比较。
包含文件驻留在逻辑上“拥有”这些定义的组件中。如果该定义将由在其它目录中的其它组件使用,则该包含文件将通过使用PUBLIC_INCLUDE_START宏将它本身声明为公共的。外部组件将使用由一个PUBINC宏表示的类/子类和文件名引用该包含文件。使用的包含文件的物理位置将由构造处理确定。
类似于接口,一个公共包含文件的使用将包含为该文件所期望的“接口”的主要和次要版本(不是文件版本)。
PUBLIC_INCLUDE_START MACRO classPath,version
PUBLIC_INCLUDE_START宏标记能由在其它目录中的其它组件使用的一个公共包含文件的开始。它的参数是:
classPath-由句点(.)隔开的类名称和零个或更多子类名称;以及
version-为该文件所期望的接口的主要.次要版本号。
  IFB<version>
				
				<dp n="d114"/>
  .ERR<PUBLIC_INCLUDE_START:!Version number for public
include missing>

  ENDIF

  IFB<classPath>

    .ERR<PUBLIC_INCLUDE_START:Class path information is
missing>

    ENDIF

  ENDM
验证classPath和version参数是否都已经被指定了。从该包含文件中扫描每个PUBLIC_INCLUDE_START宏调用的参数,并且把它们以及包含文件名称和目录路径输入到一个数据库中。这允许BIOS开发系统在编译之前,把它从包含文件中扫描的任何接口信息和来自于包含它的源文件的接口信息合并起来。
6.2 PUBINC宏
PUBINC宏由本发明使用来包含在一个不同组件中定义的一个公共包含文件。本发明扫描PUBINC宏和它的参数,以便使它们能够与定义该文件的PUBLIC_INCLUDE_START宏的参数相比较。
PUBINC MACRO classPath,filenmame,version
PUBINC宏包含一个外部包含文件到该构造里。外部包含文件在当前目录和组件的外面。它的参数是:
classPath-由句点(.)隔开的类名称和零个或更多子类名称;
fileName-包含文件的名称;以及
version-为该文件所期望的接口的主要.次要版本号。
用法:“PUBINC post.dispatcher,postdisp.inc,1.0”。
    LOCAL???incPath
由该宏使用的局部变量。
  IFNB<classPath>

  IFNB<fileName>
GET SYMBOL NAME classPath

    ???inePath CATSTR<I_>,???symbol

  %INCLUDE???incPath\\fileName

    IFB<version>
				
				<dp n="d115"/>
    .ERR<PUBINC:The include file!version is missing>

  ENDIF

  ELSE

    .ERR<PUBINC:The include file name is missing>

    ENDIF

  ELSE

  .ERR<PUBINC:The include file feature path is missing>

    ENDIF

  ENDM
验证所有参数是否都给出了。调用GET_SYMBOL_NAME宏返回包含classPath的全局变量???symbol,其用下划线(_)替换每个句点(.)。通过用一个I_前缀???symbol的值,形成包含该包含文件目录路径的全局变量名称。如果是post.dispatcher,则???incPath是I_post_dispatcher。用一个在该全局变量中使用目录路径的INCLUDE指令(即,命令)包含该文件。
该BIOS开发系统产生一个被包含在源代码库的每个源代码文件中的一个特征包含文件“feature.inc”。它为由包含该包含文件目录路径的一个PUBINC宏调用声明的每个公共包含文件定义一个全局变量,例如I_post_dispatcher TEXTEQU<@Environ(MANTICORE)\post\dispatcher>。

Claims (102)

1.一种用于开发一个最终产品(1106)的软件开发系统(100),包含:
用于定义该最终产品(1106)的产品配置数据(2100);
包含了源代码单元(1220、1224、1226、1300)的至少一个源代码库(1200),其中这些源代码单元定义一个或多个包含了接口(1316、1322)以及从属物(1312、1318、1324)的对象(1204、1206、1212、1214);
用于定义所述对象(1204、1206、1212、1214)的特性的指令(1502到1532、1702到1728);
从所述产品配置数据(2100)、所述指令(1502到1532、1702到1728)、以及从所述源代码库(1200)中获得的数据(1800)中开发配置状态数据(1900)的一个配置器(700);
一个图形用户界面(200),用于给出一个表示该最终产品(1106)的配置状态数据(1900)的可视、逻辑表示,遗漏以及选定和取消选定的对象(1204、1206、1212、1214)和选项(1524),所述界面(200)接受命令来调整该最终产品(1106);以及
在所述配置状态数据(1900)的控制下从所述源代码单元(1220、1224、1226、1300)中生成最终产品(1106)的例程(800、1000、1102、3600)。
2.如权利要求1所述的软件开发系统(100),其特征在于:所述对象(1204、1206、1212、1214)包含至少一个源代码单元(1220、1224、1226、1300),以及一个包含了所述指令(1502到1532、1702到1728)的一个对象信息数据集合(1400、1600)。
3.如权利要求2所述的软件开发系统(100),其特征在于:所述指令(1502到1532、1702到1728)包含构造指令(1502到1532、1702到1728)。
4.如权利要求1所述的软件开发系统(100),其特征在于:所述对象(1204、1206、1212、1214)包含至少一个组件(1204、1206),其中该组件包含至少一个是一个特征(1212、1214)的对象(1204、1206、1212 1214)。
5.如权利要求4所述的软件开发系统(100),其特征在于:所述组件(1204、1206)以及特征(1212 、1214)中每个都包含至少一个源代码单元(1220、1224、1226、1300)以及一个包含了指令(1502到1532、1702到1728)、用于相应组件(1204、1206)或者特征(1212、1214)的对象信息数据集合(1400、1600)。
6.如权利要求5所述的软件开发系统(100),其特征在于:所述指令(1502到1532、1702到1728)包含构造指令(1502到1532、1702到1728)。
7.如权利要求1所述的软件开发系统(100),其特征在于:所述接口(1316、1322)和从属物(1312、1318、1324)中的至少某些具有名称(在1316处为“ERRORBEEP”,在1318处为“DELAY”)以及类(在1316处为“BEEP”,在1318处为“TIMER”)命名,它们在开发该最终产品(1106)之前用恰当的绝对地址替换。
8.如权利要求7所述的软件开发系统(100),其特征在于:产生最终产品(1106)的所述例程(800、1000、1102、3600),在它们修改源代码单元(1220、1224、1226、1300)时,把用于至少某些从属物(1312、1318、1324)和接口(1316、1322)的类(在1316处为“BEEP”、在1318处为“TIMER”))和名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)引用转换成为名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)和库(1200)引用。
9.如权利要求7所述的软件开发系统(100),其特征在于:至少某些类别(在1316处为“BEEP”、在1318处为“TIMER”)命名拥有多个对象(1204、1206、1212、1214)。
10.如权利要求9所述的软件开发系统(100),其特征在于:所述对象(1204、1206、1212、1214)包含包括有特征的(1212,1214)组件(1204、1206),而且至少某些类(在1316处为“BEEP”、在1318处为“计时器”)命名涉及,多个特征(1212、1214)的接口(1316、1322)和从属物(1312、1318、1324)。
11.如权利要求1所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有版本指示(在1312、1316、1322处为“1.0”)。
12.如权利要求11所述的软件开发系统(100),其特征在于:所述接口(1316、1322)和从属物(1312、1318、1324)中的至少某些具有名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)以及类(在1316处为“BEEP”、在1318处为“TIMER”)命名,以及版本指示(在1312、1316、1322处为″1.0″),其中名称和类命名在开发该最终产品(1106)之前用恰当的绝对地址进行替换。
13.如权利要求11所述的软件开发系统(100),其特征在于:所述图形用户界面(200)在匹配的接口(1316、1322)和从属物(1312、1318、1324)中警告不兼容的版本号。
14.如权利要求13所述的软件开发系统(100),其特征在于:所述接口(1316、1322)和从属物(1312、1318、1324)中的至少某些具有名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)以及类(在1316处为“BEEP”、在1318处为“TIMER”)命名,以及版本指示(在1312、1316、1322处为“1.0”),其中名称和类命名在开发该最终产品(1106)之前用恰当的绝对地址进行替换。
15.如权利要求1所述的软件开发系统(100),其进一步包含对象规格说明数据作为与至少某些从属物(1312、1318、1324)有关的数据的一部分,其特征在于:该对象规格说明数据导致相应从属物(1312、1318 1324)优于其它具有相同标识符的接口(1316、1322),被链接到在用该指定对象(1204、1206、1212、1214)包含的一个源代码单元(1220、1224、1300)中的一个接口(1316、1322)。
16.如权利要求15所述的软件开发系统(100),其特征在于:所述接口(1316、1322)和从属物(1312、1318、1324)中的至少某些具有名称(在1316处的“ERRORBEEP”、在1318处的“DELAY”)以及类(在1316处为“BEEP”、在1318处为“TIMER”)命名,它们在开发该最终产品(1106)之前被恰当的绝对地址替换。
17.如权利要求16所述的软件开发系统(100),其特征在于:至少某些类(在1316处为“BEEP”、在1318处为“TIMER”)命名包含多个对象(1204、1206、1212、1214)。
18.如权利要求17所述的软件开发系统(100),其特征在于:所述对象(1204、1206、1212、1214)包含包括有特征(1212,1214)的组件(1204、1206),而且至少某些类(在1316处为“BEEP”、在1318处为“计时器”)命名涉及多个特征(1212、1214)的接口(1316、1322)和从属物(1312、1318、1324)。
19.如权利要求15所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有版本指示(在1312、1316、1322处为“1.0”)。
20.如权利要求19所述的软件开发系统(100),其特征在于:所述接口(1316、1322)和从属物(1312、1318、1324)中的至少某些具有名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)以及类(在1316处的“BEEP”、在1318处为“TIMER”)命名,以及版本指示(在1312、1316、1322处为″1.0″),其中名称和类命名在开发该最终产品(1106)之前被恰当的绝对地址替换。
21.如权利要求19所述的软件开发系统(100),其特征在于:所述图形用户界面(200)在匹配的接口(1316、1322)和从属物(1312、1318、1324)中警告不兼容的版本号。
22.如权利要求21所述的软件开发系统(100),其特征在于:所述接口(1316、1322)和从属物(1312、1318、1324)中的至少某些具有名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)以及类(在1316处为“BEEP”、在1318处为“TIMER”)命名,以及版本指示(在1312、1316、1322处为″1.0″),其中名称和类命令在开发该最终产品(1106)之前被恰当的绝对地址替换。
23.如权利要求22所述的软件开发系统(100),其特征在于:所述对象(1204、1206、1212、1214)包含至少一个组件(1204、1206),其中该组件包含至少一个是一个特征(1212、1214)的对象(1204、1206、1212、1214)。
24.如权利要求1所述的软件开发系统(100),包含被指定在一个RAM自由环境中运行的源代码单元(1220、1224、1226 1300),其特征在于:产生最终产品(1106)的例程(800、1000、1102、3600)在调用或者跳转从属物(1312、1318、1324)处修改所述源代码单元,插入模拟了一个子程序跳转的代码并且返回,而不需要一个基于RAM的子程序堆栈。
25.如权利要求24所述的软件开发系统(100),其特征在于:在调用或者跳转和返回从属物(1312、1318、1324)处插入的代码设置一个继一个返回之后进行一个寄存器转移的伪返回堆栈,并且在一个调用或者跳转点处,产生并且插入用于加载直接地址到所述寄存器里然后产生一个到指定接口(1316、1322)的跳转的代码。
26.如权利要求24所述的软件开发系统(100),其特征在于:在调用或者跳转和返回从属物(1312、1318、1324)处插入的代码在一个指定的寄存器中保持该返回地址、或者用于指示该返回地址位置的一个索引,并且使用该寄存器执行一个到在该调用程序中恰当点的返回。
27.如权利要求1所述的软件开发系统(100),其特征在于:当遇到一个取决于一个具有一个相应接口(1316、1322)的未选择对象(1204、1206、1212、1214)的存在的从属物(1312、1318、1324)时,配置器(700)自动地选择所述对象(1204、1206、1212、1214)用于包含在最终产品(1106)中。
28.如权利要求27所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)以及类(在1316处为“BEEP”、在1318处为“TIMER”)命名,它们在开发该最终产品(1106)之前被恰当的绝对地址替换。
29.如权利要求28所述的软件开发系统(100),其特征在于:至少某些类(在1316处为“BEEP”、在1318处为“TIMER”)命名包含多个对象(1204、1206、1212、1214)。
30.如权利要求27所述的软件开发系统(100),其特征在于:所述对象(1204、1206、1212、1214)包含包括有特征(1212,1214)的组件(1204、1206),而且至少某些类(在1316处为“BEEP”、在1318处为“计时器”)命名涉及多个特征(1212、1214)的接口(1316、1322)和从属物(1312、1318、1324)。
31.如权利要求1所述的软件开发系统(100),其特征在于:某些接口(1316、1322)可以可选地包含一个截取命名,并且其中所述配置器(700)将一个从属物(1312、1318、1324)与一个具有一个截取命名的接口(1316、1322)相关,优于其它同样命名的接口(1316、1322)。
32.如权利要求31所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物1312、1318、1324)具有版本指示(在1312、1316、1322处为“1.0”)。
33.如权利要求31所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)以及类(在1316处为“BEEP”、在1318处为“TIMER”)命名,它们在开发该最终产品(1106)之前被恰当的绝对地址替换。
34.如权利要求33所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物1312、1318、1324)具有版本指示(在1312、1316、1322处为“1.0”)。
35.如权利要求31所述的软件开发系统(100),其特征在于:所述对象(1204、1206、1212、1214)包含至少一个组件(1204、1206),其中该组件包含至少一个是一个特征(1212、1214)的对象(1204、1206、1212、1214)。
36.如权利要求35所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有版本指示(在1312、1316、1322处的“1.0”)。
37.如权利要求35所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)以及类(在1316处为“BEEP”、在1318处为“TIMER”)命名,其在开发该最终产品(1106)之前被恰当的绝对地址替换。
38.如权利要求37所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有版本指示(在1312、1316、1322处为“1.0”)。
39.如权利要求1所述的软件开发系统(100),其特征在于:产生最终产品(1106)的所述例程(800、1000、1102、3600),当面临由于没有选择一个对象(1204、1206、1212、1214)而没有相应接口(1316、1322)的至少某些从属物(1312、1318、1324)时,通过从包含该从属物(1312、1318、1324)的源代码单元中删除该从属物(1312、1318 1324)来修改该源代码单元(1220、1224、1226、1300)。
40.如权利要求39所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有版本指示(在1312、1316、1322处为“1.0”)。
41.如权利要求39所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)以及类(在1316处为“BEEP”、在1318处为“TIMER”)命名,其在开发该最终产品(1106)之前被恰当的绝对地址替换。
42.如权利要求41所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有版本指示(在1312、1316、1322处为“1.0”)。
43.如权利要求39所述的软件开发系统(100),其特征在于:宏程序3806用来标识从属物(1312、1318、1324),包含到一个控制参数2300的引用的所述宏程序3806由所述配置器(700)设置,它允许当该对象(1204、1206、1212、1214)包含一个没有被选定的相应接口(1316、1322)时,在配置器(700)的选择处删除该从属物(1312、1318、1324)。
44.如权利要求39所述的软件开发系统(100),其特征在于:所述图形用户界面(200)指示由于没有选择包含该相应接口(1316、1322)的对象,哪些从属物(1312、1318、1324)将被删除,并且接受命令来选择或者不选择相应的对象(1204、1206、1212、1214)。
45.如权利要求44所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有版本指示(在1312、1316、1322处为“1.0”)。
46.如权利要求44所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)以及类(在1316处为“BEEP”、在1318处为“TIMER”)命名,其在开发该最终产品(1106)之前被恰当的绝对地址替换。
47.如权利要求46所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有版本指示(在1312、1316、1322处为“1.0”)。
48.如权利要求1所述的软件开发系统(100),其特征在于:所述配置器(700)可以导致该图形用户界面(200)给予关于至少某些没有接口(1316、1322)的从属物(1312、1318、1324)的可视错误指示。
49.如权利要求48所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有版本指示(在1312、1316、1322处为“1.0”)。
50.如权利要求48所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)以及类(在1316处为“BEEP”、在1318处为“TIMER”)命名,其在开发该最终产品(1106)之前被恰当的绝对地址替换。
51.如权利要求50所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有版本指示(在1312、1316、1322处为“1.0”)。
52.如权利要求1所述的软件开发系统(100),其特征在于:用于定义所述对象(1204、1206、1212、1214)特性的数据(1210、1222、1400、1600),在至少某些情况中,包含一个指示(在1518处的“EXTERNALTRIGGER”),其表示一个对象的选择由另一个对象(1204、1206、1212、1214)的选择触发;而且所述配置器(700),当遇到这样的数据时,每当所述一个对象(1204、1206、1212、1214)也被选择时,选择所述另一个对象(1204、1206、1212、1214)。
53.如权利要求53所述的软件开发系统(100),其特征在于:所述指令(1502到1532、1702到1728)包含构造指令(1502到1532、1702到1728)。
54.如权利要求52所述的软件开发系统(100),其特征在于:所述对象(1204、1206、1212、1214)包含至少一个组件(1204、1206),其中该组件包含至少一个是一个特征(1212、1214)的对象(1204、1206、1212、1214)。
55.如权利要求54所述的软件开发系统(100),其特征在于:所述指令(1502到1532、1702到1728)包含构造指令(1502到1532、1702到1728)。
56.如权利要求54所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有名称(在1316处为“ERRORBEEP”、在1318处为“DELAY”)以及类(在1316处为“BEEP”、在1318处为“TIMER”)命名,其在开发该最终产品(1106)之前被恰当的绝对地址替换。
57.如权利要求56所述的软件开发系统(100),其特征在于:至少某些所述接口(1316、1322)和从属物(1312、1318、1324)具有版本指示(在1312、1316、1322处为“1.0”)。
58.如权利要求1所述的软件开发系统(100),其特征在于:至少某些所述源代码单元(1220、1224、1226、1300)包含列表单元(3704、3708、3710),而且其中所述例程包含一个产品组件链接器3600,它通过把那些列表单元(3704、3708 3710)放在一起来修改该源代码单元(1220、1224、1226、1300),并且在一个指定点(3716)处把它们插入到最终产品(1106)里,并且建立到列表项引用的链接。
59.如权利要求58所述的软件开发系统(100),其特征在于:所述列表单元(3704、3708、3710)包含分类优先级说明。
60.如权利要求58所述的软件开发系统(100),其特征在于:所述列表单元(3704、3708、3710)包含分类关键字说明。
61.如权利要求58所述的软件开发系统(100),其特征在于:所述列表单元(3704、3708、3710)包含列表入口。
62.如权利要求58所述的软件开发系统(100),其特征在于:可以定义多个列表3704,每个列表入口3710分配了一个列表名称(在3710处的“ENTRY NAME”)以便于标识和收集该列表3704的单元(在3710处的“ENTRY DATE”)。
63.如权利要求62所述的软件开发系统(100),其特征在于:所述列表单元(3704、3708、3710)包含列表入口3710,其中至少有一些列表入口3710指定了分类优先级(在3710处的“SORT PRIORITY”)以及分类关键字(在3710处的“SORT KEY”)。
64.如权利要求1所述的软件开发系统(100),其特征在于:至少某些接口(1316 1322)被声明为公共的并且可由在任何对象(1204、1206、1212、1214)中的任何从属物(1312、1318、1324)访问,或者被声明为私有的并且仅仅可由在同一个对象(1204、1206、1212、1214)内的从属物(1312、1318、1324)访问。
65.如权利要求1所述的软件开发系统(100),其特征在于:所述对象(1204、1206、1212、1214)包含至少一个组件(1204、1206),其中该组件包含至少一个特征(1212、1214),而且至少某些接口(1316、1322)被声明为公共的并且可由在任何组件(1312、1206、1212、1214)中的任何从属物(1312、1318、1324)访问,某些被声明为私有的并且仅仅可由在同一个组件(1312、1206、1212、1214)内的从属物(1312、1318、1324)访问,以及某些被声明为保护的并且仅仅由在同一个特征(1212、1214)内的从属物(1312、1318、1324)访问。
66.如权利要求1所述的软件开发系统(100),其特征在于:至少某些所述源代码单元(1220、1224、1226、1300)包含定义文本(在图40中的“STR TEXT”)和语言(在图40中的“STR LANGUAGE”)的字符串单元(4002),以及其中产生最终产品(1106)的所述例程(800、1000、1102、3600)插入利用保存在非易失性存储器3902中的一个值3904允许选择恰当的语言字符串的代码。
67.如权利要求1所述的软件开发系统(100),其特征在于:所述产品配置数据(2100)包含定义了要被构造的平台类型(在2102处的“DESKTOP”)的数据。
68.如权利要求67所述的软件开发系统(100),其特征在于:所述定义了要被构造的平台类型(在2102处的“DESKTOP”)的数据能够指定一个平台为台式机。
69.如权利要求67所述的软件开发系统(100),其特征在于:所述定义了要被构造的平台类型(在2102处的“DESKTOP”)的数据能够指定一个平台类型为便携式机。
70.如权利要求67所述的软件开发系统(100),其特征在于:所述定义了要被构造的平台类型(在2102处的“DESKTOP”)的数据能够指定一个平台类型为服务器。
71.如权利要求67所述的软件开发系统(100),其特征在于:所述定义了要被构造的平台类型(在2102处的“DESKTOP”)的数据能够指定一个平台类型为台式机、便携式机、或者服务器。
72.如权利要求1所述的软件开发系统(100),其特征在于:所述产生最终产品(1106)的例程包含一个产品组件链接器3600,其允许提供越权数据(在图42中的“REGISTER TABLE ENTRY#_2 OVERRIDEDATA”)来替换在一个数据表(在图42中的“REGISTER TABLE ENTRY#_1 ENTRY#_2 ENTRY#_3 ENTRY#_4”)中的某些数据项目。
73.如权利要求1所述的软件开发系统(100),其特征在于:所述产生最终产品(1106)的例程包含一个产品组件链接器3600,其在分别编译的可执行代码块和分别链接的可执行代码块之间建立内部段链接。
74.如权利要求1所述的软件开发系统(100),其特征在于:在所述源代码库(1200)中的代码单元3904可以被指定为驻留在非易失性存储器3902中,并且其中所述产生最终产品(1106)的例程(800、1000、1102、3600)包含一个产品组件链接器3600,它分配用于存储这种单元3904的非易失性存储器3902,并在最终产品(1106)中插入必要的代码,来给予程序用这样的方式访问(3906、3908)在非易失性存储器3902中的这种变量(3904),从而使系统设计员不必关心非易失性存储器3902的特性。
75.如权利要求74所述的软件开发系统(100),其特征在于:至少某些所述源代码单元(1220、1224、1226、1300)包含定义字符串的文本(在4002处的“STR TEXT”)和语言(在4002处的“STRLANGUAGE”)的字符串单元(4002),以及其中产生最终产品(1106)的所述例程(800、1000、1102、3600)插入利用保存在非易失性存储器3902中的一个值3904允许选择恰当语言字符串的代码。
76.如权利要求1所述的软件开发系统(100),其特征在于:所述图形用户界面(200)包含一个用于查看和修改对象(1204、1206、1212、1214)的源代码单元(1220、1224、1226、1300)的编辑器。
77.如权利要求76所述的软件开发系统(100),其特征在于:通过在配置状态数据(1900)的所述可视逻辑表示中点击一个单元,可以在所述图形用户界面(200)中打开一个编辑窗口。
78.如权利要求1所述的软件开发系统(100),其特征在于:宏指令(1502到1532、1702到1728)用来标记所述接口(1316、1322)和从属物(1312、1318、1324),以及其中代码修改被用所述配置器(700)开发的配置状态数据(1900)所驱动和控制的宏程序(3806)执行,因此标准的汇编器、编译器、和链接器1102可以用于实现该软件开发系统(100)。
79.如权利要求78所述的软件开发系统(100),其特征在于:所述配置状态数据(1900)被送入到一个用以产生特征包含文件(2300)和构造文件(2400、2500)的产品构造900中,在这之后一个产品构造例程(1000)导致由所述构造文件(2400、2500)控制的编译器和链接器1102。组合从所述源代码库(1200)中获取的源代码单元(1220、1224、1226、1300)和所述特征包含文件(2300)到定义了该最终产品(1106)的构造产品组件(1104)里。
80.如权利要求79所述的软件开发系统(100),其特征在于:所述构造文件包含组件构造文件(2400)和产品构造文件(2500)。
81.如权利要求79所述的软件开发系统(100),其特征在于:一个产品组件链接器(3600)转换所述构造产品组件(1104)到所述最终产品(1106)里。
82.如权利要求81所述的软件开发系统(100),其特征在于:所述构造文件包含组件构造文件(2400)和产品构造文件(2500)。
83.一种用于开发一个最终产品(1106)的方法(100),包含:
产生定义了该最终产品(1106)的产品配置数据(2100);
提供包含源代码单元(1220、1224、1226、1300)的至少一个源代码库(1200),其中这些源代码单元定义了一个或多个包含了接口(1316、1322)以及从属物(1312、1318、1324)的对象(1204、1206、1212、1214);
提供定义了所述对象(1204、1206、1212、1214)的特性的指令(1502到1532、1702到1728);
从所述产品配置数据(2100)、所述指令(1502 1532、1702到1728)、以及从所述源代码库(1200)中获得的数据(1800)中开发(700)配置状态数据(1900);
利用一个图形用户界面(200),检查一个表示了该最终产品(1106)的配置状态数据(1900)的可视逻辑表示,遗漏以及选择和取消选择的对象(1204、1206、1212、1214)以及选项(1524),并且提供命令来调整最终产品(1106);以及
在所述配置状态数据(1900)的控制下从所述源代码单元(1220、1224、1226、1300)中生成(800、1000、1102、3600)该最终产品(1106)。
84.如权利要求83所述的方法,包含:提供包含了至少一个源代码单元(1220、1224、1226、1300)以及一个包含所述指令(1502到1532、1702到1728)的对象信息数据集合(1400、1600)的所述对象(1204、1206、1212、1214)。
85.如权利要求83所述的方法,包含:提供至少一个是一个组件(1204、1206)的对象(1204、1206、1212、1214),其中该组件包含至少一个是一个特征(1204、1214)的对象(1204、1206、1212、1214)。
86.如权利要求83所述的方法,包含:向至少某些所述接口(1316、1322)和从属物(1312、1318、1324)分配名称(在1316处的“ERRORBEEP”、在1318处的“DELAY”)以及类(在1316处的“BEEP”、在1318处的“TIMER”)命名,并且在开发该最终产品(1106)之前用恰当的绝对地址替换它们。
87.如权利要求83所述的方法,包含:分配对象规格说明数据作为与至少某些从属物(1312、1318、1324)有关的数据的一部分,然后根据对象规格说明数据,优于其它具有相同标识符的接口(1316、1322),链接相应的从属物(1312、1318、1324)到在包含该指定对象(1204、1206、1212、1214)的一个源代码单元(1220、1224、1300)中的一个接口(1316、1322)。
88.如权利要求83所述的方法,包含:指定在一个RAM自由环境中运行的源代码单元(1220、1224、1226、1300),并且在调用或者跳转从属物(1312、1318、1324)处,产生(800、1000、1102、3600)修改的源代码单元(1220、1224、1226、1300),其模拟一个子程序跳转并且返回,而不需要一个基于RAM的子程序堆栈。
89.如权利要求83所述的方法,包含:当遇到一个取决于一个具有一个相应接口(1316、1322)的未选择对象(1204、1206、1212、1214)的存在的从属物(1312、1318、1324)时,自动地选择(700)所述对象(1204、1206、1212、1214)用于包含在最终产品(1106)中。
90.如权利要求83所述的方法,包含:为至少某些接口(1316、1322)添加截取命名,并且将一个从属物(1312、1318、1324)与一个具有一个截取命名的接口(1316、1322)关联(700),而优于其它同样命名的接口(1316、1322)。
91.如权利要求83所述的方法,包含:当面临由于没有选择一个对象(1204、1206、1212、1214)而导致没有相应接口(1316、1322)的从属物(1312、1318、1324)时,并且在那儿没有一个错误状态时,通过从源代码单元(1220、1224、1226、1300)中删除从属物(1312、1318、1324)来修改源代码单元(1220、1224、1226、1300)。
92.如权利要求83所述的方法,包含:利用图形用户界面(200)指示一个关于没有接口(1316、1322)的从属物(1312、1318、1324)的可视错误指示。
93.如权利要求83所述的方法,包含:指定一个对象(1204、1206、1212、1214)的选择由另一个对象(1204、1206、1212、1214)的选择触发;并且每当选择另一个对象(1204、1206、1212、1214)时,选择该一个对象(1204、1206、1212、1214)。
94.如权利要求83所述的方法,包含:在至少某些所述源代码单元(1220、1224、1226、1300)中提供列表单元(3704、3708、3710),然后通过把那些列表单元(3704、3708 3710)放在一起来修改该源代码单元(1220、1224、1226、1300),并且在一个指定点(3716)处把它们插入到最终产品(1106)里,并且建立到列表项引用的链接。
95.如权利要求83所述的方法,包含:声明某些接口(1316、1322)为公共的,并且使它们可由在任何对象(1204、1206、1212、1214)中的任何从属物(1312、1318、1324)访问,并且声明其它接口(1316、1322)为私有的,并且使它们仅仅由在同一个对象(1204、1206、1212、1214)内的从属物(1312、1318、1324)访问。
96.如权利要求83所述的方法,包含:增加至少某些字符串单元(4002)到至少某些所述源代码单元(1220、1224、1226、1300)中,定义该字符串的文本(在图40中的“STR TEXT”)以及语言(在图40中的“STR LANGUAGE”),并且插入利用被放置到非易失性存储器3902里的一个值3904允许选择恰当语言字符串的代码。
97.如权利要求83所述的方法,包含:向所述产品配置数据(2100)添加定义了要被构造的平台类型(在2102处的“DESKTOP”)的数据。
98.如权利要求83所述的方法,包含:提供至少某些越权数据(在图42中的“REGISTER TABLE ENTRY#_2 OVERRIDE DATA”),以及让它替换在一个数据表(在图42中的“ENTRY#_1 ENTRY#_2 ENTRY#_3 ENTRY#_4”)中的某些数据项。
99.如权利要求所述的方法,包含:继汇编或者编译之后,在分开编译的可执行代码块和分别链接的可执行代码块之间建立内部段链接。
100.如权利要求83所述的方法,包含:在所述源代码库(1200)中指定某些代码单元3904注定要驻留在非易失性存储器3902中,并且以后为这种单元3904的存储分配非易失性存储器3902,以及以这样的方式在最终产品(1106)里插入必要的代码以给予程序对这种变量(3904)的访问(3906、3908),使得系统设计员不必关心该非易失性存储器3902的特性。
101.如权利要求83所述的方法,包含:使用所述图形用户界面(200)来查看和修改对象(1204、1206、1212、1214)的源代码单元(1220、1224、1226、1300)。
102.如权利要求83所述的方法,包含:利用宏指令(1502到1532、1702到1728)标识接口(1316、1322)和从属物(1312、1318、1324),然后通过在配置状态数据(1900)的控制下执行宏程序(3806)来执行代码修改,并且使用标准的汇编器、编译器、和链接器1102来汇编或者编译以及链接该源代码单元。
CN 00816143 1999-09-24 2000-09-22 便于组件选择的软件开发系统 Pending CN1399737A (zh)

Applications Claiming Priority (4)

Application Number Priority Date Filing Date Title
US09/404,298 1999-09-24
US09/404,298 US6487713B1 (en) 1999-09-24 1999-09-24 Software development system that presents a logical view of project components, facilitates their selection, and signals missing links prior to compilation
US53167800A 2000-03-20 2000-03-20
US09/531,678 2000-03-20

Publications (1)

Publication Number Publication Date
CN1399737A true CN1399737A (zh) 2003-02-26

Family

ID=27018590

Family Applications (1)

Application Number Title Priority Date Filing Date
CN 00816143 Pending CN1399737A (zh) 1999-09-24 2000-09-22 便于组件选择的软件开发系统

Country Status (4)

Country Link
CN (1) CN1399737A (zh)
GB (1) GB2371134B (zh)
TW (1) TW523685B (zh)
WO (1) WO2001023998A1 (zh)

Cited By (11)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN100375956C (zh) * 2004-10-19 2008-03-19 国际商业机器公司 在运行时选择图形组件类型的系统和方法
CN104077128A (zh) * 2014-06-09 2014-10-01 中国建设银行股份有限公司 一种数据处理方法及装置
CN106502736A (zh) * 2016-10-18 2017-03-15 腾讯科技(深圳)有限公司 应用程序处理方法和装置
WO2017193640A1 (zh) * 2016-05-07 2017-11-16 腾讯科技(深圳)有限公司 应用更新方法和装置
CN107894945A (zh) * 2017-11-17 2018-04-10 深圳市泉眼网络科技有限公司 埋点添加方法、移动终端及计算机可读存储介质
CN109828752A (zh) * 2018-12-14 2019-05-31 平安科技(深圳)有限公司 项目代码自动生成方法、装置、计算机设备及存储介质
CN111722846A (zh) * 2020-05-29 2020-09-29 苏州浪潮智能科技有限公司 一种兼容多种oem产品的cim接口定制的方法和设备
CN112558975A (zh) * 2020-12-17 2021-03-26 北京奇艺世纪科技有限公司 组件的代码切换方法、装置、电子设备及可读存储介质
CN113688152A (zh) * 2021-08-30 2021-11-23 北京京东振世信息技术有限公司 一种系统功能自校验方法和装置
CN114926143A (zh) * 2022-05-16 2022-08-19 三峡高科信息技术有限责任公司 基于业务组件和流程引擎的配置企业工作流的方法及平台
CN117251143A (zh) * 2023-11-14 2023-12-19 武汉万云网络科技有限公司 一种应用系统、构建方法及其可视化开发工具的实现方法

Families Citing this family (16)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
EP1338959A1 (en) * 2002-02-15 2003-08-27 Karin Henriette Hackin Fernandez Universal customisation tool for providing customised computer programs
TWI402693B (zh) * 2006-12-22 2013-07-21 Hon Hai Prec Ind Co Ltd 檔案版本管控介面裝置及方法
WO2012054786A1 (en) 2010-10-20 2012-04-26 Playspan Inc. Flexible monetization service apparatuses, methods and systems
US11216468B2 (en) 2015-02-08 2022-01-04 Visa International Service Association Converged merchant processing apparatuses, methods and systems
US10241769B2 (en) 2016-12-14 2019-03-26 International Business Machines Corporation Marking sibling caller routines
US10152338B2 (en) 2016-12-14 2018-12-11 International Business Machines Corporation Marking external sibling caller routines
US10180827B2 (en) 2016-12-14 2019-01-15 International Business Machines Corporation Suppressing storing of context information
US10095493B2 (en) 2016-12-14 2018-10-09 International Business Machines Corporation Call sequence generation based on type of routine
US20180165073A1 (en) 2016-12-14 2018-06-14 International Business Machines Corporation Context information based on type of routine being called
US10235190B2 (en) 2016-12-14 2019-03-19 International Business Machines Corporation Executing instructions to store context information based on routine to be executed
CN111984248B (zh) * 2019-05-22 2023-08-25 腾讯科技(深圳)有限公司 页面编辑方法和装置、存储介质及电子装置
CN112783515B (zh) * 2021-02-08 2023-08-25 腾讯科技(深圳)有限公司 插件的控制方法和装置、存储介质
US11442706B1 (en) * 2021-05-27 2022-09-13 Mastercard Technologies Canada ULC Developing software products using reusable code artifacts
CN113419759A (zh) * 2021-06-21 2021-09-21 广联达科技股份有限公司 文件升级方法、装置及电子设备
US11972237B1 (en) * 2023-01-09 2024-04-30 Microsoft Technology Licensing, Llc Member invocation declarative interception
US20240272881A1 (en) * 2023-02-10 2024-08-15 Aquafadas S.A.S.U. System, method and computer program for managing functional interface component design in application builder

Family Cites Families (3)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US5325533A (en) * 1993-06-28 1994-06-28 Taligent, Inc. Engineering system for modeling computer programs
CA2128387C (en) * 1993-08-23 1999-12-28 Daniel F. Hurley Method and apparatus for configuring computer programs from available subprograms
US5950209A (en) * 1996-10-02 1999-09-07 Alcatel Usa Sourcing, L.P. Software release control system and method

Cited By (22)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN100375956C (zh) * 2004-10-19 2008-03-19 国际商业机器公司 在运行时选择图形组件类型的系统和方法
CN104077128A (zh) * 2014-06-09 2014-10-01 中国建设银行股份有限公司 一种数据处理方法及装置
CN104077128B (zh) * 2014-06-09 2017-07-11 中国建设银行股份有限公司 一种数据处理方法及装置
WO2017193640A1 (zh) * 2016-05-07 2017-11-16 腾讯科技(深圳)有限公司 应用更新方法和装置
US10871953B2 (en) 2016-05-07 2020-12-22 Tencent Technology (Shenzhen) Company Limited Application update method and apparatus
US10831567B2 (en) 2016-10-18 2020-11-10 Tencent Technology (Shenzhen) Company Limited Application processing method and apparatus
CN106502736A (zh) * 2016-10-18 2017-03-15 腾讯科技(深圳)有限公司 应用程序处理方法和装置
WO2018072634A1 (zh) * 2016-10-18 2018-04-26 腾讯科技(深圳)有限公司 应用程序处理方法和装置
US11269696B2 (en) 2016-10-18 2022-03-08 Tencent Technology (Shenzhen) Company Limited Application processing method and apparatus
CN107894945A (zh) * 2017-11-17 2018-04-10 深圳市泉眼网络科技有限公司 埋点添加方法、移动终端及计算机可读存储介质
CN109828752A (zh) * 2018-12-14 2019-05-31 平安科技(深圳)有限公司 项目代码自动生成方法、装置、计算机设备及存储介质
CN109828752B (zh) * 2018-12-14 2024-01-02 平安科技(深圳)有限公司 项目代码自动生成方法、装置、计算机设备及存储介质
CN111722846A (zh) * 2020-05-29 2020-09-29 苏州浪潮智能科技有限公司 一种兼容多种oem产品的cim接口定制的方法和设备
CN111722846B (zh) * 2020-05-29 2022-05-31 苏州浪潮智能科技有限公司 一种兼容多种oem产品的cim接口定制的方法和设备
CN112558975A (zh) * 2020-12-17 2021-03-26 北京奇艺世纪科技有限公司 组件的代码切换方法、装置、电子设备及可读存储介质
CN112558975B (zh) * 2020-12-17 2023-09-01 北京奇艺世纪科技有限公司 组件的代码切换方法、装置、电子设备及可读存储介质
CN113688152A (zh) * 2021-08-30 2021-11-23 北京京东振世信息技术有限公司 一种系统功能自校验方法和装置
CN113688152B (zh) * 2021-08-30 2023-12-05 北京京东振世信息技术有限公司 一种系统功能自校验方法和装置
CN114926143A (zh) * 2022-05-16 2022-08-19 三峡高科信息技术有限责任公司 基于业务组件和流程引擎的配置企业工作流的方法及平台
CN114926143B (zh) * 2022-05-16 2022-11-08 三峡高科信息技术有限责任公司 基于业务组件和流程引擎的配置企业工作流的方法及平台
CN117251143A (zh) * 2023-11-14 2023-12-19 武汉万云网络科技有限公司 一种应用系统、构建方法及其可视化开发工具的实现方法
CN117251143B (zh) * 2023-11-14 2024-02-06 武汉万云网络科技有限公司 一种应用系统、构建方法及其可视化开发工具的实现方法

Also Published As

Publication number Publication date
GB0208207D0 (en) 2002-05-22
GB2371134B (en) 2003-12-17
TW523685B (en) 2003-03-11
GB2371134A (en) 2002-07-17
WO2001023998A1 (en) 2001-04-05

Similar Documents

Publication Publication Date Title
CN1399737A (zh) 便于组件选择的软件开发系统
CN1096637C (zh) 管理类方法名
CN1959631A (zh) 一种基于itron的应用软件自主装配技术
CN1073276A (zh) 语言的中性对象
CN1182467C (zh) 可扩充的分布企业应用集成系统
CN1130626C (zh) 支援并行程序的装置以及支持程序编制的方法
CN1321275A (zh) 与源代码控制系统交互的方法和设备
CN1524216A (zh) 软件构件插件程序结构的系统和方法
CN1578949A (zh) 数据对象导向的储存系统
CN1828527A (zh) 用于跨不同应用程序框架的数据服务的平台
CN1838165A (zh) 工作项跟踪系统的工作项规则
CN1359489A (zh) 用于构筑建模工具的装置和方法
CN1834908A (zh) 用于将开发模式应用于基于组件的应用程序的系统和方法
CN1551006A (zh) 分布式计算系统架构及分布式应用的设计、部署和管理
CN1739107A (zh) 为可由硬件/软件接口系统管理的信息单元提供同步服务的系统和方法
CN1828517A (zh) 文档处理装置和文档处理方法
CN1961294A (zh) 为可由硬件/软件接口系统管理的信息单元提供关系和分层同步服务的系统和方法
CN1063168A (zh) 并行处理装置
CN1797399A (zh) 用于文本挖掘和搜索的应用程序编程接口
CN1609795A (zh) 用于计算机平台的编程接口
CN1755721A (zh) 组件化和可扩展的工作流模型
CN1833240A (zh) 维护包内部件之间的关系的方法和装置
CN1601510A (zh) 分布式计算系统的架构和分布式应用程序的自动设计,部署及管理
CN1781078A (zh) 硬件加速器个性编译器
CN1679026A (zh) Web服务设备和方法

Legal Events

Date Code Title Description
C06 Publication
PB01 Publication
C10 Entry into substantive examination
SE01 Entry into force of request for substantive examination
C02 Deemed withdrawal of patent application after publication (patent law 2001)
WD01 Invention patent application deemed withdrawn after publication