Version 7.0
Copyright © 2021 Lowell D. Thomas
APG
… an ABNF Parser Generator
ast.c
Go to the documentation of this file.
1 /* *************************************************************************************
2  Copyright (c) 2021, Lowell D. Thomas
3  All rights reserved.
4 
5  This file is part of APG Version 7.0.
6  APG Version 7.0 may be used under the terms of the BSD 2-Clause License.
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions are met:
10 
11  1. Redistributions of source code must retain the above copyright notice, this
12  list of conditions and the following disclaimer.
13 
14  2. Redistributions in binary form must reproduce the above copyright notice,
15  this list of conditions and the following disclaimer in the documentation
16  and/or other materials provided with the distribution.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 * *************************************************************************************/
34 #include "./apg.h"
35 #ifdef APG_AST
36 #include "./lib.h"
37 #include "./parserp.h"
38 #include "./astp.h"
39 
40 static const void* s_vpMagicNumber = (void*)"ast";
41 
51 void* vpAstCtor(void* vpParserCtx){
52  if(!bParserValidate(vpParserCtx)){
53  vExContext();
54  return NULL; // should never return
55  }
56  parser* spParser = (parser*)vpParserCtx;
57  if(spParser->vpAst){
58  vAstDtor(spParser->vpAst);
59  spParser->vpAst = NULL;
60  }
61  ast* spCtx = NULL;
62  spCtx = (ast*)vpMemAlloc(spParser->vpMem, sizeof(ast));
63  memset((void*)spCtx, 0, sizeof(ast));
64  spCtx->spException = spMemException(spParser->vpMem);
65  spCtx->pfnRuleCallbacks = (ast_callback*)vpMemAlloc(spParser->vpMem, (sizeof(ast_callback) * spParser->uiRuleCount));
66  memset((void*)spCtx->pfnRuleCallbacks, 0, (sizeof(ast_callback) * spParser->uiRuleCount));
67  if(spParser->uiUdtCount){
68  spCtx->pfnUdtCallbacks = (ast_callback*)vpMemAlloc(spParser->vpMem, (sizeof(ast_callback) * spParser->uiUdtCount));
69  memset((void*)spCtx->pfnUdtCallbacks, 0, (sizeof(ast_callback) * spParser->uiUdtCount));
70  }
71  spCtx->vpVecThatStack = vpVecCtor(spParser->vpMem, sizeof(aint), 1000);
72  spCtx->vpVecOpenStack = vpVecCtor(spParser->vpMem, sizeof(aint), 100);
73  spCtx->vpVecRecords = vpVecCtor(spParser->vpMem, sizeof(ast_record), 1000);
74  // success
75  spCtx->spParser = spParser;
76  spParser->vpAst = (void*)spCtx;
77  spCtx->vpValidate = s_vpMagicNumber;
78  return (void*)spCtx;
79 }
80 
81 void vAstDtor(void* vpCtx){
82  ast* spCtx = (ast*)vpCtx;
83  if(vpCtx && (spCtx->vpValidate == s_vpMagicNumber)){
84  void* vpMem = spCtx->spParser->vpMem;
85  vMemFree(vpMem, spCtx->pfnRuleCallbacks);
86  if(spCtx->spParser->uiUdtCount){
87  vMemFree(vpMem, spCtx->pfnUdtCallbacks);
88  }
89  vVecDtor(spCtx->vpVecThatStack);
90  vVecDtor(spCtx->vpVecOpenStack);
91  vVecDtor(spCtx->vpVecRecords);
92  spCtx->spParser->vpAst = NULL;
93  memset((void*)spCtx, 0, sizeof(ast));
94  vMemFree(vpMem, spCtx);
95  }else{
96  vExContext();
97  }
98 }
99 
104 abool bAstValidate(void* vpCtx){
105  ast* spCtx = (ast*)vpCtx;
106  if(vpCtx && (spCtx->vpValidate == s_vpMagicNumber)){
107  return APG_TRUE;
108  }
109  return APG_FALSE;
110 }
111 
118 void vAstClear(void* vpCtx){
119  ast* spCtx = (ast*)vpCtx;
120  if(vpCtx){
121  if(spCtx->vpValidate == s_vpMagicNumber){
122  vVecClear(spCtx->vpVecThatStack);
123  vVecClear(spCtx->vpVecOpenStack);
124  vVecClear(spCtx->vpVecRecords);
125  }else{
126  vExContext();
127  }
128  }
129 }
130 
137 void vAstInfo(void* vpCtx, ast_info* spInfo){
138  ast* spCtx = (ast*)vpCtx;
139  if(vpCtx && (spCtx->vpValidate == s_vpMagicNumber)){
140  if(!spInfo){
141  XTHROW(spCtx->spException, "spInfo cannot be NULL");
142  }
143  spInfo->acpString = spCtx->spParser->acpInputString;
144  spInfo->uiStringLength = spCtx->spParser->uiInputStringLength;
145  spInfo->uiRuleCount = spCtx->spParser->uiRuleCount;
146  spInfo->uiUdtCount = spCtx->spParser->uiUdtCount;
147  spInfo->uiRecordCount = uiVecLen(spCtx->vpVecRecords);
148  spInfo->spRecords = (ast_record*)vpVecFirst(spCtx->vpVecRecords);
149  }else{
150  vExContext();
151  }
152 }
153 
165 void vAstTranslate(void* vpCtx, void* vpUserData){
166  ast* spCtx = (ast*)vpCtx;
167  if(vpCtx && (spCtx->vpValidate == s_vpMagicNumber)){
168  ast_record* spRecords = (ast_record*)vpVecFirst(spCtx->vpVecRecords);
169  if(spRecords){
170  aint uiRecords = uiVecLen(spCtx->vpVecRecords);
171  aint ui = 0;
172  ast_record* spRecord;
173  ast_data sData;
174  aint uiReturn;
175  sData.acpString = spCtx->spParser->acpInputString;
176  sData.uiStringLength = spCtx->spParser->uiInputStringLength;
177  sData.vpUserData = vpUserData;
178  sData.spException = spCtx->spException;
179  while( ui < uiRecords){
180  spRecord = &spRecords[ui];
181  sData.uiPhraseLength = spRecord->uiPhraseLength;
182  sData.uiPhraseOffset = spRecord->uiPhraseOffset;
183  sData.uiState = spRecord->uiState;
184  sData.cpName = spRecord->cpName;
185  sData.uiIndex = spRecord->uiIndex;
186  sData.bIsUdt = spRecord->bIsUdt;
187  uiReturn = ID_AST_OK;
188  if(spRecord->bIsUdt){
189  if(spCtx->pfnUdtCallbacks[spRecord->uiIndex]){
190  uiReturn = spCtx->pfnUdtCallbacks[spRecord->uiIndex](&sData);
191  }
192  }else{
193  if(spCtx->pfnRuleCallbacks[spRecord->uiIndex]){
194  uiReturn = spCtx->pfnRuleCallbacks[spRecord->uiIndex](&sData);
195  }
196  }
197  if(sData.uiState == ID_AST_PRE && uiReturn == ID_AST_SKIP){
198  ui = spRecord->uiThatRecord;
199  }else{
200  ui++;
201  }
202  }
203  }
204  }else{
205  vExContext();
206  }
207 }
208 
243 void vAstSetRuleCallback(void* vpCtx, aint uiRuleIndex, ast_callback pfnCallback){
244  ast* spCtx = (ast*)vpCtx;
245  if(vpCtx && (spCtx->vpValidate == s_vpMagicNumber)){
246  if(uiRuleIndex < spCtx->spParser->uiRuleCount){
247  spCtx->pfnRuleCallbacks[uiRuleIndex] = pfnCallback;
248  }else{
249  XTHROW(spCtx->spException, "rule index out of range");
250  }
251  }else{
252  vExContext();
253  }
254 }
255 
266 void vAstSetUdtCallback(void* vpCtx, aint uiUdtIndex, ast_callback pfnCallback){
267  ast* spCtx = (ast*)vpCtx;
268  if(vpCtx && (spCtx->vpValidate == s_vpMagicNumber)){
269  if(uiUdtIndex < spCtx->spParser->uiUdtCount){
270  spCtx->pfnUdtCallbacks[uiUdtIndex] = pfnCallback;
271  }else{
272  XTHROW(spCtx->spException, "UDT index out of range");
273  }
274  }else{
275  vExContext();
276  }
277 }
278 
286 void vAstRuleOpen(void* vpCtx, aint uiRuleIndex, aint uiPhraseOffset){
287  ast* spCtx = (ast*)vpCtx;
288  aint uiRecordCount = uiVecLen(spCtx->vpVecRecords);
289  vpVecPush(spCtx->vpVecOpenStack, (void*)&uiRecordCount);
290  aint uiIndex = uiRuleIndex;
291  abool bIsUdt = APG_FALSE;
292  if(uiRuleIndex >= spCtx->spParser->uiRuleCount){
293  uiIndex = uiRuleIndex - spCtx->spParser->uiRuleCount;
294  bIsUdt = APG_TRUE;
295  if(spCtx->pfnUdtCallbacks[uiIndex] == NULL){
296  return;
297  }
298  }else{
299  if(spCtx->pfnRuleCallbacks[uiIndex] == NULL){
300  return;
301  }
302  }
303  ast_record sRecord;
304  if(bIsUdt){
305  sRecord.cpName = spCtx->spParser->spUdts[uiIndex].cpUdtName;
306  }else{
307  sRecord.cpName = spCtx->spParser->spRules[uiIndex].cpRuleName;
308  }
309  sRecord.bIsUdt = bIsUdt;
310  sRecord.uiIndex = uiIndex;
311  sRecord.uiPhraseLength = APG_UNDEFINED;
312  sRecord.uiPhraseOffset = uiPhraseOffset;
313  sRecord.uiState = ID_AST_PRE;
314  sRecord.uiThatRecord = APG_UNDEFINED;
315  sRecord.uiThisRecord = uiVecLen(spCtx->vpVecRecords);
316  vpVecPush(spCtx->vpVecThatStack, (void*)&sRecord.uiThisRecord);
317  vpVecPush(spCtx->vpVecRecords, (void*)&sRecord);
318 }
319 
329 void vAstRuleClose(void* vpCtx, aint uiRuleIndex, aint uiState, aint uiPhraseOffset, aint uiPhraseLength){
330  ast* spCtx = (ast*)vpCtx;
331  aint* uipRecordCount = (aint*)vpVecPop(spCtx->vpVecOpenStack);
332  if(!uipRecordCount){
333  XTHROW(spCtx->spException, "AST open record stack should not be empty empty");
334  }
335  aint uiRecordCount = *uipRecordCount;
336  if(uiState == ID_MATCH){
337  aint uiIndex = uiRuleIndex;
338  abool bIsUdt = APG_FALSE;
339  if(uiRuleIndex >= spCtx->spParser->uiRuleCount){
340  uiIndex = uiRuleIndex - spCtx->spParser->uiRuleCount;
341  bIsUdt = APG_TRUE;
342  if(spCtx->pfnUdtCallbacks[uiIndex] == NULL){
343  return;
344  }
345  }else{
346  if(spCtx->pfnRuleCallbacks[uiIndex] == NULL){
347  return;
348  }
349  }
350  ast_record sRecord;
351  ast_record* spThatRecord;
352  aint* uipThatRecordIndex = (aint*)vpVecPop(spCtx->vpVecThatStack);
353  if(!uipThatRecordIndex){
354  XTHROW(spCtx->spException, "AST that stack is empty");
355  }
356  spThatRecord = (ast_record*)vpVecAt(spCtx->vpVecRecords, *uipThatRecordIndex);
357  if(!spThatRecord){
358  XTHROW(spCtx->spException, "requested AST record out of range");
359  }
360  sRecord.bIsUdt = bIsUdt;
361  sRecord.cpName = spThatRecord->cpName;
362  sRecord.uiIndex = uiIndex;
363  sRecord.uiPhraseLength = uiPhraseLength;
364  sRecord.uiPhraseOffset = uiPhraseOffset;
365  sRecord.uiState = ID_AST_POST;
366  sRecord.uiThatRecord = spThatRecord->uiThisRecord;
367  sRecord.uiThisRecord = uiVecLen(spCtx->vpVecRecords);
368  vpVecPush(spCtx->vpVecRecords, (void*)&sRecord);
369  // refresh the pointer after the push (it is stale if the vector grows)
370  spThatRecord = (ast_record*)vpVecAt(spCtx->vpVecRecords, *uipThatRecordIndex);
371  if(!spThatRecord){
372  XTHROW(spCtx->spException, "requested AST record out of range");
373  }
374  spThatRecord->uiPhraseLength = uiPhraseLength;
375  spThatRecord->uiThatRecord = sRecord.uiThisRecord;
376  }else{
377  if(uiRecordCount < uiVecLen(spCtx->vpVecRecords)){
378  if(!vpVecPopi(spCtx->vpVecRecords, uiRecordCount)){
379  XTHROW(spCtx->spException, "AST record stack should not be empty");
380  }
381  if(!vpVecPop(spCtx->vpVecThatStack)){
382  XTHROW(spCtx->spException, "AST \"that\" record stack should not be empty");
383  }
384  }
385  }
386 }
387 
392 void vAstOpOpen(void* vpCtx){
393  ast* spCtx = (ast*)vpCtx;
394  aint uiRecordCount = uiVecLen(spCtx->vpVecRecords);
395  vpVecPush(spCtx->vpVecOpenStack, (void*)&uiRecordCount);
396 }
397 
403 void vAstOpClose(void* vpCtx, aint uiState){
404  ast* spCtx = (ast*)vpCtx;
405  aint* uipRecordCount = (aint*)vpVecPop(spCtx->vpVecOpenStack);
406  if(!uipRecordCount){
407  XTHROW(spCtx->spException, "AST open stack empty");
408  }
409  aint uiRecordCount = *uipRecordCount;
410 
411  if(uiState == ID_NOMATCH){
412  if(uiRecordCount < uiVecLen(spCtx->vpVecRecords)){
413  if(!vpVecPopi(spCtx->vpVecRecords, uiRecordCount)){
414  XTHROW(spCtx->spException, "AST record stack empty");
415  }
416  }
417  }
418 }
419 #endif /* APG_AST */
lib.h
This header "#include"s all publid lib headers and other standard headers needed by most objects.
ast_record::uiThatRecord
aint uiThatRecord
The matching record number. That is, if uiThisRecord the number of the record that opens the rule,...
Definition: ast.h:46
bAstValidate
abool bAstValidate(void *vpCtx)
Validate an AST context pointer.
Definition: ast.c:104
apg.h
The APG header file.
ast_data::uiPhraseOffset
aint uiPhraseOffset
Definition: ast.h:72
vAstSetRuleCallback
void vAstSetRuleCallback(void *vpCtx, aint uiRuleIndex, ast_callback pfnCallback)
Define a callback function for a single rule on the AST.
Definition: ast.c:243
parserp.h
Private header for the SABNF parser.
ast_info::acpString
const achar * acpString
The parsed input string.
Definition: ast.h:58
ast_info::uiRuleCount
aint uiRuleCount
The number of rules.
Definition: ast.h:60
ast_info::uiStringLength
aint uiStringLength
The number of characters in the input string.
Definition: ast.h:62
ast::vpVecThatStack
void * vpVecThatStack
Pointer to the vector holding a LIFO stack to match up and down node records.
Definition: astp.h:52
ast_data::uiStringLength
aint uiStringLength
Definition: ast.h:71
vVecDtor
void vVecDtor(void *vpCtx)
The vector component destructor.
Definition: vector.c:161
ast_record::uiPhraseLength
aint uiPhraseLength
The number of characters in the matched phrase.
Definition: ast.h:49
ID_AST_POST
#define ID_AST_POST
indicates post-node-traversal AST callback state (up the tree)
Definition: parser.h:92
ast_info::uiUdtCount
aint uiUdtCount
The number of UDTs.
Definition: ast.h:61
ID_AST_OK
#define ID_AST_OK
normal AST callback function return
Definition: parser.h:93
ast_data::spException
exception * spException
Use but don't alter. Use to throw exceptions to the AST catch block.
Definition: ast.h:78
vExContext
void vExContext()
Handles bad context pointers.
Definition: exception.c:126
ID_AST_PRE
#define ID_AST_PRE
indicates pre-node-traversal AST callback state (down the tree)
Definition: parser.h:91
ast_data
Input data to the AST callback functions.
Definition: ast.h:69
ast_data::cpName
const char * cpName
Name of the rule or UDT.
Definition: ast.h:75
ast_record::cpName
const char * cpName
Name of the rule or UDT of this record.
Definition: ast.h:43
vAstTranslate
void vAstTranslate(void *vpCtx, void *vpUserData)
Do a depth-first traversal of the AST with user-defined callback functions to translate the AST recor...
Definition: ast.c:165
ast_data::uiPhraseLength
aint uiPhraseLength
Definition: ast.h:73
ast::vpVecOpenStack
void * vpVecOpenStack
Pointer to a vector LIFO stack of open rule nodes.
Definition: astp.h:53
vpVecAt
void * vpVecAt(void *vpCtx, aint uiIndex)
Get a the indexed vector element. The vector is not altered.
Definition: vector.c:362
ast_data::uiIndex
aint uiIndex
Index of the rule or UDT.
Definition: ast.h:76
vAstInfo
void vAstInfo(void *vpCtx, ast_info *spInfo)
Retrieve basic information about the AST object.
Definition: ast.c:137
ast_record
Format of an AST record.
Definition: ast.h:42
ast::spParser
parser * spParser
Pointer to the parent parser.
Definition: astp.h:50
ast::pfnRuleCallbacks
ast_callback * pfnRuleCallbacks
An array of rule name call back functions.
Definition: astp.h:54
XTHROW
#define XTHROW(ctx, msg)
Exception throw macro.
Definition: exception.h:67
vpVecPop
void * vpVecPop(void *vpCtx)
Pops one element from the end of the array.
Definition: vector.c:250
vAstOpOpen
void vAstOpOpen(void *vpCtx)
Called in preparation for a downward traversal of an RNM or UDT node.
Definition: ast.c:392
aint
uint_fast32_t aint
The APG parser's unsigned integer type.
Definition: apg.h:79
spMemException
exception * spMemException(void *vpCtx)
Get a pointer to this memory objects's exception handler.
Definition: memory.c:174
vAstDtor
void vAstDtor(void *vpCtx)
Definition: ast.c:81
vAstOpClose
void vAstOpClose(void *vpCtx, aint uiState)
Called to finish up after an upward traversal of an RNM or UDT node.
Definition: ast.c:403
vpMemAlloc
void * vpMemAlloc(void *vpCtx, aint uiBytes)
Allocates memory.
Definition: memory.c:196
uiVecLen
aint uiVecLen(void *vpCtx)
Get the vector length. That is, the number of elements on the vector.
Definition: vector.c:385
vpVecCtor
void * vpVecCtor(void *vpMem, aint uiElementSize, aint uiInitialAlloc)
The vector object constructor.
Definition: vector.c:118
ast
The AST object context. Holds the object's state.
Definition: astp.h:46
ast_record::bIsUdt
abool bIsUdt
True if this record is for a UDT.
Definition: ast.h:51
ast_data::uiState
aint uiState
Definition: ast.h:74
ast_info
All the information a user needs to write a custom AST translator.
Definition: ast.h:57
ast::spException
exception * spException
Pointer to an exception structure for reporting fatal errors back to the parser's catch block scope.
Definition: astp.h:48
vMemFree
void vMemFree(void *vpCtx, const void *vpData)
Free memory previously allocated with vpMemAlloc().
Definition: memory.c:226
ast::vpVecRecords
void * vpVecRecords
Pointer to the vector holding the AST records (two for each saved node).
Definition: astp.h:51
ast_callback
aint(* ast_callback)(ast_data *spData)
The prototype for AST translation callback functions.
Definition: ast.h:91
ID_AST_SKIP
#define ID_AST_SKIP
on return from AST callback, skip all nodes below (ignored on return from ID_AST_POST state)
Definition: parser.h:94
ast_info::uiRecordCount
aint uiRecordCount
The number of records (two for each node of the AST, one down traversal, one up.)
Definition: ast.h:63
ID_MATCH
#define ID_MATCH
indicates a matched phrase parser state on return from parse tree below this node
Definition: parser.h:73
ast_record::uiState
aint uiState
ID_AST_PRE if the current record opens the rule, ID_AST_POST if the current record closes the rule.
Definition: ast.h:50
ast_record::uiThisRecord
aint uiThisRecord
The record number.
Definition: ast.h:45
APG_UNDEFINED
#define APG_UNDEFINED
Definition: apg.h:318
vAstClear
void vAstClear(void *vpCtx)
Clear the AST records for reuse of the AST object.
Definition: ast.c:118
ast_data::acpString
const achar * acpString
Definition: ast.h:70
vpVecFirst
void * vpVecFirst(void *vpCtx)
Get the first element one the vector. The vector is not altered.
Definition: vector.c:326
ast_info::spRecords
ast_record * spRecords
The list of records in the order of a depth-first traversal of the AST.
Definition: ast.h:59
ast_data::bIsUdt
abool bIsUdt
True if this record is for a UDT. False if it is for a rule.
Definition: ast.h:77
APG_TRUE
#define APG_TRUE
Definition: apg.h:291
vpAstCtor
void * vpAstCtor(void *vpParserCtx)
The AST object constructor.
Definition: ast.c:51
ast::pfnUdtCallbacks
ast_callback * pfnUdtCallbacks
An array of UDT call back functions.
Definition: astp.h:55
ast_data::vpUserData
void * vpUserData
Definition: ast.h:80
abool
uint8_t abool
abool is the APG bool type.
Definition: apg.h:140
ast::vpValidate
const void * vpValidate
A "magic number" indicating a valid, initialized AST object.
Definition: astp.h:47
vpVecPopi
void * vpVecPopi(void *vpCtx, aint uiIndex)
Pops the element at the given zero-based index and all higher indexes.
Definition: vector.c:306
ID_NOMATCH
#define ID_NOMATCH
indicates that no phrase was matched on return from parse tree below this node
Definition: parser.h:74
vAstSetUdtCallback
void vAstSetUdtCallback(void *vpCtx, aint uiUdtIndex, ast_callback pfnCallback)
Define a callback function for a single UDT on the AST.
Definition: ast.c:266
vAstRuleOpen
void vAstRuleOpen(void *vpCtx, aint uiRuleIndex, aint uiPhraseOffset)
Called by parser's RNM operator before downward traversal.
Definition: ast.c:286
astp.h
Private header file for the AST functions.
ast_record::uiPhraseOffset
aint uiPhraseOffset
The offset into the input string to the first character of the matched phrase.
Definition: ast.h:48
ast_record::uiIndex
aint uiIndex
Index of the rule or UDT of this record.
Definition: ast.h:44
vpVecPush
void * vpVecPush(void *vpCtx, void *vpElement)
Adds one element to the end of the array.
Definition: vector.c:193
vAstRuleClose
void vAstRuleClose(void *vpCtx, aint uiRuleIndex, aint uiState, aint uiPhraseOffset, aint uiPhraseLength)
Called by parser's RNM operator after upward traversal.
Definition: ast.c:329
bParserValidate
abool bParserValidate(void *vpCtx)
Validate the context pointer of a parser.
Definition: parser.c:422
vVecClear
void vVecClear(void *vpCtx)
Clears all used elements in a vector component.
Definition: vector.c:420
APG_FALSE
#define APG_FALSE
Definition: apg.h:292
APG Version 7.0 is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.