💾 Archived View for runjimmyrunrunyoufuckerrun.com › src › foreign › pmw › src › preprocess.c captured on 2021-12-17 at 13:26:06.
View Raw
More Information
-=-=-=-=-=-=-
/*************************************************
- The PMW Music Typesetter - 3rd incarnation *
- ************************************************/
/* Copyright (c) Philip Hazel, 1991 - 2020 */
/* Written by Philip Hazel, starting November 1991 */
/* This file last modified: December 2020 */
/* This file contains code for handling "preprocessing" functions. */
#include "pmwhdr.h"
#include "readhdr.h"
/*************************************************
- Deal with pre-processing directive *
- ************************************************/
/* We enter with read_ptr pointing to the first letter of the directive's name,
so we are guaranteed to read a word. We can use normal item reading routines,
but must take care not to do so at the end of a line.
Arguments: none
Returns: nothing
void
pre_process(void)
{
next_word();
sigchNL();
DEBUG(("pre_process(%s) entered\n", read_word));
/* Deal with "if" */
if (Ustrcmp(read_word, "if") == 0)
{
int OK;
if (read_skipdepth > 0)
{
read_skipdepth++;
read_chptr = read_endptr;
read_ch = '\n';
DEBUG(("pre_process(if) ending\n"));
return;
}
for (;;)
{
OK = TRUE;
read_word[0] = 0;
if (read_ch != '\n') next_word();
if (Ustrcmp(read_word, "not") == 0)
{
OK = !OK;
sigchNL();
read_word[0] = 0;
if (read_ch != '\n') next_word();
}
if (read_word[0] == 0)
{ error_moan(ERR10, "Word"); break; }
else
{
int i;
if (Ustrcmp(read_word, "score") == 0)
{
for (i = 0; i < STAVE_BITVEC_SIZE; i++)
if (curmovt->staves[i] != ~0u) { OK = !OK; break; }
}
else if (Ustrcmp(read_word, "part") == 0)
{
for (i = 0; i < STAVE_BITVEC_SIZE; i++)
if (curmovt->staves[i] != ~0u) break;
if (i >= STAVE_BITVEC_SIZE) OK = !OK;
}
/* For a stave list, we can't use a common routine with other directives
because we mustn't stray over the end of the line! */
else if (Ustrcmp(read_word, "staff") == 0 || Ustrcmp(read_word, "stave") == 0 ||
Ustrcmp(read_word, "staves") == 0)
{
usint map[STAVE_BITVEC_SIZE];
mac_initstave(map, 0);
mac_setstave(map, 0); /* Staff zero is always selected */
sigchNL();
while (isdigit(read_ch))
{
int s = read_integer(FALSE);
int t = s;
sigchNL();
if (read_ch == '-')
{
next_ch();
sigchNL();
if (!isdigit(read_ch))
{
error_moan(ERR10, "Number");
t = s;
}
else t = read_integer(FALSE);
}
if (t < s) error_moan(ERR21);
else if (t > MAX_STAVE) error_moan(ERR22, MAX_STAVE+1);
else
{
for (i = s; i <= t; i++) mac_setstave(map, i);
}
sigchNL();
if (read_ch == ',')
{
next_ch();
sigchNL();
}
}
for (i = 0; i < STAVE_BITVEC_SIZE; i++)
if (map[i] != curmovt->staves[i]) { OK = !OK; break; }
}
/* Deal with definition test */
else if (Ustrcmp(read_word, "undef") == 0)
{
sigchNL();
read_word[0] = 0;
if (read_ch != '\n') next_word();
if (read_word[0] == 0) error_moan(ERR10, "Macro name"); else
{
if (Tree_Search(define_tree, read_word) != NULL) OK = !OK;
}
}
/* Test if any format is set */
else if (Ustrcmp(read_word, "format") == 0)
{
if (main_format[0] == 0) OK = !OK;
}
/* Not recognized; take as format word */
else
{
if (Ustrcmp(read_word, main_format) != 0) OK = !OK;
else main_format_tested = TRUE;
}
}
/* See if the next thing is "or"; if not and if not newline, error.
Otherwise, if it's "or" and OK == FALSE, let the loop continue. */
sigchNL();
if (read_ch == '\n') break;
read_word[0] = 0;
next_word();
if (Ustrcmp(read_word, "or") != 0) { error_moan(ERR10, "\"or\""); break; }
if (OK) break;
sigchNL();
}
/* Decision taken; act appropriately */
if (OK) read_okdepth++; else read_skipdepth++;
DEBUG(("pre_process(if) ending\n"));
return;
}
/* Deal with "else" */
if (Ustrcmp(read_word, "else") == 0)
{
if (read_skipdepth <= 1)
{
if (read_skipdepth == 1)
{
read_skipdepth--;
read_okdepth++;
}
else if (read_okdepth > 0)
{
read_skipdepth++;
read_okdepth--;
}
else error_moan(ERR17, "\"*else\"");
}
DEBUG(("pre_process(else) ending\n"));
return;
}
/* Deal with "fi" */
if (Ustrcmp(read_word, "fi") == 0)
{
if (read_skipdepth > 0) read_skipdepth--; else
if (read_okdepth > 0) read_okdepth--;
else error_moan(ERR17, "*fi");
DEBUG(("pre_process(fi) ending\n"));
return;
}
/* Others are only looked at when not skipping */
if (read_skipdepth > 0)
{
DEBUG(("pre_process() ending -- skipping\n"));
return;
}
/* Deal with defining names */
if (Ustrcmp(read_word, "define") == 0)
{
if (read_ch != '\n') /* Don't use next_word(), because it */
{ /* converts to lower case */
int i = 0;
sigch();
if (isalnum(read_ch))
{
do
{
if (i >= WORD_BUFFERSIZE - 1)
error_moan(ERR136, "Macro name", WORD_BUFFERSIZE - 1); /* Hard */
read_word[i++] = read_ch;
next_ch();
}
while (isalnum(read_ch));
}
read_word[i] = 0;
}
if (read_word[0] == 0) error_moan(ERR10, "Macro name"); else
{
int len;
int argcount = 0;
uschar *args[MAX_MACROARGS];
uschar arg[MAX_MACRODEFAULT + 1];
tree_node *p = store_Xget(sizeof(tree_node));
p->name = store_Xget(Ustrlen(read_word) + 1);
Ustrcpy(p->name, read_word);
if (*(--read_chptr) == '(')
{
while (read_chptr < read_endptr && *read_chptr != ')')
{
int bracount = 0;
BOOL inquotes = FALSE;
uschar *s = arg;
if (argcount >= MAX_MACROARGS)
error_moan(ERR137, MAX_MACROARGS); /* Hard */
while (++read_chptr < read_endptr &&
((*read_chptr != ',' && *read_chptr != ')') ||
bracount > 0 || inquotes))
{
int ch = *read_chptr;
if (s - arg >= MAX_MACRODEFAULT)
error_moan(ERR136, "Macro default argument", MAX_MACRODEFAULT); /* Hard */
if (ch == '&') *s++ = *(++read_chptr); else
{
if (ch == '\"') inquotes = !inquotes;
if (!inquotes)
{
if (ch == '(') bracount++;
else if (ch == ')') bracount--;
}
*s++ = ch;
}
}
if (read_chptr >= read_endptr) error_moan(ERR99);
if (s - arg > 0)
{
uschar *ss = store_Xget(s - arg + 1);
*s = 0;
Ustrcpy(ss, arg);
args[argcount++] = ss;
}
else args[argcount++] = NULL;
}
if (*read_chptr == ')') read_chptr++;
}
while (*read_chptr == ' ' || *read_chptr == '\t') read_chptr++;
while (read_endptr[-1] == ' ' || read_endptr[-1] == '\t') read_endptr--;
len = read_endptr - read_chptr;
if (len <= 0 && argcount == 0) p->data = NULL; else
{
int i;
uschar *pp = store_Xget(len + 1);
macrostr *mm =
store_Xget((int)sizeof(macrostr) + (argcount-1)*((int)sizeof(uschar *)));
mm->argcount = argcount;
p->data = (uschar *)mm;
mm->text = pp;
while (len-- > 0) *pp++ = *read_chptr++;
*pp = 0;
for (i = 0; i < argcount; i++) mm->args[i] = args[i];
}
if (!Tree_InsertNode(&define_tree, p)) error_moan(ERR14, read_word);
read_chptr = read_endptr;
read_ch = '\n';
}
}
/* Deal with included files */
else if (Ustrcmp(read_word, "include") == 0)
{
FILE *f;
if (read_filestackptr >= MAX_INCLUDE)
{ error_moan(ERR15, MAX_INCLUDE); return; }
if (read_ch == '\n' || !read_plainstring())
{ error_moan(ERR10, "File name in quotes"); return; }
sys_relativize(read_word, WORD_BUFFERSIZE);
f = Ufopen(read_word, "r");
if (f == NULL) error_moan(ERR4, read_word, strerror(errno)); /* Hard error */
/* Stack the current variables and replace with new ones. The
size is added to the total size expected. */
read_filestack[read_filestackptr].file = input_file;
read_filestack[read_filestackptr].filename = main_filename;
read_filestack[read_filestackptr].linenumber = read_linenumber;
read_filestack[read_filestackptr++].okdepth = read_okdepth;
input_file = f;
read_okdepth = 0;
read_linenumber = 0;
main_filename = store_copystring(read_word);
DEBUG(("including file %s\n", main_filename));
}
/* Deal with comment */
else if (Ustrcmp(read_word, "comment") == 0)
{
uschar *s = read_chptr - 1;
fprintf(stderr, "%s\n", s);
read_chptr = read_endptr;
read_ch = '\n';
}
/* Else unknown preprocessing directive */
else
{
error_moan(ERR13, read_word);
read_chptr = read_endptr;
read_ch = '\n';
}
/* Test for extraneous characters */
sigchNL();
if (read_ch != '\n') error_moan(ERR16, "Extraneous characters ignored");
DEBUG(("pre_process() ending\n"));
}
/* End of preprocess.c */