Annotation of src/sys/external/bsd/acpica/dist/compiler/dtcompile.c, Revision 1.7
1.1 jruoho 1: /******************************************************************************
2: *
3: * Module Name: dtcompile.c - Front-end for data table compiler
4: *
5: *****************************************************************************/
6:
1.2 christos 7: /*
1.7 ! christos 8: * Copyright (C) 2000 - 2016, Intel Corp.
1.1 jruoho 9: * All rights reserved.
10: *
1.2 christos 11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions, and the following disclaimer,
16: * without modification.
17: * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18: * substantially similar to the "NO WARRANTY" disclaimer below
19: * ("Disclaimer") and any redistribution must be conditioned upon
20: * including a substantially similar Disclaimer requirement for further
21: * binary redistribution.
22: * 3. Neither the names of the above-listed copyright holders nor the names
23: * of any contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * Alternatively, this software may be distributed under the terms of the
27: * GNU General Public License ("GPL") version 2 as published by the Free
28: * Software Foundation.
29: *
30: * NO WARRANTY
31: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41: * POSSIBILITY OF SUCH DAMAGES.
42: */
1.1 jruoho 43:
44: #define _DECLARE_DT_GLOBALS
45:
46: #include "aslcompiler.h"
47: #include "dtcompiler.h"
48:
49: #define _COMPONENT DT_COMPILER
50: ACPI_MODULE_NAME ("dtcompile")
51:
52: static char VersionString[9];
53:
54:
55: /* Local prototypes */
56:
1.2 christos 57: static ACPI_STATUS
1.1 jruoho 58: DtInitialize (
59: void);
60:
61: static ACPI_STATUS
62: DtCompileDataTable (
63: DT_FIELD **Field);
64:
65: static void
66: DtInsertCompilerIds (
67: DT_FIELD *FieldList);
68:
69:
70: /******************************************************************************
71: *
72: * FUNCTION: DtDoCompile
73: *
74: * PARAMETERS: None
75: *
76: * RETURN: Status
77: *
78: * DESCRIPTION: Main entry point for the data table compiler.
79: *
80: * Note: Assumes Gbl_Files[ASL_FILE_INPUT] is initialized and the file is
81: * open at seek offset zero.
82: *
83: *****************************************************************************/
84:
85: ACPI_STATUS
86: DtDoCompile (
87: void)
88: {
89: ACPI_STATUS Status;
90: UINT8 Event;
91: DT_FIELD *FieldList;
92:
93:
94: /* Initialize globals */
95:
1.2 christos 96: Status = DtInitialize ();
97: if (ACPI_FAILURE (Status))
98: {
99: printf ("Error during compiler initialization, 0x%X\n", Status);
100: return (Status);
101: }
102:
103: /* Preprocessor */
104:
1.5 christos 105: if (Gbl_PreprocessFlag)
106: {
107: /* Preprocessor */
108:
109: Event = UtBeginEvent ("Preprocess input file");
110: PrDoPreprocess ();
111: UtEndEvent (Event);
1.2 christos 112:
1.5 christos 113: if (Gbl_PreprocessOnly)
114: {
115: return (AE_OK);
116: }
1.2 christos 117: }
1.1 jruoho 118:
119: /*
120: * Scan the input file (file is already open) and
121: * build the parse tree
122: */
123: Event = UtBeginEvent ("Scan and parse input file");
124: FieldList = DtScanFile (Gbl_Files[ASL_FILE_INPUT].Handle);
125: UtEndEvent (Event);
126:
127: /* Did the parse tree get successfully constructed? */
128:
129: if (!FieldList)
130: {
131: /* TBD: temporary error message. Msgs should come from function above */
132:
133: DtError (ASL_ERROR, ASL_MSG_SYNTAX, NULL,
1.2 christos 134: "Input file does not appear to be an ASL or data table source file");
135:
136: Status = AE_ERROR;
137: goto CleanupAndExit;
1.1 jruoho 138: }
139:
140: Event = UtBeginEvent ("Compile parse tree");
141:
142: /*
143: * Compile the parse tree
144: */
145: Status = DtCompileDataTable (&FieldList);
146: UtEndEvent (Event);
147:
148: if (ACPI_FAILURE (Status))
149: {
150: /* TBD: temporary error message. Msgs should come from function above */
151:
152: DtError (ASL_ERROR, ASL_MSG_SYNTAX, NULL,
153: "Could not compile input file");
1.2 christos 154:
1.1 jruoho 155: goto CleanupAndExit;
156: }
157:
158: /* Create/open the binary output file */
159:
160: Gbl_Files[ASL_FILE_AML_OUTPUT].Filename = NULL;
161: Status = FlOpenAmlOutputFile (Gbl_OutputFilenamePrefix);
162: if (ACPI_FAILURE (Status))
163: {
164: goto CleanupAndExit;
165: }
166:
167: /* Write the binary, then the optional hex file */
168:
169: DtOutputBinary (Gbl_RootTable);
1.2 christos 170: HxDoHexOutput ();
171: DtWriteTableToListing ();
1.1 jruoho 172:
173: CleanupAndExit:
174:
1.4 christos 175: AcpiUtDeleteCaches ();
176: DtDeleteCaches ();
1.1 jruoho 177: CmCleanupAndExit ();
178: return (Status);
179: }
180:
181:
182: /******************************************************************************
183: *
184: * FUNCTION: DtInitialize
185: *
186: * PARAMETERS: None
187: *
1.2 christos 188: * RETURN: Status
1.1 jruoho 189: *
190: * DESCRIPTION: Initialize data table compiler globals. Enables multiple
191: * compiles per invocation.
192: *
193: *****************************************************************************/
194:
1.2 christos 195: static ACPI_STATUS
1.1 jruoho 196: DtInitialize (
197: void)
198: {
1.2 christos 199: ACPI_STATUS Status;
200:
201:
202: Status = AcpiOsInitialize ();
203: if (ACPI_FAILURE (Status))
204: {
205: return (Status);
206: }
207:
208: Status = AcpiUtInitGlobals ();
209: if (ACPI_FAILURE (Status))
210: {
211: return (Status);
212: }
1.1 jruoho 213:
214: Gbl_FieldList = NULL;
215: Gbl_RootTable = NULL;
216: Gbl_SubtableStack = NULL;
217:
1.3 tron 218: snprintf (VersionString, sizeof(VersionString), "%X",
1.2 christos 219: (UINT32) ACPI_CA_VERSION);
220: return (AE_OK);
1.1 jruoho 221: }
222:
223:
224: /******************************************************************************
225: *
226: * FUNCTION: DtInsertCompilerIds
227: *
228: * PARAMETERS: FieldList - Current field list pointer
229: *
230: * RETURN: None
231: *
232: * DESCRIPTION: Insert the IDs (Name, Version) of the current compiler into
233: * the original ACPI table header.
234: *
235: *****************************************************************************/
236:
237: static void
238: DtInsertCompilerIds (
239: DT_FIELD *FieldList)
240: {
241: DT_FIELD *Next;
242: UINT32 i;
243:
244:
245: /*
246: * Don't insert current compiler ID if requested. Used for compiler
247: * debug/validation only.
248: */
249: if (Gbl_UseOriginalCompilerId)
250: {
251: return;
252: }
253:
254: /* Walk to the Compiler fields at the end of the header */
255:
256: Next = FieldList;
257: for (i = 0; i < 7; i++)
258: {
259: Next = Next->Next;
260: }
261:
1.2 christos 262: Next->Value = ASL_CREATOR_ID;
1.1 jruoho 263: Next->Flags = DT_FIELD_NOT_ALLOCATED;
264:
265: Next = Next->Next;
266: Next->Value = VersionString;
267: Next->Flags = DT_FIELD_NOT_ALLOCATED;
268: }
269:
270:
271: /******************************************************************************
272: *
273: * FUNCTION: DtCompileDataTable
274: *
275: * PARAMETERS: FieldList - Current field list pointer
276: *
277: * RETURN: Status
278: *
279: * DESCRIPTION: Entry point to compile one data table
280: *
281: *****************************************************************************/
282:
283: static ACPI_STATUS
284: DtCompileDataTable (
285: DT_FIELD **FieldList)
286: {
1.6 christos 287: const ACPI_DMTABLE_DATA *TableData;
1.1 jruoho 288: DT_SUBTABLE *Subtable;
289: char *Signature;
290: ACPI_TABLE_HEADER *AcpiTableHeader;
291: ACPI_STATUS Status;
1.2 christos 292: DT_FIELD *RootField = *FieldList;
1.1 jruoho 293:
294:
295: /* Verify that we at least have a table signature and save it */
296:
1.2 christos 297: Signature = DtGetFieldValue (*FieldList);
1.1 jruoho 298: if (!Signature)
299: {
1.2 christos 300: snprintf (MsgBuffer, sizeof(MsgBuffer), "Expected \"%s\"", "Signature");
301: DtNameError (ASL_ERROR, ASL_MSG_INVALID_FIELD_NAME,
302: *FieldList, MsgBuffer);
1.1 jruoho 303: return (AE_ERROR);
304: }
305:
1.6 christos 306: Gbl_Signature = UtStringCacheCalloc (strlen (Signature) + 1);
1.1 jruoho 307: strcpy (Gbl_Signature, Signature);
308:
309: /*
310: * Handle tables that don't use the common ACPI table header structure.
311: * Currently, these are the FACS and RSDP. Also check for an OEMx table,
312: * these tables have user-defined contents.
313: */
314: if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
315: {
316: Status = DtCompileFacs (FieldList);
317: if (ACPI_FAILURE (Status))
318: {
319: return (Status);
320: }
321:
322: DtSetTableLength ();
323: return (Status);
324: }
1.2 christos 325: else if (ACPI_VALIDATE_RSDP_SIG (Signature))
1.1 jruoho 326: {
327: Status = DtCompileRsdp (FieldList);
328: return (Status);
329: }
1.2 christos 330: else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_S3PT))
1.1 jruoho 331: {
1.2 christos 332: Status = DtCompileS3pt (FieldList);
333: if (ACPI_FAILURE (Status))
334: {
335: return (Status);
336: }
337:
338: DtSetTableLength ();
339: return (Status);
1.1 jruoho 340: }
341:
342: /*
343: * All other tables must use the common ACPI table header. Insert the
344: * current iASL IDs (name, version), and compile the header now.
345: */
346: DtInsertCompilerIds (*FieldList);
347:
348: Status = DtCompileTable (FieldList, AcpiDmTableInfoHeader,
1.7 ! christos 349: &Gbl_RootTable, TRUE);
1.1 jruoho 350: if (ACPI_FAILURE (Status))
351: {
352: return (Status);
353: }
354:
355: DtPushSubtable (Gbl_RootTable);
356:
1.2 christos 357: /* Validate the signature via the ACPI table list */
1.1 jruoho 358:
359: TableData = AcpiDmGetTableData (Signature);
1.2 christos 360: if (!TableData || Gbl_CompileGeneric)
1.1 jruoho 361: {
1.6 christos 362: /* Unknown table signature and/or force generic compile */
363:
364: DtCompileGeneric ((void **) FieldList, NULL, NULL);
1.2 christos 365: goto FinishHeader;
1.1 jruoho 366: }
367:
1.2 christos 368: /* Dispatch to per-table compile */
369:
1.1 jruoho 370: if (TableData->CmTableHandler)
371: {
372: /* Complex table, has a handler */
373:
374: Status = TableData->CmTableHandler ((void **) FieldList);
375: if (ACPI_FAILURE (Status))
376: {
377: return (Status);
378: }
379: }
380: else if (TableData->TableInfo)
381: {
382: /* Simple table, just walk the info table */
383:
384: Subtable = NULL;
385: Status = DtCompileTable (FieldList, TableData->TableInfo,
1.7 ! christos 386: &Subtable, TRUE);
1.1 jruoho 387: if (ACPI_FAILURE (Status))
388: {
389: return (Status);
390: }
391:
392: DtInsertSubtable (Gbl_RootTable, Subtable);
393: DtPopSubtable ();
394: }
395: else
396: {
397: DtFatal (ASL_MSG_COMPILER_INTERNAL, *FieldList,
398: "Missing table dispatch info");
399: return (AE_ERROR);
400: }
401:
1.2 christos 402: FinishHeader:
403:
1.1 jruoho 404: /* Set the final table length and then the checksum */
405:
406: DtSetTableLength ();
407: AcpiTableHeader = ACPI_CAST_PTR (
408: ACPI_TABLE_HEADER, Gbl_RootTable->Buffer);
409: DtSetTableChecksum (&AcpiTableHeader->Checksum);
410:
1.2 christos 411: DtDumpFieldList (RootField);
412: DtDumpSubtableList ();
1.1 jruoho 413: return (AE_OK);
414: }
415:
416:
417: /******************************************************************************
418: *
419: * FUNCTION: DtCompileTable
420: *
421: * PARAMETERS: Field - Current field list pointer
422: * Info - Info table for this ACPI table
423: * RetSubtable - Compile result of table
424: * Required - If this subtable must exist
425: *
426: * RETURN: Status
427: *
428: * DESCRIPTION: Compile a subtable
429: *
430: *****************************************************************************/
431:
432: ACPI_STATUS
433: DtCompileTable (
434: DT_FIELD **Field,
435: ACPI_DMTABLE_INFO *Info,
436: DT_SUBTABLE **RetSubtable,
437: BOOLEAN Required)
438: {
439: DT_FIELD *LocalField;
440: UINT32 Length;
441: DT_SUBTABLE *Subtable;
1.6 christos 442: DT_SUBTABLE *InlineSubtable = NULL;
1.1 jruoho 443: UINT32 FieldLength = 0;
444: UINT8 FieldType;
445: UINT8 *Buffer;
446: UINT8 *FlagBuffer = NULL;
1.4 christos 447: char *String;
1.2 christos 448: UINT32 CurrentFlagByteOffset = 0;
1.6 christos 449: ACPI_STATUS Status = AE_OK;
1.1 jruoho 450:
451:
452: if (!Field || !*Field)
453: {
454: return (AE_BAD_PARAMETER);
455: }
456:
1.2 christos 457: /* Ignore optional subtable if name does not match */
458:
459: if ((Info->Flags & DT_OPTIONAL) &&
1.6 christos 460: strcmp ((*Field)->Name, Info->Name))
1.2 christos 461: {
462: *RetSubtable = NULL;
463: return (AE_OK);
464: }
465:
1.1 jruoho 466: Length = DtGetSubtableLength (*Field, Info);
1.2 christos 467: if (Length == ASL_EOF)
468: {
469: return (AE_ERROR);
470: }
471:
1.4 christos 472: Subtable = UtSubtableCacheCalloc ();
1.1 jruoho 473:
1.2 christos 474: if (Length > 0)
475: {
1.4 christos 476: String = UtStringCacheCalloc (Length);
477: Subtable->Buffer = ACPI_CAST_PTR (UINT8, String);
1.2 christos 478: }
1.4 christos 479:
1.1 jruoho 480: Subtable->Length = Length;
481: Subtable->TotalLength = Length;
482: Buffer = Subtable->Buffer;
483:
484: LocalField = *Field;
1.6 christos 485: Subtable->Name = LocalField->Name;
1.1 jruoho 486:
487: /*
488: * Main loop walks the info table for this ACPI table or subtable
489: */
490: for (; Info->Name; Info++)
491: {
1.2 christos 492: if (Info->Opcode == ACPI_DMT_EXTRA_TEXT)
493: {
494: continue;
495: }
496:
1.1 jruoho 497: if (!LocalField)
498: {
1.2 christos 499: snprintf (MsgBuffer, sizeof(MsgBuffer), "Found NULL field - Field name \"%s\" needed",
1.1 jruoho 500: Info->Name);
501: DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
502: Status = AE_BAD_DATA;
503: goto Error;
504: }
505:
1.2 christos 506: /* Maintain table offsets */
1.1 jruoho 507:
1.2 christos 508: LocalField->TableOffset = Gbl_CurrentTableOffset;
509: FieldLength = DtGetFieldLength (LocalField, Info);
510: Gbl_CurrentTableOffset += FieldLength;
1.1 jruoho 511:
512: FieldType = DtGetFieldType (Info);
513: Gbl_InputFieldCount++;
514:
515: switch (FieldType)
516: {
517: case DT_FIELD_TYPE_FLAGS_INTEGER:
518: /*
519: * Start of the definition of a flags field.
520: * This master flags integer starts at value zero, in preparation
521: * to compile and insert the flag fields from the individual bits
522: */
523: LocalField = LocalField->Next;
524: *Field = LocalField;
525:
526: FlagBuffer = Buffer;
1.2 christos 527: CurrentFlagByteOffset = Info->Offset;
1.1 jruoho 528: break;
529:
530: case DT_FIELD_TYPE_FLAG:
531:
532: /* Individual Flag field, can be multiple bits */
533:
534: if (FlagBuffer)
535: {
1.2 christos 536: /*
537: * We must increment the FlagBuffer when we have crossed
538: * into the next flags byte within the flags field
539: * of type DT_FIELD_TYPE_FLAGS_INTEGER.
540: */
541: FlagBuffer += (Info->Offset - CurrentFlagByteOffset);
542: CurrentFlagByteOffset = Info->Offset;
543:
544: DtCompileFlag (FlagBuffer, LocalField, Info);
1.1 jruoho 545: }
546: else
547: {
548: /* TBD - this is an internal error */
549: }
550:
551: LocalField = LocalField->Next;
552: *Field = LocalField;
553: break;
554:
555: case DT_FIELD_TYPE_INLINE_SUBTABLE:
556: /*
557: * Recursion (one level max): compile GAS (Generic Address)
558: * or Notify in-line subtable
559: */
560: *Field = LocalField;
561:
1.6 christos 562: switch (Info->Opcode)
1.1 jruoho 563: {
1.6 christos 564: case ACPI_DMT_GAS:
565:
1.1 jruoho 566: Status = DtCompileTable (Field, AcpiDmTableInfoGas,
567: &InlineSubtable, TRUE);
1.6 christos 568: break;
569:
570: case ACPI_DMT_HESTNTFY:
571:
1.1 jruoho 572: Status = DtCompileTable (Field, AcpiDmTableInfoHestNotify,
573: &InlineSubtable, TRUE);
1.6 christos 574: break;
575:
576: case ACPI_DMT_IORTMEM:
577:
578: Status = DtCompileTable (Field, AcpiDmTableInfoIortAcc,
579: &InlineSubtable, TRUE);
580: break;
581:
582: default:
583: sprintf (MsgBuffer, "Invalid DMT opcode: 0x%.2X",
584: Info->Opcode);
585: DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
586: Status = AE_BAD_DATA;
587: break;
1.1 jruoho 588: }
589:
590: if (ACPI_FAILURE (Status))
591: {
592: goto Error;
593: }
594:
1.2 christos 595: DtSetSubtableLength (InlineSubtable);
596:
1.6 christos 597: memcpy (Buffer, InlineSubtable->Buffer, FieldLength);
1.1 jruoho 598: LocalField = *Field;
599: break;
600:
1.2 christos 601: case DT_FIELD_TYPE_LABEL:
602:
603: DtWriteFieldToListing (Buffer, LocalField, 0);
604: LocalField = LocalField->Next;
605: break;
606:
1.1 jruoho 607: default:
608:
609: /* Normal case for most field types (Integer, String, etc.) */
610:
611: DtCompileOneField (Buffer, LocalField,
612: FieldLength, FieldType, Info->Flags);
1.2 christos 613:
614: DtWriteFieldToListing (Buffer, LocalField, FieldLength);
1.1 jruoho 615: LocalField = LocalField->Next;
616:
617: if (Info->Flags & DT_LENGTH)
618: {
619: /* Field is an Integer that will contain a subtable length */
620:
621: Subtable->LengthField = Buffer;
622: Subtable->SizeOfLengthField = FieldLength;
623: }
624: break;
625: }
626:
627: Buffer += FieldLength;
628: }
629:
630: *Field = LocalField;
631: *RetSubtable = Subtable;
632: return (AE_OK);
633:
634: Error:
635: ACPI_FREE (Subtable->Buffer);
636: ACPI_FREE (Subtable);
637: return (Status);
638: }
1.6 christos 639:
640:
641: /******************************************************************************
642: *
1.7 ! christos 643: * FUNCTION: DtCompileTwoSubtables
! 644: *
! 645: * PARAMETERS: List - Current field list pointer
! 646: * TableInfo1 - Info table 1
! 647: * TableInfo1 - Info table 2
! 648: *
! 649: * RETURN: Status
! 650: *
! 651: * DESCRIPTION: Compile tables with a header and one or more same subtables.
! 652: * Include CPEP, EINJ, ERST, MCFG, MSCT, WDAT
! 653: *
! 654: *****************************************************************************/
! 655:
! 656: ACPI_STATUS
! 657: DtCompileTwoSubtables (
! 658: void **List,
! 659: ACPI_DMTABLE_INFO *TableInfo1,
! 660: ACPI_DMTABLE_INFO *TableInfo2)
! 661: {
! 662: ACPI_STATUS Status;
! 663: DT_SUBTABLE *Subtable;
! 664: DT_SUBTABLE *ParentTable;
! 665: DT_FIELD **PFieldList = (DT_FIELD **) List;
! 666:
! 667:
! 668: Status = DtCompileTable (PFieldList, TableInfo1, &Subtable, TRUE);
! 669: if (ACPI_FAILURE (Status))
! 670: {
! 671: return (Status);
! 672: }
! 673:
! 674: ParentTable = DtPeekSubtable ();
! 675: DtInsertSubtable (ParentTable, Subtable);
! 676:
! 677: while (*PFieldList)
! 678: {
! 679: Status = DtCompileTable (PFieldList, TableInfo2, &Subtable, FALSE);
! 680: if (ACPI_FAILURE (Status))
! 681: {
! 682: return (Status);
! 683: }
! 684:
! 685: DtInsertSubtable (ParentTable, Subtable);
! 686: }
! 687:
! 688: return (AE_OK);
! 689: }
! 690:
! 691:
! 692: /******************************************************************************
! 693: *
1.6 christos 694: * FUNCTION: DtCompilePadding
695: *
696: * PARAMETERS: Length - Padding field size
697: * RetSubtable - Compile result of table
698: *
699: * RETURN: Status
700: *
701: * DESCRIPTION: Compile a subtable for padding purpose
702: *
703: *****************************************************************************/
704:
705: ACPI_STATUS
706: DtCompilePadding (
707: UINT32 Length,
708: DT_SUBTABLE **RetSubtable)
709: {
710: DT_SUBTABLE *Subtable;
711: /* UINT8 *Buffer; */
712: char *String;
713:
714:
715: Subtable = UtSubtableCacheCalloc ();
716:
717: if (Length > 0)
718: {
719: String = UtStringCacheCalloc (Length);
720: Subtable->Buffer = ACPI_CAST_PTR (UINT8, String);
721: }
722:
723: Subtable->Length = Length;
724: Subtable->TotalLength = Length;
725: /* Buffer = Subtable->Buffer; */
726:
727: *RetSubtable = Subtable;
728: return (AE_OK);
729: }
CVSweb <webmaster@jp.NetBSD.org>