%{
/* ========================================================================== */
/* Copyright (c) 2018-2021 Michael Baeuerle
 *
 * All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, and/or sell copies of the Software, and to permit persons
 * to whom the Software is furnished to do so, provided that the above
 * copyright notice(s) and this permission notice appear in all copies of
 * the Software and that both the above copyright notice(s) and this
 * permission notice appear in supporting documentation.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
 * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Except as contained in this notice, the name of a copyright holder
 * shall not be used in advertising or otherwise to promote the sale, use
 * or other dealings in this Software without prior written authorization
 * of the copyright holder.
 *
 * SPDX-License-Identifier: ICU
 */


/* ========================================================================== */
/* Code copied verbatim by lexer */

#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "hfp_lexer.h"
#include "hfp_parser.h"

#define yyerror cl_hfp_yyerror
#define yylex cl_hfp_yylex

static void msg(const char *, const char *);
static char *my_strdup(const char *);

%}

   /* Leave type of yytext undefined (the HP-UX lex fails with %pointer) */


%%
   /* Rules section */

   /* Local variables */
   char  sbuf[81];
   size_t  i;

\x0  {
     /* Ignore NUL */
      msg("NUL (ignored)", NULL);
   }

\\\x0  {
     /* Ignore \NUL (<obs-qp>) */
      msg("\\NUL (ignored)", NULL);
   }

\\\r|\\\n  {
     /* Ignore \LF and \CR (<obs-qp>) */
      msg("\\CR or \\LF (ignored)", NULL);
   }

\r|\n  {
     /* Ignore LF and CR (folding) */;
      msg("CR or LF (ignored)", NULL);
   }

\t  {
      msg("Tab", yytext);
      yylval.str = my_strdup(yytext);
      return (T_HT);
   }

[ ]  {
      msg("Space", yytext);
      yylval.str = my_strdup(yytext);
      return (T_SP);
   }

\(|\)  {
      msg("Parenthesis", yytext);
      yylval.str = my_strdup(yytext);
      return ((int) yytext[0]);
   }

[:]  {
      msg("Colon", yytext);
      yylval.str = my_strdup(yytext);
      return ((int) yytext[0]);
   }

[=]  {
      msg("Equal", yytext);
      yylval.str = my_strdup(yytext);
      return ((int) yytext[0]);
   }

\\  {
      msg("Backslash", yytext);
      yylval.str = my_strdup(yytext);
      return (T_BS);
   }

^[C|c][A|a][N|n][C|c][E|e][L|l]-[L|l][O|o][C|c][K|k]/:  {
      msg("Field name", yytext);
      yylval.str = my_strdup(yytext);
      return (T_LOCK);
   }

^[C|c][A|a][N|n][C|c][E|e][L|l]-[K|k][E|e][Y|y]/:  {
      msg("Field name", yytext);
      yylval.str = my_strdup(yytext);
      return (T_KEY);
   }

[-/A-Za-z0-9]+/:  {
      msg("Scheme", yytext);
      yylval.str = my_strdup(yytext);
      i = 0;
      while (yylval.str[i])
      {
         yylval.str[i] = tolower(yylval.str[i]);
         ++i;
      }
      return (T_SCHEME);
   }

[+/A-Za-z0-9]{4}  {
      msg("Base64 quad", yytext);
      yylval.str = my_strdup(yytext);
      return (T_BASE64Q);
   }

[+/A-Za-z0-9]  {
      msg("Base64 char", yytext);
      yylval.str = my_strdup(yytext);
      return (T_BASE64);
   }

[!]|["]|[#$%&'*+,]|[-]|[./0-9;<>?@A-Z[]|[]]|\^|[_`a-z{|}~]  {
      /*
       * Should match a character of <ctext> as defined in RFC 5322:
       * https://tools.ietf.org/html/rfc5322#section-3.2.2
       * Exceptions: ':' and '=' have their own tokens
       *
       * The SysV lex of HP-UX 11.11 has problems with the following characters
       * in a bracket expression:
       *    "  Does not lose its special meaning in some cases
       *    ]  (as first character) is not detected if more characters follow
       * The bracket expressions '["]' and '[]]' are tested to work
       */
      msg("Ctext char", yytext);
      yylval.str = my_strdup(yytext);
      return (T_CTEXT);
   }

\x1|\x2|\x3|\x4|\x5|\x6|\x7|\x8|\xB|\xC|\xE|\xF|\x10|\x11|\x12|\x13|\x14|\x15|\x16|\x17|\x18|\x19|\x1A|\x1B|\x1C|\x1D|\x1E|\x1F  {
      msg("Control char", NULL);
      yylval.str = my_strdup(yytext);
      return (T_OBS_NO_WS_CTL);
   }

.  {
      snprintf(sbuf, 81, "Unknown token '%s'", yytext);
      yyerror(sbuf);
      yylval.str = my_strdup(yytext);
      return (T_ERROR);
   }


%%
/* ========================================================================== */
/* Code generated by lexer */

/* This is called if there is no more input */
int yywrap(void)
{
    /* Terminate */
    return (1);
}


/* Print debug message */
static void msg(const char *s1, const char *s2)
{
   if (cl_hfp_debugmode)
   {
      if (NULL == s2)
         fprintf(stderr, "Lexer  : %s\n", s1);
      else
         fprintf(stderr, "Lexer  : %s '%s'\n", s1, s2);
   }

   return;
}


/* With POSIX.1-2001 strdup() requires XSI-Extension */
char *my_strdup(const char *s)
{
   char *res = (char *) malloc(strlen(s) + (size_t) 1);

   if (NULL != res)
      strcpy(res, s);

   /* errno == ENOMEM is already set by malloc() if allocation failed */

   return (res);
}


/* EOF */
