``` %%writefile spn.l %option noyywrap %{ #include #include #include #define MAX_PATH_LEN 255 #define MAX_COMP_LEN 14 char output[MAX_PATH_LEN + 1] = ""; // Store the output output int portable = 0; // 1 if path starts with '/', 0 otherwise void error(const char *message); %} %% [ \t]+ { /* Ignore extra lead or trailing spaces */ } ^"/" { portable = 1; strcpy(output, "/"); } ".." { if (strlen(output) == 0 || strcmp(output, "/") == 0) { error("malformed pathname"); } char *last_slash = strrchr(output, '/'); if (last_slash != NULL) { *last_slash = '\0'; // Remove last component if (strlen(output) == 0) { strcpy(output, "/"); // Change to root if now empty } } else { error("malformed pathname"); } } "/"+ { /* Ignore extra '/' */ } "." { /* Ignore '.' */ } [a-zA-Z0-9.]+ { if (portable && strlen(yytext) > MAX_COMP_LEN) { error("component too long"); } if (!portable && strlen(output) + strlen(yytext) + 1 > MAX_PATH_LEN) { error("pathname too long"); } if (strlen(output) > 0 && output[strlen(output) - 1] != '/') { strcat(output, "/"); } strcat(output, yytext); } [^a-zA-Z0-9./\n\r]+ { error("invalid character"); } [\r\n]+ { if (strlen(output) > 0 && output[strlen(output) - 1] == '/') { output[strlen(output) - 1] = '\0'; // trailing '/' } if (strlen(output) > 0) { printf("%s", output); // Print path without \n } output[0] = '\0'; portable = 0; printf("%s", yytext); } %% void error(const char *message) { fprintf(stderr, "%s\n", message); exit(1); } int main(void) { yylex(); printf("\n"); return 0; } ```